mirror of
https://github.com/Luzifer/aoc2019.git
synced 2024-12-22 05:51:16 +00:00
Partial: Day 18
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
84e8a9afa0
commit
2820e2d148
3 changed files with 461 additions and 0 deletions
320
day18.go
Normal file
320
day18.go
Normal file
|
@ -0,0 +1,320 @@
|
||||||
|
package aoc2019
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"math"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type day18TileType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
day18TileTypeWall day18TileType = iota
|
||||||
|
day18TileTypeFloor
|
||||||
|
day18TileTypeDoor
|
||||||
|
day18TileTypeKey
|
||||||
|
day18TileTypeActor
|
||||||
|
)
|
||||||
|
|
||||||
|
type day18Tile struct {
|
||||||
|
X, Y int
|
||||||
|
Type day18TileType
|
||||||
|
KeyLockID string
|
||||||
|
|
||||||
|
distFromActor int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *day18Tile) updateBFSDistance(grid day18Grid, dist int64, wg *sync.WaitGroup) {
|
||||||
|
defer wg.Done()
|
||||||
|
if d.distFromActor < dist {
|
||||||
|
// Do not update tiles which dist has been set already
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set distance
|
||||||
|
d.distFromActor = dist
|
||||||
|
|
||||||
|
// Seek adjacent tiles and update them too
|
||||||
|
for _, t := range []*day18Tile{
|
||||||
|
grid[grid.key(d.X-1, d.Y)],
|
||||||
|
grid[grid.key(d.X+1, d.Y)],
|
||||||
|
grid[grid.key(d.X, d.Y-1)],
|
||||||
|
grid[grid.key(d.X, d.Y+1)],
|
||||||
|
} {
|
||||||
|
if t.Type == day18TileTypeWall || t.Type == day18TileTypeDoor {
|
||||||
|
// Doors and walls are inaccessible objects and therefore
|
||||||
|
// immediately stop distance progressing
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go t.updateBFSDistance(grid, dist+1, wg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type day18Grid map[string]*day18Tile
|
||||||
|
|
||||||
|
func (d day18Grid) accessibleKeys() []string {
|
||||||
|
var keys []string
|
||||||
|
|
||||||
|
for _, key := range d.getTilesByType(day18TileTypeKey) {
|
||||||
|
if key.distFromActor < math.MaxInt64 {
|
||||||
|
keys = append(keys, key.KeyLockID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(keys)
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d day18Grid) bounds() (minX, minY, maxX, maxY int) {
|
||||||
|
minX, minY = math.MaxInt64, math.MaxInt64
|
||||||
|
|
||||||
|
for _, t := range d {
|
||||||
|
if t.X < minX {
|
||||||
|
minX = t.X
|
||||||
|
}
|
||||||
|
if t.Y < minY {
|
||||||
|
minY = t.Y
|
||||||
|
}
|
||||||
|
if t.X > maxX {
|
||||||
|
maxX = t.X
|
||||||
|
}
|
||||||
|
if t.Y > maxY {
|
||||||
|
maxY = t.Y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d day18Grid) clone() day18Grid {
|
||||||
|
var out = make(day18Grid)
|
||||||
|
|
||||||
|
for key, tile := range d {
|
||||||
|
var tmpTile = &day18Tile{}
|
||||||
|
*tmpTile = *tile
|
||||||
|
out[key] = tmpTile
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d day18Grid) getKeyByID(id string) *day18Tile {
|
||||||
|
for _, key := range d.getTilesByType(day18TileTypeKey) {
|
||||||
|
if key.KeyLockID == id {
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d day18Grid) getPathDistances(path string, shortest *int64) (map[string]int64, error) {
|
||||||
|
var (
|
||||||
|
dist int64
|
||||||
|
// Always work on a clone and leave the original grid intact
|
||||||
|
grid = d.clone()
|
||||||
|
out = make(map[string]int64)
|
||||||
|
)
|
||||||
|
|
||||||
|
grid.updateBFSDistance()
|
||||||
|
|
||||||
|
// Apply movements
|
||||||
|
for _, c := range path {
|
||||||
|
key := grid.getKeyByID(string(c))
|
||||||
|
moveDist, err := grid.move(key.X, key.Y)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "Unable to move")
|
||||||
|
}
|
||||||
|
dist += moveDist
|
||||||
|
grid.updateBFSDistance()
|
||||||
|
|
||||||
|
if dist >= *shortest {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remainingKeys := grid.getTilesByType(day18TileTypeKey)
|
||||||
|
|
||||||
|
if len(remainingKeys) == 0 {
|
||||||
|
fmt.Printf("DBG %s = %d\n", path, dist)
|
||||||
|
out[path] = dist
|
||||||
|
if dist < *shortest {
|
||||||
|
*shortest = dist
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(remainingKeys, func(i, j int) bool { return remainingKeys[i].distFromActor < remainingKeys[j].distFromActor })
|
||||||
|
|
||||||
|
for _, k := range remainingKeys {
|
||||||
|
if k.distFromActor == math.MaxInt64 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
recDists, err := d.getPathDistances(path+k.KeyLockID, shortest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, dist := range recDists {
|
||||||
|
out[key] = dist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d day18Grid) getTilesByType(t day18TileType) []*day18Tile {
|
||||||
|
var out []*day18Tile
|
||||||
|
|
||||||
|
for _, tile := range d {
|
||||||
|
if tile.Type == t {
|
||||||
|
out = append(out, tile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (day18Grid) key(x, y int) string { return fmt.Sprintf("%d:%d", x, y) }
|
||||||
|
|
||||||
|
func (d day18Grid) move(x, y int) (int64, error) {
|
||||||
|
var (
|
||||||
|
origin = d.getTilesByType(day18TileTypeActor)[0] // There MUST be only one actor
|
||||||
|
target = d[d.key(x, y)]
|
||||||
|
)
|
||||||
|
|
||||||
|
if target.distFromActor == math.MaxInt64 {
|
||||||
|
return 0, errors.New("Distance not initialized / move to unreachable destination")
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.Type == day18TileTypeKey {
|
||||||
|
for _, door := range d.getTilesByType(day18TileTypeDoor) {
|
||||||
|
if door.KeyLockID == strings.ToUpper(target.KeyLockID) {
|
||||||
|
// Unlock door, transform to floor
|
||||||
|
door.Type = day18TileTypeFloor
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the actor
|
||||||
|
target.Type = day18TileTypeActor
|
||||||
|
origin.Type = day18TileTypeFloor
|
||||||
|
|
||||||
|
return target.distFromActor, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d day18Grid) print() {
|
||||||
|
var minX, minY, maxX, maxY = d.bounds()
|
||||||
|
|
||||||
|
for y := minY; y <= maxY; y++ {
|
||||||
|
for x := minX; x <= maxX; x++ {
|
||||||
|
var t = d[d.key(x, y)]
|
||||||
|
switch t.Type {
|
||||||
|
case day18TileTypeActor:
|
||||||
|
fmt.Print("@")
|
||||||
|
case day18TileTypeDoor, day18TileTypeKey:
|
||||||
|
fmt.Print(t.KeyLockID)
|
||||||
|
case day18TileTypeFloor:
|
||||||
|
fmt.Print(".")
|
||||||
|
case day18TileTypeWall:
|
||||||
|
fmt.Print("\u2588")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d day18Grid) updateBFSDistance() {
|
||||||
|
// Reset distances
|
||||||
|
for _, t := range d {
|
||||||
|
t.distFromActor = math.MaxInt64
|
||||||
|
}
|
||||||
|
|
||||||
|
wg := new(sync.WaitGroup)
|
||||||
|
wg.Add(1)
|
||||||
|
d.getTilesByType(day18TileTypeActor)[0].updateBFSDistance(d, 0, wg)
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func day18ReadGrid(raw []byte) day18Grid {
|
||||||
|
var (
|
||||||
|
out = make(day18Grid)
|
||||||
|
x, y int
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, c := range raw {
|
||||||
|
var t = &day18Tile{X: x, Y: y, KeyLockID: string(c)}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case c == '\n':
|
||||||
|
x, y = 0, y+1
|
||||||
|
continue
|
||||||
|
case c == '#':
|
||||||
|
t.Type = day18TileTypeWall
|
||||||
|
case c == '.':
|
||||||
|
t.Type = day18TileTypeFloor
|
||||||
|
case c == '@':
|
||||||
|
t.Type = day18TileTypeActor
|
||||||
|
case 'a' <= c && c <= 'z':
|
||||||
|
t.Type = day18TileTypeKey
|
||||||
|
case 'A' <= c && c <= 'Z':
|
||||||
|
t.Type = day18TileTypeDoor
|
||||||
|
}
|
||||||
|
|
||||||
|
out[out.key(x, y)] = t
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func solveDay18Part1(inFile string) (int64, error) {
|
||||||
|
raw, err := ioutil.ReadFile(inFile)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Wrap(err, "Unable to read file")
|
||||||
|
}
|
||||||
|
|
||||||
|
grid := day18ReadGrid(bytes.TrimSpace(raw))
|
||||||
|
|
||||||
|
grid.print()
|
||||||
|
|
||||||
|
// Calculate max heuristic distance by using always using shortest
|
||||||
|
// single distance which will not be the shortest total distance
|
||||||
|
// but set an upper limit for the heuristic
|
||||||
|
cgrid := grid.clone()
|
||||||
|
cgrid.updateBFSDistance()
|
||||||
|
var minDist int64
|
||||||
|
for len(cgrid.accessibleKeys()) > 0 {
|
||||||
|
keys := cgrid.getTilesByType(day18TileTypeKey)
|
||||||
|
sort.Slice(keys, func(i, j int) bool { return keys[i].distFromActor < keys[j].distFromActor })
|
||||||
|
d, err := cgrid.move(keys[0].X, keys[0].Y)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Wrap(err, "Failed to move")
|
||||||
|
}
|
||||||
|
minDist += d
|
||||||
|
cgrid.updateBFSDistance()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Shortest distance for heuristic: %d", minDist)
|
||||||
|
|
||||||
|
dists, err := grid.getPathDistances("", &minDist)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Wrap(err, "Unable to determine distances")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%#v\n", dists)
|
||||||
|
|
||||||
|
return minDist, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func solveDay18Part2(inFile string) (int64, error) { return 0, errors.New("Not implemented") }
|
81
day18_input.txt
Normal file
81
day18_input.txt
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#################################################################################
|
||||||
|
#.#...#.....#...............#.....#v....#.........#p....#...#...................#
|
||||||
|
#.#.#.#.#.#.#M#############.#.###.#####.#####.###.#.###.#.#.#################.#.#
|
||||||
|
#..n#...#.#...#.#...........#...#.......#.....#.....#.#...#...#.......#...#...#.#
|
||||||
|
#########.#####.#.###########.#.#######.#.###########.#######.#C#####.#.#.#.###.#
|
||||||
|
#.........#.#.....#.........#.#.#.......#...........#...........#...#.#.#...#...#
|
||||||
|
#.#########.#.#########.#####.#W###.###############.###.#########.###.#.#####.###
|
||||||
|
#.Y...#...#...#.......#z......#...#.#...#...#.....#..d#.#.#..x..#...#.#.#...#.#.#
|
||||||
|
#####.#.#.#.###.#.###.#####.#####.#.#.#.#.#.#.###.###.#.#.#.###.#.#.#.#.#.#.#.#.#
|
||||||
|
#.....#.#...#...#.#.#.....#...#...#.#.#.#.#...#.......#...#.#...#.#.....#.#...#.#
|
||||||
|
#.#######.#######.#.#####.#####.#####.#.#.#############.###.#.###.#########.###.#
|
||||||
|
#...#...#.#...#...#.#...#.....#...B...#.#.....#...#.....#...#.#.....#....t#.....#
|
||||||
|
#.#.#.#.#.#.#.#.###.#.#.#####.#.#######.#.###.#.#.###.###.###.#.#####.###.#####N#
|
||||||
|
#.#...#.#...#.#.#.....#...#...#.#...#...#...#.#.#...#.#...#...#...#...#.#...#.#.#
|
||||||
|
#.#####.#####.#.#########.#.###.#.#.#.#.###.#.#.###.###.###.#######.###.###.#.#.#
|
||||||
|
#.#...#.#.......#...#.....#...#...#.#.#.#.#.#...#.#.....#...#.....#.#...#...#.#.#
|
||||||
|
#.#.###.#########.#.#.###.###.#####.#.#.#.#.#####.#######.###.###.#.#.###.###.#.#
|
||||||
|
#.#...#.#...#.....#.#...#...#.#...#.#.#.#.#.#.....#.....#...#.#.#...#...#.#...#.#
|
||||||
|
#.###.#.#.#.#.#####.#.#.#####.#.###.#.###.#.#.###.###.#.###.#.#.#####.#.#J#E###.#
|
||||||
|
#.....#.#.#...#...#.#.#.....#.#.....#...#.#.#.#.......#.#...#.#...#...#...#.....#
|
||||||
|
#######.#.#####.###.#######.#.#########.#.#.#.#########.#.###.#.#.#.#########.###
|
||||||
|
#.......#.#.....#.I.#.....#.............#...#...#.....#.#...#.#.#.#.........#...#
|
||||||
|
#.#######.###.###.#.#####.#.###########.#.###.#.###.###.###.#####.#########.###.#
|
||||||
|
#.......#...#.#...#.....#.#.#.......#...#.#...#.#...#.....#.........#.....#.#...#
|
||||||
|
#.#####.###.#.#.#######.#.###.#####.#.###.#####.#.###.#######.#####.#.###.#.###.#
|
||||||
|
#.#...#...#.#.#.......#.#.....#.#...#...#.#...#.#...#u#.....#...#...#.#.#.#...#.#
|
||||||
|
#.###.#.###.#.#######.#.#######.#.#####.#.#.#.#.#.#.#.#.#.#.###.#####.#.#.###.#.#
|
||||||
|
#...#.#...#.....#.....#.#.....#...#...#.#...#.#.#.#...#.#.#...#.#.....#.#.#...#.#
|
||||||
|
###.#.###.#####.#.#####.#.#.#.#.###.#.#.#####.#.#.#####.#.#.###.#.#####.#.#.###.#
|
||||||
|
#...#...#.......#.#.....#.#.#.#.....#.#.#.....#.#.#.....#.#.#...#.....#.#.#.#..k#
|
||||||
|
#.###.###########.#.#######.#.#######.#.#.#####.###.#####.###.#.#####.#.#.#.#.###
|
||||||
|
#...#...........#.#.....#...#.......#.#.#...#.........#...#...#.#.....#.#...#.#.#
|
||||||
|
###.#.###.###.###.#####.#.#.#######.#.#.###.#.#########.#.#.###.#.#####.#####.#.#
|
||||||
|
#.#.#...#...#.#...#...#.#.#.#.....#.#.#.#.#.#...#.......#.#.#...#...#.....#...#.#
|
||||||
|
#.#.###.###.#.#.###.#.#.#.###.###.###.###.#.#####.#######.#.#.#####.#.#.#.#.###.#
|
||||||
|
#.#.#.....#.#.#.....#g#...#...#.#...#...#.#.......#...#...#.#...#.#.#.#.#.#.....#
|
||||||
|
#.#.#######.#.#######.###.#.###.###.###.#.#########.###.###.###.#.#.#.#.#######.#
|
||||||
|
#...#.....#.#.#.....#.#...#.......#.#...#.....#.......#.#.#...#...#.#.#.......#.#
|
||||||
|
#.###.###.#.#.#.###.#.###########.#.#.###.###.#.#####.#.#.###.#####.#.#######.#.#
|
||||||
|
#.....#.....#...#...#.A...........#.........#.......#.R.....#.......#.......#...#
|
||||||
|
#######################################.@.#######################################
|
||||||
|
#.....#.........#...........#......r#...........#.#...#.............#.......#...#
|
||||||
|
###.###.#.#######.#.#######.#.#####.###.#.#.###.#.#.#.#.#######.###.#.#####.###.#
|
||||||
|
#...#...#.........#...#...#.#.....#.....#.#...#...#.#...#...#...#.#.#.....#.....#
|
||||||
|
#.###.###############.#.###.#.###.#####.#.###.#####.#######.#.###.#.#####.#######
|
||||||
|
#.....#.......#.#.....#...#.#.#...#.....#.#.#.#.....#.......#.#...#.....#.......#
|
||||||
|
#.#######.###.#.#.#######.#.###.#.#######.#.#.#.#########.###.#.#######G#.#####.#
|
||||||
|
#.....#...#.#...#.#.......#...#.#.#.....#...#.#.#.....#..a#...#.#.....#.#i....#.#
|
||||||
|
#####.#.###.###.#.###.#.#####.#.###.###.#####.#.###.#.#.#.#.###.#.###.#.#######.#
|
||||||
|
#...#.#.#.....#.#...#.#.#.....#.....#...#...#.......#...#.#.#.....#.#.........#.#
|
||||||
|
#.#.#.#.#.#####.###.#.###.###########.###.#.#.#############.#.#####.#########.#.#
|
||||||
|
#.#.#.#.#.......#...#.....#.....#...#...#.#.#.#.............#.......#...#.....O.#
|
||||||
|
#.#.#.#.#########.#######.#.###.#.#.###.#.#.###.###########.#########.#.#######.#
|
||||||
|
#.#.#e#.........#.#.....#...#...#.#.....#.#.#...#...........#.......#.#.....#...#
|
||||||
|
###.#.#########.#.#.###.#####P###.#######.#.#.#########.#####.#####.#.#####.#.###
|
||||||
|
#...#.......#...#...#.#.#...#...#...#...#.#...#.......#.#w....#f..#...#...#.#...#
|
||||||
|
#.#.#######.#.#######.#.#.#####.#.#.#.#.#.#.###.#####.###.###.#.#.#####.#.#.#####
|
||||||
|
#.#.#...#...#.........#.#...#...#.#...#.#.#.#.......#.#...#...#.#...#...#.#.#...#
|
||||||
|
#.#.#.###.#######.###.#.#.#.#.###.#####.#.###.#######.#.#######.###.#.###.#.#.#.#
|
||||||
|
#.#...#...#.....#...#.#.#.#...#..o..#...#...#...#...#.#...#...F.#...#...#.#...#.#
|
||||||
|
#.#####.###.###.###.###.#####.#####.#.#.#.#.#.###.#.#.###.#.#####L###.#.#.#####.#
|
||||||
|
#.......#...#.#.#...#.#.....#.....#.#.#.#.#...#...#.#.#...#...#...#...#.#.....#.#
|
||||||
|
#K#######.#.#.#.#.###.#####.#####X###.#.#######.###.#.#.#######.#####.#.#######.#
|
||||||
|
#....j..#.#.#.....#...#.....#...#...#.#.#.......#...#.#.....#...#.S.#.#.........#
|
||||||
|
#######.###.#####.#.###.#####.#.###.#.###.#######.###.#####.#.###.#.#.###########
|
||||||
|
#.....#...#.....#.#...#.......#...#.#...#.....#.#.#.......#.#l....#.#.#...#.....#
|
||||||
|
#T#.#####.#####.#####.#.#########.#.###.#.###.#.#.#####.#.#.#######.#.#.###.###.#
|
||||||
|
#.#.....#.#.....#.....#.#.......#.#.#...#c#.#.#.....#...#.#...Z.#...#.#.....#...#
|
||||||
|
#.###.###.#.#.###.#####.#.#####.#.#.#.#.#.#.#.#####.#.#######.###.###.#.#####.#.#
|
||||||
|
#...#...#...#.#...#...#...#...#.#.#.#.#.#...#.....#...#.....#.#s..#...#.#.#...#.#
|
||||||
|
###.###.#.#####.###.###.###.#.###.#.#.###.#######.###.#.#.###.#.###.###Q#.#.#####
|
||||||
|
#.#.#.#.#.#...#...#...#.#...#.....#.#...#.#.....#.#...#.#.#...#.V.#.#...#.#.....#
|
||||||
|
#.#.#.#.#.#.#.###.#.#.#.#.#########.###.#.#.###.#.#####.#.#.#####.#.#.###.#####.#
|
||||||
|
#...#.#...#.#...#.#.#.#.#...#...#...#...#.#...#y..#...#.#.#.......#.#.#.......#.#
|
||||||
|
#.###.#####.###.#.###.#.###.#.###.###.#.#####.#####.#.#.#.#########.#.#.#.#####.#
|
||||||
|
#.#.....#...#.#...#...#.#...#.#.D.#.U.#.#.....#...#.#.#.#.......#...#..b#.#.....#
|
||||||
|
#.#####.#.###.#####.###.#.###.#.###.###.#.#####.#.#.#.#.#######.#.#######.#.###.#
|
||||||
|
#.H...#.#...#...........#.#...#.#.....#.#m......#...#...#.......#.#...#...#.#...#
|
||||||
|
#####.#.###.#############.#.#.#.#####.#.#.###############.#######.#.#.#####.#.###
|
||||||
|
#..q......#...............#.#.........#.#...............#...........#.......#..h#
|
||||||
|
#################################################################################
|
60
day18_test.go
Normal file
60
day18_test.go
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
package aoc2019
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDay18GetDistances(t *testing.T) {
|
||||||
|
grid := day18ReadGrid([]byte("########################\n#...............b.C.D.f#\n#.######################\n#.....@.a.B.c.d.A.e.F.g#\n########################"))
|
||||||
|
|
||||||
|
var maxInt int64 = math.MaxInt64
|
||||||
|
|
||||||
|
dists, err := grid.getPathDistances("", &maxInt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetPathDistances caused an error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d := dists["bacdfeg"]; d != 132 {
|
||||||
|
t.Errorf("Invalid distance for bacdfeg: exp=132 got=%d", d)
|
||||||
|
}
|
||||||
|
|
||||||
|
grid = day18ReadGrid([]byte(`#################
|
||||||
|
#i.G..c...e..H.p#
|
||||||
|
########.########
|
||||||
|
#j.A..b...f..D.o#
|
||||||
|
########@########
|
||||||
|
#k.E..a...g..B.n#
|
||||||
|
########.########
|
||||||
|
#l.F..d...h..C.m#
|
||||||
|
#################`))
|
||||||
|
maxInt = math.MaxInt64
|
||||||
|
|
||||||
|
dists, err = grid.getPathDistances("", &maxInt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetPathDistances caused an error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d := dists["afbjgnhdloepcikm"]; d != 136 {
|
||||||
|
t.Errorf("Invalid distance for bacdfeg: exp=136 got=%d", d)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCalculateDay18_Part1(t *testing.T) {
|
||||||
|
res, err := solveDay18Part1("day18_input.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Day 18 solver failed: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Solution Day 18 Part 1: %d", res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCalculateDay18_Part2(t *testing.T) {
|
||||||
|
res, err := solveDay18Part2("day18_input.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Day 18 solver failed: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Solution Day 18 Part 2: %d", res)
|
||||||
|
}
|
Loading…
Reference in a new issue