diff --git a/day8/dayEight.go b/day8/dayEight.go index 2081287..aea94d5 100644 --- a/day8/dayEight.go +++ b/day8/dayEight.go @@ -2,20 +2,71 @@ package day8 import ( "fmt" + "log" "os" "regexp" + "slices" "strings" ) func Run() int { fmt.Print("hello day 8") - filename := "day8/input" + filename := "day8/example3" net, path := Read(filename) - fmt.Printf("got %+v and %+v\n",net, path) - result := TraverseNetwork(net, path) + fmt.Printf("got %+v and %+v\n", net, path) + result := GhostTraverse(net, path) return result } +func GhostTraverse(net Network, path Path) int { + stepsNum := 0 + simultaneousPaths := make([]Node, 0) + for nodeName, node := range net.Nodes { + if strings.HasSuffix(nodeName, "A") { + simultaneousPaths = append(simultaneousPaths, node) + } + } + log.Printf("collected start points: %+v\n", 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 { + containsNonZEnding := slices.ContainsFunc(simulaneousPath, func(curNode Node) bool { + name := curNode.Name + last := name[len(name) - 1] + return last != 'Z' + }) + // log.Printf("checking if done for %+v : %t", simulaneousPath, !containsNonZEnding) + return !containsNonZEnding +} + +func getNextNode(net Network, curNode Node, direction rune) Node { + var nextNodeName string + switch direction { + case 'L': + nextNodeName = curNode.Left + case 'R': + nextNodeName = curNode.Right + } + nextNode, found := net.Nodes[nextNodeName] + if !found { + panic(fmt.Sprintf("instruction %s from node %+v results in not found next node %s", + string(direction), curNode, nextNodeName)) + } + return nextNode +} + func TraverseNetwork(net Network, path Path) int { stepsNum := 0 @@ -50,9 +101,9 @@ func Read(filename string) (Network, Path) { if err != nil { panic(fmt.Sprintln("error reading file ", filename)) } - lines := strings.Split( string(bytes), "\n") + lines := strings.Split(string(bytes), "\n") path := Path{ - Instruction: strings.TrimSpace( lines[0] ), + Instruction: strings.TrimSpace(lines[0]), } netDescriptions := lines[2:] @@ -69,8 +120,8 @@ func Read(filename string) (Network, Path) { panic(fmt.Sprintln("error finding match in string : ", line)) } node := Node{ - Name: match[nameIndex], - Left: match[leftIndex], + Name: match[nameIndex], + Left: match[leftIndex], Right: match[rightIndex], } net.Nodes[node.Name] = node @@ -80,7 +131,7 @@ func Read(filename string) (Network, Path) { } type Node struct { - Name string + Name string Left, Right string } @@ -90,9 +141,10 @@ type Network struct { type Path struct { Instruction string - curStep int + curStep int } -func (p *Path)next() rune { + +func (p *Path) next() rune { curInstruction := p.Instruction[p.curStep] p.curStep += 1 if p.curStep == len(p.Instruction) { diff --git a/day8/example3 b/day8/example3 new file mode 100644 index 0000000..f2e972e --- /dev/null +++ b/day8/example3 @@ -0,0 +1,10 @@ +LR + +GGA = (GGB, XXX) +GGB = (XXX, GGZ) +GGZ = (GGB, XXX) +HHA = (HHB, XXX) +HHB = (HHC, HHC) +HHC = (HHZ, HHZ) +HHZ = (HHB, HHB) +XXX = (XXX, XXX)