github.com/agrigoryan/aoc_2023_go@v0.0.0-20231216221323-4ace361ec685/day8/d8p2.go (about) 1 package day8 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // greatest common divisor (GCD) via Euclidean algorithm 9 func gcd(a, b int) int { 10 for b != 0 { 11 t := b 12 b = a % b 13 a = t 14 } 15 return a 16 } 17 18 // find Least Common Multiple (LCM) via GCD 19 func lcm(a, b int, integers ...int) int { 20 result := a * b / gcd(a, b) 21 22 for i := 0; i < len(integers); i++ { 23 result = lcm(result, integers[i]) 24 } 25 26 return result 27 } 28 29 func d8p2(input string) int { 30 lines := strings.Split(input, "\n") 31 32 directions := []rune(lines[0]) 33 34 nodesByName := map[string]*node{} 35 36 startNodes := []*node{} 37 38 for _, line := range lines[2:] { 39 name := strings.Split(line, " ")[0] 40 left := line[strings.Index(line, "(")+1 : strings.Index(line, ",")] 41 right := line[strings.Index(line, ", ")+2 : strings.Index(line, ")")] 42 nodesByName[name] = &node{name, left, right, name[len(name)-1] == 'Z'} 43 if name[len(name)-1] == 'A' { 44 startNodes = append(startNodes, nodesByName[name]) 45 } 46 } 47 48 cycleLength := func(n *node) int { 49 steps := 0 50 for { 51 direction := directions[steps%len(directions)] 52 if n.endingNode { 53 break 54 } 55 if direction == 'R' { 56 n = nodesByName[n.right] 57 } else { 58 n = nodesByName[n.left] 59 } 60 steps += 1 61 } 62 return steps 63 } 64 65 cycleLengths := make([]int, len(startNodes)) 66 67 for i, n := range startNodes { 68 cycleLengths[i] = cycleLength(n) 69 } 70 71 res := lcm(cycleLengths[0], cycleLengths[1], cycleLengths[2:]...) 72 fmt.Println(res) 73 return res 74 }