-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmain.go
124 lines (107 loc) · 2.33 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package main
import (
"io"
aoc "github.com/teivah/advent-of-code"
)
func fs1(input io.Reader) int {
groups := aoc.StringGroups(aoc.ReaderToStrings(input))
directions := parseDirections(groups[0][0])
nodes := parseNodes(groups[1])
cur := "AAA"
distance := 0
for i := 0; ; i = (i + 1) % len(directions) {
if cur == "ZZZ" {
return distance
}
dir := directions[i]
if dir == aoc.Left {
cur = nodes[cur].left
} else {
cur = nodes[cur].right
}
distance++
}
}
func parseDirections(s string) []aoc.Direction {
var instructions []aoc.Direction
for _, c := range s {
switch c {
case 'L':
instructions = append(instructions, aoc.Left)
case 'R':
instructions = append(instructions, aoc.Right)
default:
panic(c)
}
}
return instructions
}
type Node struct {
left string
right string
}
func parseNodes(lines []string) map[string]Node {
m := make(map[string]Node, len(lines))
for _, s := range lines {
node, name := parseNode(s)
m[name] = node
}
return m
}
func parseNode(s string) (Node, string) {
del := aoc.NewDelimiter(s, " = ")
name := del.GetString(0)
nodes := del.GetString(1)
nodes = nodes[1 : len(nodes)-1]
directions := aoc.NewDelimiter(nodes, ", ")
return Node{
left: directions.GetString(0),
right: directions.GetString(1),
}, name
}
func fs2(input io.Reader) int {
groups := aoc.StringGroups(aoc.ReaderToStrings(input))
directions := parseDirections(groups[0][0])
nodes := parseNodes(groups[1])
var curs []string
for name := range nodes {
if isStartingNode(name) {
curs = append(curs, name)
}
}
distance := 0
distances := make(map[int]int)
for i := 0; ; i = (i + 1) % len(directions) {
if len(distances) == len(curs) {
break
}
dir := directions[i]
for curIdx, name := range curs {
if dir == aoc.Left {
curs[curIdx] = nodes[name].left
} else {
curs[curIdx] = nodes[name].right
}
}
distance++
for idx, cur := range curs {
if isEndingNode(cur) {
if _, exists := distances[idx]; exists {
continue
}
distances[idx] = distance
}
}
}
numbers := make([]int, 0, len(curs))
for _, d := range distances {
numbers = append(numbers, d)
}
return aoc.LeastCommonMultiple(numbers)
}
func isStartingNode(name string) bool {
return name[len(name)-1] == 'A'
}
func isEndingNode(name string) bool {
return name[len(name)-1] == 'Z'
}