-
Notifications
You must be signed in to change notification settings - Fork 0
/
day13.go
187 lines (165 loc) · 3.66 KB
/
day13.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package main
import (
"fmt"
"sort"
"strconv"
"unicode"
)
const (
RIGHT_ORDER PacketOrder = iota
WRONG_ORDER
EQUAL_ORDER
)
type PacketOrder uint8
type PacketValue struct {
list []PacketValue
number int
}
type Packet struct {
left PacketValue
right PacketValue
}
func numberToList(number int) []PacketValue {
value := PacketValue{}
value.number = number
return []PacketValue{value}
}
func packetListsOrder(left, right []PacketValue) PacketOrder {
for i := 0; ; i++ {
if len(left) == i {
if len(right) == i {
return EQUAL_ORDER
}
return RIGHT_ORDER
}
if len(right) == i {
return WRONG_ORDER
}
order := packetValuesOrder(left[i], right[i])
if order != EQUAL_ORDER {
return order
}
}
}
func packetValuesOrder(left, right PacketValue) PacketOrder {
if left.list == nil {
if right.list == nil {
switch {
case left.number < right.number:
return RIGHT_ORDER
case left.number > right.number:
return WRONG_ORDER
default:
return EQUAL_ORDER
}
}
return packetListsOrder(numberToList(left.number), right.list)
} else {
if right.list == nil {
return packetListsOrder(left.list, numberToList(right.number))
}
return packetListsOrder(left.list, right.list)
}
}
func (packet Packet) isInRightOrder() bool {
return packetValuesOrder(packet.left, packet.right) == RIGHT_ORDER
}
func SumPacketIndicesInRightOrder(packets []Packet) int {
sum := 0
for i, packet := range packets {
if packet.isInRightOrder() {
sum += i + 1
}
}
return sum
}
func packetList(packets []Packet) []PacketValue {
list := make([]PacketValue, len(packets)*2)
for i, p := range packets {
list[i*2] = p.left
list[i*2+1] = p.right
}
return list
}
func dividerPackets() [2]PacketValue {
divider := [2]PacketValue{}
col := 0
divider[0] = parsePacketValue("[[2]]", &col)
col = 0
divider[1] = parsePacketValue("[[6]]", &col)
return divider
}
func DecoderKey(packets []PacketValue) int {
divider := dividerPackets()
packets = append(packets, divider[:]...)
sort.Slice(packets, func(i, j int) bool { return packetValuesOrder(packets[i], packets[j]) == RIGHT_ORDER })
key := 1
d := 0
for i, packet := range packets {
if packetValuesOrder(packet, divider[d]) == EQUAL_ORDER {
key *= i + 1
d++
if d == len(divider) {
break
}
}
}
return key
}
func day13(input []string) {
packets := parsePackets(input)
fmt.Println(SumPacketIndicesInRightOrder(packets))
fmt.Println(DecoderKey(packetList(packets)))
}
func init() {
Solutions[13] = day13
}
func parsePacketNumber(value string, col *int) int {
c := *col
for unicode.IsNumber(rune(value[*col])) {
*col += 1
}
if number, err := strconv.Atoi(value[c:*col]); err == nil {
return number
}
return -1
}
func parsePacketList(value string, col *int) []PacketValue {
list := []PacketValue{}
for value[*col] != ']' {
*col += 1
packetValue := parsePacketValue(value, col)
if packetValue.list != nil || packetValue.number >= 0 {
list = append(list, packetValue)
}
}
*col += 1
return list
}
func parsePacketValue(value string, col *int) PacketValue {
packetValue := PacketValue{}
if value[*col] == '[' {
packetValue.number = -1
packetValue.list = parsePacketList(value, col)
} else {
packetValue.number = parsePacketNumber(value, col)
}
return packetValue
}
func parsePacket(input []string, row *int) Packet {
packet := Packet{}
col := 0
packet.left = parsePacketValue(input[*row], &col)
col = 0
packet.right = parsePacketValue(input[*row+1], &col)
*row += 3
return packet
}
func parsePackets(input []string) []Packet {
packets := []Packet{}
row := 0
for row < len(input) {
packets = append(packets, parsePacket(input, &row))
}
return packets
}