day23, part1

This commit is contained in:
efim 2023-12-23 09:16:04 +00:00
parent c3acf211c3
commit 44de1377ca
7 changed files with 267 additions and 3 deletions

22
day23/aLongWalk.go Normal file
View File

@ -0,0 +1,22 @@
package day23
import (
"fmt"
)
// length of longest scenic route
func Run() int {
fmt.Println("day 23")
filename := "day23/example"
field := ReadField(filename)
finalPaths := RunAllScenicPaths(field)
max := 0
for _, path := range finalPaths {
if path.visited.Cardinality() > max {
max = path.visited.Cardinality()
}
}
return max
}

23
day23/example Normal file
View File

@ -0,0 +1,23 @@
#.#####################
#.......#########...###
#######.#########.#.###
###.....#.>.>.###.#.###
###v#####.#v#.###.#.###
###.>...#.#.#.....#...#
###v###.#.#.#########.#
###...#.#.#.......#...#
#####.#.#.#######.#.###
#.....#.#.#.......#...#
#.#####.#.#.#########v#
#.#...#...#...###...>.#
#.#.#v#######v###.###v#
#...#.>.#...>.>.#.###.#
#####v#.#.###v#.#.###.#
#.....#...#...#.#.#...#
#.#########.###.#.#.###
#...###...#...#...#.###
###.###.#.###v#####v###
#...#...#.#.>.>.#.>.###
#.###.###.#.###.#.#v###
#.....###...###...#...#
#####################.#

112
day23/field.go Normal file
View File

@ -0,0 +1,112 @@
package day23
import (
"fmt"
"os"
"strings"
)
type Coord struct {
Row, Col int
}
type CellType rune
const (
Path CellType = '.'
Tree CellType = '#'
SlideDown CellType = 'v'
SlideUp CellType = '^'
SlideLeft CellType = '<'
SlideRight CellType = '>'
)
type Field struct {
MaxRow, MaxCol int
Cells map[Coord]CellType
StartCol, EndCol int
}
func (f *Field) Neighbors(c Coord) (neighbors []Coord) {
symb, exists := f.Cells[c]
if !exists {
panic(fmt.Sprintf("coord %+v not found in field", c))
}
var coords []Coord
switch symb {
case Path:
coords = []Coord{
{Row: c.Row + 1, Col: c.Col},
{Row: c.Row - 1, Col: c.Col},
{Row: c.Row, Col: c.Col + 1},
{Row: c.Row, Col: c.Col - 1},
}
case Tree:
panic(fmt.Sprintf("attempting to get neighbors of a tree at %+v", c))
case SlideDown:
coords = []Coord{{Row: c.Row + 1, Col: c.Col}}
case SlideUp:
coords = []Coord{{Row: c.Row - 1, Col: c.Col}}
case SlideLeft:
coords = []Coord{{Row: c.Row, Col: c.Col - 1}}
case SlideRight:
coords = []Coord{{Row: c.Row, Col: c.Col + 1}}
}
for _, coord := range coords {
neighborSymb, found := f.Cells[coord]
if !found || neighborSymb == Tree {
continue
}
neighbors = append(neighbors, coord)
}
return
}
func (f *Field) String() (result string) {
result += "\n"
for row := 0; row <= f.MaxRow; row++ {
for col := 0; col <= f.MaxCol; col++ {
if row == 0 && col == f.StartCol {
result += "S"
continue
}
if row == f.MaxRow && col == f.EndCol {
result += "E"
continue
}
symb := f.Cells[Coord{Row: row, Col: col}]
result += string(symb)
}
result += "\n"
}
return
}
func ReadField(filename string) (result Field) {
bytes, err := os.ReadFile(filename)
if err != nil {
panic(err)
}
lines := strings.Split(strings.TrimSpace(string(bytes)), "\n")
result.MaxRow = len(lines) - 1
result.MaxCol = len(lines[0]) - 1
rows := make(map[Coord]CellType)
for rowNum, row := range lines {
for colNum, symb := range row {
rows[Coord{Row: rowNum, Col: colNum}] = CellType(symb)
if rowNum == 0 && symb == rune(Path) {
result.StartCol = colNum
}
if rowNum == result.MaxRow && symb == rune(Path) {
result.EndCol = colNum
}
}
}
result.Cells = rows
return
}

