-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
122 lines (97 loc) · 2.22 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
package main
import (
"github.com/danvolchek/AdventOfCode/lib"
"strconv"
)
type Ordering int
const (
Smaller Ordering = iota
Equal
Larger
)
type Value struct {
Val int
Items []Value
}
// elements returns the items rawList represents
func elements(rawList string) []string {
if len(rawList) == 0 {
return nil
}
var result []string
var last int
var nesting int
for i := range rawList {
switch rawList[i] {
case '[':
nesting += 1
case ']':
nesting -= 1
case ',':
if nesting == 0 {
result = append(result, rawList[last:i])
last = i + 1
}
}
}
result = append(result, rawList[last:])
return result
}
func parseValue(raw string) Value {
// If raw is an int, then it is a single value
if v, err := strconv.Atoi(raw); err == nil {
return Value{Val: v}
}
// Otherwise, strip the list markers and parse the item contents recursively
return Value{
Items: lib.Map(elements(raw[1:len(raw)-1]), parseValue),
}
}
func (v Value) Compare(o Value) Ordering {
// If both are ints, compare their values
if v.Items == nil && o.Items == nil {
return compare(v.Val, o.Val)
}
toList := func(v Value) []Value {
if v.Items != nil {
return v.Items
}
return []Value{v}
}
// Otherwise, compare the elements pairwise, replacing an int with a list of that int
vList, oList := toList(v), toList(o)
for i := 0; i < len(vList) && i < len(oList); i += 1 {
result := vList[i].Compare(oList[i])
if result != Equal {
return result
}
}
// If one list ran out if items, the ordering is based on list size
return compare(len(vList), len(oList))
}
func compare(a, b int) Ordering {
if a == b {
return Equal
}
if a < b {
return Smaller
}
return Larger
}
func solve(packets [][]Value) int {
sum := 0
for i, pair := range packets {
if pair[0].Compare(pair[1]) == Smaller {
sum += i + 1
}
}
return sum
}
func main() {
solver := lib.Solver[[][]Value, int]{
ParseF: lib.ParseChunks(lib.ParseLine(parseValue)),
SolveF: solve,
}
solver.Expect("[1,1,3,1,1]\n[1,1,5,1,1]\n\n[[1],[2,3,4]]\n[[1],4]\n\n[9]\n[[8,7,6]]\n\n[[4,4],4,4]\n[[4,4],4,4,4]\n\n[7,7,7,7]\n[7,7,7]\n\n[]\n[3]\n\n[[[]]]\n[[]]\n\n[1,[2,[3,[4,[5,6,7]]]],8,9]\n[1,[2,[3,[4,[5,6,0]]]],8,9]", 13)
solver.Verify(5340)
}