day23: started hardcode of part2, way too slow
This commit is contained in:
parent
44de1377ca
commit
7ebb6dee2c
|
@ -7,7 +7,7 @@ import (
|
||||||
// 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/example"
|
filename := "day23/input"
|
||||||
field := ReadField(filename)
|
field := ReadField(filename)
|
||||||
finalPaths := RunAllScenicPaths(field)
|
finalPaths := RunAllScenicPaths(field)
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,35 @@ type Field struct {
|
||||||
StartCol, EndCol int
|
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) {
|
func (f *Field) Neighbors(c Coord) (neighbors []Coord) {
|
||||||
symb, exists := f.Cells[c]
|
symb, exists := f.Cells[c]
|
||||||
if !exists {
|
if !exists {
|
||||||
|
|
|
@ -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.
|
|
@ -1,6 +1,8 @@
|
||||||
package day23
|
package day23
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,7 +12,7 @@ type PathEnd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExtendPath(p PathEnd, f Field) (nextPaths []PathEnd) {
|
func ExtendPath(p PathEnd, f Field) (nextPaths []PathEnd) {
|
||||||
endPointNeighbors := f.Neighbors(p.end)
|
endPointNeighbors := f.NeighborsPart2(p.end)
|
||||||
for _, potentialNewEnd := range endPointNeighbors {
|
for _, potentialNewEnd := range endPointNeighbors {
|
||||||
if !p.visited.Contains(potentialNewEnd) {
|
if !p.visited.Contains(potentialNewEnd) {
|
||||||
nextVisited := p.visited.Clone()
|
nextVisited := p.visited.Clone()
|
||||||
|
@ -39,6 +41,7 @@ func RunAllScenicPaths(f Field) (result []PathEnd) {
|
||||||
|
|
||||||
if curCheckedPath.end == theEndCoord {
|
if curCheckedPath.end == theEndCoord {
|
||||||
result = append(result, curCheckedPath)
|
result = append(result, curCheckedPath)
|
||||||
|
log.Printf("found end path of len %d . %+v", curCheckedPath.visited.Cardinality(), curCheckedPath)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue