day23, example second
This commit is contained in:
parent
7ebb6dee2c
commit
28cf35e0e4
|
@ -2,19 +2,21 @@ package day23
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// length of longest scenic route
|
// length of longest scenic route
|
||||||
func Run() int {
|
func Run() int {
|
||||||
fmt.Println("day 23")
|
fmt.Println("day 23")
|
||||||
filename := "day23/input"
|
filename := "day23/example"
|
||||||
field := ReadField(filename)
|
field := ReadField(filename)
|
||||||
finalPaths := RunAllScenicPaths(field)
|
finalPaths := RunDFSTingy(field)
|
||||||
|
log.Println(finalPaths)
|
||||||
|
|
||||||
max := 0
|
max := 0
|
||||||
for _, path := range finalPaths {
|
for _, path := range finalPaths {
|
||||||
if path.visited.Cardinality() > max {
|
if path.Visited.Cardinality() > max {
|
||||||
max = path.visited.Cardinality()
|
max = path.Visited.Cardinality()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return max
|
return max
|
||||||
|
|
|
@ -27,6 +27,10 @@ type Field struct {
|
||||||
StartCol, EndCol int
|
StartCol, EndCol int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Field) EndCoord() Coord {
|
||||||
|
return Coord{Row: f.MaxRow, Col: f.EndCol}
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Field) NeighborsPart2(c Coord) (neighbors []Coord) {
|
func (f *Field) NeighborsPart2(c Coord) (neighbors []Coord) {
|
||||||
symb, exists := f.Cells[c]
|
symb, exists := f.Cells[c]
|
||||||
if !exists {
|
if !exists {
|
||||||
|
|
|
@ -65,3 +65,8 @@ 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,
|
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,
|
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.
|
i for my 'detour' determine whether it is consistent with any of already found paths to end.
|
||||||
|
** NO. dfs doesn't mean i'll find shortest path first.
|
||||||
|
so if i'm in visited, it doesn't mean that stored is shorter and current is a detour.
|
||||||
|
|
||||||
|
but dfs should mean that all paths from this prefix have finished.
|
||||||
|
so, sure. there have to be all done?
|
||||||
|
|
|
@ -27,19 +27,94 @@ func ExtendPath(p PathEnd, f Field) (nextPaths []PathEnd) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// info on path from start to end
|
||||||
|
type PathInfo struct {
|
||||||
|
Visited mapset.Set[Coord]
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunDFSTingy(f Field) []PathInfo {
|
||||||
|
initialPath := PathEnd{
|
||||||
|
end: Coord{Row: 0, Col: f.StartCol}, visited: mapset.NewSet[Coord](),
|
||||||
|
}
|
||||||
|
initialShared := make(map[Coord][]PathInfo)
|
||||||
|
|
||||||
|
return DFSScenicPaths(f, initialPath, initialShared)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DFSScenicPaths(f Field, curPath PathEnd,
|
||||||
|
sharedMem map[Coord][]PathInfo) (pathsFromTheStartToEnd []PathInfo) {
|
||||||
|
|
||||||
|
curCoord := curPath.end
|
||||||
|
if curCoord == f.EndCoord() {
|
||||||
|
pathsFromTheStartToEnd = append(pathsFromTheStartToEnd, PathInfo{curPath.visited.Clone()})
|
||||||
|
log.Printf("got to end. visited %+v . will return %+v\n", curPath.visited, pathsFromTheStartToEnd)
|
||||||
|
// i guess return only from current to end?
|
||||||
|
// and on non terminal first time, return copy with self added?
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// now for non final point
|
||||||
|
knownPaths, visitedBefore := sharedMem[curCoord]
|
||||||
|
|
||||||
|
// NOTE but this only if we haven't visited this coord before!
|
||||||
|
|
||||||
|
if !visitedBefore {
|
||||||
|
nextSteps := ExtendPath(curPath, f)
|
||||||
|
suffixesFromCurToEnd := make([]PathInfo, 0)
|
||||||
|
for _, nextPath := range nextSteps {
|
||||||
|
pathsToEndThrough := DFSScenicPaths(f, nextPath, sharedMem)
|
||||||
|
// i guess here deduct the prefix.
|
||||||
|
|
||||||
|
for _, path := range pathsToEndThrough {
|
||||||
|
// will contain this and further
|
||||||
|
suffix := PathInfo{
|
||||||
|
Visited: path.Visited.Difference(curPath.visited).Clone(),
|
||||||
|
}
|
||||||
|
suffixesFromCurToEnd = append(suffixesFromCurToEnd, suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
pathsFromTheStartToEnd = append(pathsFromTheStartToEnd, pathsToEndThrough...)
|
||||||
|
}
|
||||||
|
|
||||||
|
sharedMem[curCoord] = suffixesFromCurToEnd
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
// have visited this point before, due to dfs all possible paths to end should already be known
|
||||||
|
// so curPath.visited should contian a detour.
|
||||||
|
// need to figure out if this detour is compatible with any of the known paths to end
|
||||||
|
// from those create 'new' paths to end with that detour
|
||||||
|
// return those and add those to the shared mem
|
||||||
|
for _, knownPathToEnd := range knownPaths {
|
||||||
|
// those are all points through which this known path goes from current to end
|
||||||
|
// if our curPath
|
||||||
|
fromCurToEnd := knownPathToEnd.Visited
|
||||||
|
thisPrefix := curPath.visited
|
||||||
|
|
||||||
|
if thisPrefix.Intersect(fromCurToEnd).Cardinality() == 0 {
|
||||||
|
// then current prefix is compatible with this path.
|
||||||
|
fromCurPrefixToEnd := thisPrefix.Clone()
|
||||||
|
fromCurPrefixToEnd.Union(fromCurToEnd)
|
||||||
|
pathsFromTheStartToEnd = append(pathsFromTheStartToEnd, PathInfo{fromCurPrefixToEnd})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("should not be reachable")
|
||||||
|
}
|
||||||
|
|
||||||
// return paths that end on End
|
// return paths that end on End
|
||||||
func RunAllScenicPaths(f Field) (result []PathEnd) {
|
func RunAllScenicPaths(f Field) (result []PathEnd) {
|
||||||
pathsToFurther := []PathEnd{
|
pathsToFurther := []PathEnd{
|
||||||
{end: Coord{Row: 0, Col: f.StartCol}, visited: mapset.NewSet[Coord]()},
|
{end: Coord{Row: 0, Col: f.StartCol}, visited: mapset.NewSet[Coord]()},
|
||||||
}
|
}
|
||||||
|
|
||||||
theEndCoord := Coord{Row: f.MaxRow, Col: f.EndCol}
|
|
||||||
|
|
||||||
for len(pathsToFurther) > 0 {
|
for len(pathsToFurther) > 0 {
|
||||||
curCheckedPath := pathsToFurther[0]
|
curCheckedPath := pathsToFurther[0]
|
||||||
pathsToFurther = pathsToFurther[1:]
|
pathsToFurther = pathsToFurther[1:]
|
||||||
|
|
||||||
if curCheckedPath.end == theEndCoord {
|
if curCheckedPath.end == f.EndCoord() {
|
||||||
result = append(result, curCheckedPath)
|
result = append(result, curCheckedPath)
|
||||||
log.Printf("found end path of len %d . %+v", curCheckedPath.visited.Cardinality(), curCheckedPath)
|
log.Printf("found end path of len %d . %+v", curCheckedPath.visited.Cardinality(), curCheckedPath)
|
||||||
continue
|
continue
|
||||||
|
|
Loading…
Reference in New Issue