diff --git a/day23/aLongWalk.go b/day23/aLongWalk.go index 18dad7e..37e44af 100644 --- a/day23/aLongWalk.go +++ b/day23/aLongWalk.go @@ -7,7 +7,7 @@ import ( // length of longest scenic route func Run() int { fmt.Println("day 23") - filename := "day23/example" + filename := "day23/input" field := ReadField(filename) finalPaths := RunAllScenicPaths(field) diff --git a/day23/field.go b/day23/field.go index 361bba8..45adf50 100644 --- a/day23/field.go +++ b/day23/field.go @@ -27,6 +27,35 @@ type Field struct { StartCol, EndCol int } +func (f *Field) NeighborsPart2(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 Tree: + panic(fmt.Sprintf("attempting to get neighbors of a tree at %+v", c)) + default: + 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}, + } + } + + for _, coord := range coords { + neighborSymb, found := f.Cells[coord] + if !found || neighborSymb == Tree { + continue + } + neighbors = append(neighbors, coord) + } + return +} + func (f *Field) Neighbors(c Coord) (neighbors []Coord) { symb, exists := f.Cells[c] if !exists { diff --git a/day23/notes.org b/day23/notes.org new file mode 100644 index 0000000..d5e569f --- /dev/null +++ b/day23/notes.org @@ -0,0 +1,67 @@ +#+title: Notes +* ok, second part is long. +and here optimization of storing direction of enter into path, and it's length, +would that be helpful? +it might not, because based on visited some future longer path might not be available. + +i don't know how to optimize. + +i could maybe do same calculation in parallel, somehow +put not into queue, but into channel +* wait a second. previous answer was 2018 +and now long checks result in me waiting for intermediate 1882. +let's add early cutoffs, if not end by 2018, then abandon +doubt that's implementable + +* well. do i want to try parallel? +seems like false path, really +like there should be a better optimizaiton first +* maybe we could join detours into 'potential longest paths' +like if we traverse, and get to a point which was previously visited, +for evey path that went through that split path, +i could check whether i can take paths that went through this point, and switch their part with the detoured part. +* and maybe we could continue longest paths first? +like making pathsToFurther a heap by visited.Cordinality ? + +oh, and then we'll find 'some path to end' +and additional paths will try to add their detour. + +so, i guess when finding a path to end, i could save path to end for each point. +then if i reach the point, i could check if i can use some of the + +and i guess if i do depth first then i'll always have all paths to end from a point if i return to it? +* this sounds like an idea. +with heap do depth first. + +if it's first visit to a point, just go further +if i find the end, i'd want to mark all points on the path with path info + +hm. recursive calls might make this easier. +because i'd want both 'prefixVisited' set and totalPathSet + +due to depth first, we'll discover shortest path first. +and points will get mapped with this first (of potential multiple) path info to end. + +now if on followup steps i get into the point with info on paths to end, +that should mean that i've already found all paths to end from that point, right? + +now i need to check for the 'detour' which 'paths to end' are still possible with that detour added +by taking set of elements from this point, to end. and checking that intersection with detour elements is 0. + +if there are like this - report finding a new path, and save to all elements of that path somehow. + +and now on finding detours i wouldn't need to re-check path to end, that should save a lot of time +** so how to go about in coding this? +have shared map[Coord][]EndPathInfo + +the DFS means i'm recursing into each child. +and taking the result of the call. +it should be info on path to end? or multiple paths to end. +which should be added to current node. + +and then calling with start point will return paths to end from start, and i'll be able to take the by length + +ok. but. if i'm entering the coord, and there are already paths to end. +then i need to presume that those are only possible paths to end from this point, +because all other paths should have been explored by now, +i for my 'detour' determine whether it is consistent with any of already found paths to end. diff --git a/day23/paths.go b/day23/paths.go index f502ea0..7920b2a 100644 --- a/day23/paths.go +++ b/day23/paths.go @@ -1,6 +1,8 @@ package day23 import ( + "log" + mapset "github.com/deckarep/golang-set/v2" ) @@ -10,7 +12,7 @@ type PathEnd struct { } func ExtendPath(p PathEnd, f Field) (nextPaths []PathEnd) { - endPointNeighbors := f.Neighbors(p.end) + endPointNeighbors := f.NeighborsPart2(p.end) for _, potentialNewEnd := range endPointNeighbors { if !p.visited.Contains(potentialNewEnd) { nextVisited := p.visited.Clone() @@ -39,6 +41,7 @@ func RunAllScenicPaths(f Field) (result []PathEnd) { if curCheckedPath.end == theEndCoord { result = append(result, curCheckedPath) + log.Printf("found end path of len %d . %+v", curCheckedPath.visited.Cardinality(), curCheckedPath) continue }