day8, example3 new approach
This commit is contained in:
parent
dea9d15c66
commit
3300a8bf3e
109
day8/dayEight.go
109
day8/dayEight.go
|
@ -18,8 +18,7 @@ func Run() int {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func GhostTraverse(net Network, path Path) int {
|
func getGhostStartNodes(net Network) []Node {
|
||||||
stepsNum := 0
|
|
||||||
simultaneousPaths := make([]Node, 0)
|
simultaneousPaths := make([]Node, 0)
|
||||||
for nodeName, node := range net.Nodes {
|
for nodeName, node := range net.Nodes {
|
||||||
if strings.HasSuffix(nodeName, "A") {
|
if strings.HasSuffix(nodeName, "A") {
|
||||||
|
@ -27,28 +26,94 @@ func GhostTraverse(net Network, path Path) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Printf("collected start points: %+v\n", simultaneousPaths)
|
log.Printf("collected start points: %+v\n", simultaneousPaths)
|
||||||
|
return simultaneousPaths
|
||||||
// concurrent iteraction
|
|
||||||
for !isGhostWayDone(simultaneousPaths) {
|
|
||||||
direction := path.next()
|
|
||||||
for i, curNode := range simultaneousPaths {
|
|
||||||
simultaneousPaths[i] = getNextNode(net, curNode, direction)
|
|
||||||
}
|
|
||||||
// log.Printf("done step into %+v\n", simultaneousPaths)
|
|
||||||
stepsNum += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return stepsNum
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isGhostWayDone(simulaneousPath []Node) bool {
|
type GhostPathInfo struct {
|
||||||
containsNonZEnding := slices.ContainsFunc(simulaneousPath, func(curNode Node) bool {
|
InitialSteps, CycleLen int
|
||||||
name := curNode.Name
|
}
|
||||||
last := name[len(name) - 1]
|
|
||||||
return last != 'Z'
|
func getGhostPathInfo(startNode Node, net Network, pathString string) GhostPathInfo {
|
||||||
})
|
path := Path {Instruction: pathString}
|
||||||
// log.Printf("checking if done for %+v : %t", simulaneousPath, !containsNonZEnding)
|
initialSteps, cycleLen := 0, 1
|
||||||
return !containsNonZEnding
|
runnerNode := startNode
|
||||||
|
|
||||||
|
for !strings.HasSuffix(runnerNode.Name, "Z") {
|
||||||
|
direction := path.next()
|
||||||
|
runnerNode = getNextNode(net, runnerNode, direction)
|
||||||
|
initialSteps += 1
|
||||||
|
}
|
||||||
|
// one more step for starting to check for cycle
|
||||||
|
oneDirection := path.next()
|
||||||
|
runnerNode = getNextNode(net, runnerNode, oneDirection)
|
||||||
|
|
||||||
|
for !strings.HasSuffix(runnerNode.Name, "Z") {
|
||||||
|
direction := path.next()
|
||||||
|
runnerNode = getNextNode(net, runnerNode, direction)
|
||||||
|
cycleLen += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return GhostPathInfo{
|
||||||
|
InitialSteps: initialSteps,
|
||||||
|
CycleLen: cycleLen,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GhostTraverse(net Network, path Path) int {
|
||||||
|
simultaneousPaths := getGhostStartNodes(net)
|
||||||
|
pathInfos := make([]GhostPathInfo, 0, len(simultaneousPaths))
|
||||||
|
for _, pathStart := range simultaneousPaths {
|
||||||
|
pathInfos = append(pathInfos, getGhostPathInfo(pathStart, net, path.Instruction))
|
||||||
|
}
|
||||||
|
log.Printf("path infos are %+v\n", pathInfos)
|
||||||
|
|
||||||
|
// and now the algo.
|
||||||
|
// if initial paths equal - that's answer
|
||||||
|
// if not - seed round, +1 cycle to each
|
||||||
|
// if equal - that the answer
|
||||||
|
// if not - here's the main loop
|
||||||
|
// find biggest.
|
||||||
|
// then iterate all but that one.
|
||||||
|
// calculate diff % curCycle. if == 0, just add to where they stand together
|
||||||
|
// if not - add cycles to this with one overhopping
|
||||||
|
// and check whether they are all equeal
|
||||||
|
|
||||||
|
stepCounts := make([]int, len(pathInfos))
|
||||||
|
for i, pathInfo := range pathInfos {
|
||||||
|
stepCounts[i] = pathInfo.InitialSteps
|
||||||
|
}
|
||||||
|
|
||||||
|
// oh, i don't need to seed the cycle, they are already not equal
|
||||||
|
for !allEqual(stepCounts) {
|
||||||
|
max := slices.Max(stepCounts)
|
||||||
|
for i, pathInfo := range pathInfos {
|
||||||
|
steps := stepCounts[i]
|
||||||
|
if steps == max {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
diff := max - steps
|
||||||
|
isCatchingUp := diff % pathInfo.CycleLen == 0
|
||||||
|
if isCatchingUp {
|
||||||
|
stepCounts[i] = max
|
||||||
|
} else {
|
||||||
|
overJump := (diff / pathInfo.CycleLen + 1) * pathInfo.CycleLen
|
||||||
|
stepCounts[i] += overJump
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Printf("done one cycle iteration, results : %+v", stepCounts)
|
||||||
|
}
|
||||||
|
|
||||||
|
return stepCounts[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func allEqual(nums []int) bool {
|
||||||
|
head := nums[0]
|
||||||
|
for _, num := range nums {
|
||||||
|
if num != head {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNextNode(net Network, curNode Node, direction rune) Node {
|
func getNextNode(net Network, curNode Node, direction rune) Node {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#+title: Notes
|
||||||
|
* ok, for part 2 i think i'm supposed to find cicles.
|
||||||
|
so for each starting point?
|
||||||
|
calculate how long it takes to get to first Z, let's call is initialN
|
||||||
|
and then how long it takes to get to Z again, call it cicleN
|
||||||
|
|
||||||
|
i have initial0 + n0 * cicle0 = k
|
||||||
|
|
||||||
|
now i need to find minimal number K ( steps ), so that exists solution for each starting point
|
||||||
|
|
||||||
|
(k - initial0) % cycle0 == 0
|
||||||
|
|
||||||
|
so. get both these numbers for each starting point.
|
||||||
|
if initialN are equal, that's the answer.
|
||||||
|
|
||||||
|
if they are not equal?
|
||||||
|
then i have what? huh
|
||||||
|
|
||||||
|
i guess then i need to add 1 cycle length to all.
|
||||||
|
if they are equal, nice.
|
||||||
|
|
||||||
|
but if they are not equal?
|
||||||
|
i guess i have one that's longest?
|
||||||
|
then i need to advance all paths, up to and overshoot if necessary by their cycle lengths.
|
||||||
|
so take the difference, if divisible by cycle - yay. just multiply, if not divisible - overshoot with +1 cycle
|
||||||
|
|
||||||
|
if all are same, that's solution.
|
||||||
|
if one is farthest, repeat
|
||||||
|
* i stopped bruteforce at 4080000000
|
Loading…
Reference in New Issue