31
day23/field_test.go Normal file
View File

@ -0,0 +1,31 @@
package day23
import "testing"
func TestReadField(t *testing.T) {
filename := "example"
field := ReadField(filename)
t.Log(field.String())
}
func TestStartNeighbors(t *testing.T) {
filename := "example"
field := ReadField(filename)
startNeighbors := field.Neighbors(Coord{Row: 0, Col: field.StartCol})
t.Log(startNeighbors)
}
// 5,3
func TestForkNeighbors(t *testing.T) {
filename := "example"
field := ReadField(filename)
startNeighbors := field.Neighbors(Coord{Row: 5, Col: 3})
t.Log(startNeighbors)
}
func TestSlideNeighbors(t *testing.T) {
filename := "example"
field := ReadField(filename)
startNeighbors := field.Neighbors(Coord{Row: 6, Col: 3})
t.Log(startNeighbors)
}

57
day23/paths.go Normal file
View File

@ -0,0 +1,57 @@
package day23
import (
mapset "github.com/deckarep/golang-set/v2"
)
type PathEnd struct {
end Coord
visited mapset.Set[Coord]
}
func ExtendPath(p PathEnd, f Field) (nextPaths []PathEnd) {
endPointNeighbors := f.Neighbors(p.end)
for _, potentialNewEnd := range endPointNeighbors {
if !p.visited.Contains(potentialNewEnd) {
nextVisited := p.visited.Clone()
nextVisited.Add(p.end)
nextPaths = append(nextPaths, PathEnd{
end: potentialNewEnd,
visited: nextVisited,
})
}
}
return
}
// return paths that end on End
func RunAllScenicPaths(f Field) (result []PathEnd) {
pathsToFurther := []PathEnd{
{end: Coord{Row: 0, Col: f.StartCol}, visited: mapset.NewSet[Coord]()},
}
theEndCoord := Coord{Row: f.MaxRow, Col: f.EndCol}
for len(pathsToFurther) > 0 {
curCheckedPath := pathsToFurther[0]
pathsToFurther = pathsToFurther[1:]
if curCheckedPath.end == theEndCoord {
result = append(result, curCheckedPath)
continue
}
nextSteps := ExtendPath(curCheckedPath, f)
// log.Printf("for %+v next steps %+v\n", curCheckedPath, pathsToFurther)
// log.Printf("remaining paths to check len is %d", len(pathsToFurther))
// log.Println(pathsToFurther)
if len(nextSteps) > 0 {
pathsToFurther = append(pathsToFurther, nextSteps...)
}
}
return
}

19
day23/paths_test.go Normal file
View File

@ -0,0 +1,19 @@
package day23
import "testing"
func TestRunAllPaths(t *testing.T) {
filename := "example"
field := ReadField(filename)
finalPaths := RunAllScenicPaths(field)
t.Log(finalPaths)
max := 0
for _, path := range finalPaths {
if path.visited.Cardinality() > max {
max = path.visited.Cardinality()
}
}
t.Logf("max path len is %d", max)
}

View File

@ -4,15 +4,15 @@ import (
"log" "log"
"time" "time"
"sunshine.industries/aoc2023/day22" "sunshine.industries/aoc2023/day23"
) )
func main() { func main() {
startTime := time.Now() startTime := time.Now()
log.Print("> starting run:") log.Print("> starting run:")
result := day22.Run() result := day23.Run()
log.Printf("\n\nday22 result: %d\n****\n", result) log.Printf("\n\nday23 result: %d\n****\n", result)
endTime := time.Now() endTime := time.Now()
diff := endTime.Sub(startTime) diff := endTime.Sub(startTime)
log.Printf("execution took %s", diff.String()) log.Printf("execution took %s", diff.String())