@@ -13,13 +13,52 @@ func main() {
13
13
fmt .Printf ("Part 2: %d\n " , part2 (util .RelativeFile ("input" ))) // 13476220616073
14
14
}
15
15
16
- type parser struct {
16
+ func part1 (file string ) int64 {
17
+ data , err := hex .DecodeString (util .ReadLinesStrings (file )[0 ])
18
+ util .Check (err )
19
+ p := Parser {data : data }
20
+ p .ReadNumSubPackets (1 )
21
+ return p .sumVersionNums
22
+ }
23
+
24
+ func part2 (file string ) int64 {
25
+ return evalExpression (util .ReadLinesStrings (file )[0 ])
26
+ }
27
+
28
+ func evalExpression (text string ) int64 {
29
+ data , err := hex .DecodeString (text )
30
+ util .Check (err )
31
+ p := Parser {data : data }
32
+ var out []int64
33
+ out , _ = p .ReadNumSubPackets (1 )
34
+ return out [0 ]
35
+ }
36
+
37
+ // Parser holds data for parsing the Buoyancy Interchange Transmission System (BITS) expression.
38
+ type Parser struct {
17
39
data []byte
18
40
pos int
19
41
sumVersionNums int64
20
42
}
21
43
22
- func (p * parser ) ReadLiteral () (int64 , bool ) {
44
+ func (p * Parser ) Chomp (ln int ) (int64 , bool ) {
45
+ i := bits .GetAsInt (p .data , p .pos , ln )
46
+ p .pos += ln
47
+ return i , (len (p .data )* 8 )- 1 > p .pos
48
+ }
49
+
50
+ // ReadVersion reads the 3 bits at the start of the expression. These are only useful for part 1 of day 16.
51
+ func (p * Parser ) ReadVersion () (int64 , bool ) {
52
+ return p .Chomp (3 )
53
+ }
54
+
55
+ // ReadMode reads the 3 bits of the mode at the head of an expression (after the version).
56
+ func (p * Parser ) ReadMode () (int64 , bool ) {
57
+ return p .Chomp (3 )
58
+ }
59
+
60
+ // ReadLiteral reads a single literal value.
61
+ func (p * Parser ) ReadLiteral () (int64 , bool ) {
23
62
var ok bool
24
63
var read int64
25
64
val := int64 (0 )
@@ -36,21 +75,45 @@ func (p *parser) ReadLiteral() (int64, bool) {
36
75
return val , ok
37
76
}
38
77
39
- func (p * parser ) Chomp (ln int ) (int64 , bool ) {
40
- i := bits .GetAsInt (p .data , p .pos , ln )
41
- p .pos += ln
42
- return i , (len (p .data )* 8 )- 1 > p .pos
78
+ // ReadNested begins to parse a sub-packet chunk.
79
+ // If the length type id is 0 - read packets until the total number of bits has been reached
80
+ // If the length type id is 1 - read the specified number of packets
81
+ func (p * Parser ) ReadNested () ([]int64 , bool ) {
82
+ lengthTypeId , _ := p .Chomp (1 )
83
+ if lengthTypeId == 0 {
84
+ // Total number of bits
85
+ totalNumberOfBits , _ := p .Chomp (15 )
86
+ return p .ReadSubPacketsOfLength (int (totalNumberOfBits ))
87
+ } else {
88
+ numberOfPackets , _ := p .Chomp (11 )
89
+ return p .ReadNumSubPackets (numberOfPackets )
90
+ }
43
91
}
44
92
45
- func (p * parser ) ReadVersion () (int64 , bool ) {
46
- return p .Chomp (3 )
93
+ // ReadNumSubPackets reads the specified number of sub-packets
94
+ func (p * Parser ) ReadNumSubPackets (num int64 ) ([]int64 , bool ) {
95
+ var out []int64
96
+ for i := int64 (0 ); i < num ; i ++ {
97
+ o , _ := p .ReadSubPacket ()
98
+ out = append (out , o )
99
+ }
100
+ return out , true
47
101
}
48
102
49
- func (p * parser ) ReadMode () (int64 , bool ) {
50
- return p .Chomp (3 )
103
+ // ReadSubPacketsOfLength reads sub-packets limited to the number of bits
104
+ func (p * Parser ) ReadSubPacketsOfLength (lim int ) ([]int64 , bool ) {
105
+ var out []int64
106
+ lim = p .pos + lim
107
+ for p .pos < lim {
108
+ o , _ := p .ReadSubPacket ()
109
+ out = append (out , o )
110
+ }
111
+ return out , true
51
112
}
52
113
53
- func (p * parser ) ReadSub () (int64 , bool ) {
114
+ // ReadSubPacket reads a single sub-packet. However, since a sub-packet can have more sub-packets it is recursive via
115
+ // ReadNested calls back to itself.
116
+ func (p * Parser ) ReadSubPacket () (int64 , bool ) {
54
117
var out int64
55
118
var ok bool
56
119
v , _ := p .ReadVersion ()
@@ -121,55 +184,3 @@ func (p *parser) ReadSub() (int64, bool) {
121
184
122
185
return out , ok
123
186
}
124
-
125
- func (p * parser ) ReadNested () ([]int64 , bool ) {
126
- lengthTypeId , _ := p .Chomp (1 )
127
- if lengthTypeId == 0 {
128
- // Total number of bits
129
- totalNumberOfBits , _ := p .Chomp (15 )
130
- return p .ReadBits (int (totalNumberOfBits ))
131
- } else {
132
- numberOfPackets , _ := p .Chomp (11 )
133
- return p .ReadNumSubPackets (numberOfPackets )
134
- }
135
- }
136
-
137
- func (p * parser ) ReadNumSubPackets (num int64 ) ([]int64 , bool ) {
138
- var out []int64
139
- for i := int64 (0 ); i < num ; i ++ {
140
- o , _ := p .ReadSub ()
141
- out = append (out , o )
142
- }
143
- return out , true
144
- }
145
-
146
- func (p * parser ) ReadBits (lim int ) ([]int64 , bool ) {
147
- var out []int64
148
- lim = p .pos + lim
149
- for p .pos < lim {
150
- o , _ := p .ReadSub ()
151
- out = append (out , o )
152
- }
153
- return out , true
154
- }
155
-
156
- func part1 (file string ) int64 {
157
- data , err := hex .DecodeString (util .ReadLinesStrings (file )[0 ])
158
- util .Check (err )
159
- p := parser {data : data }
160
- p .ReadNumSubPackets (1 )
161
- return p .sumVersionNums
162
- }
163
-
164
- func part2 (file string ) int64 {
165
- return evalExpression (util .ReadLinesStrings (file )[0 ])
166
- }
167
-
168
- func evalExpression (text string ) int64 {
169
- data , err := hex .DecodeString (text )
170
- util .Check (err )
171
- p := parser {data : data }
172
- var out []int64
173
- out , _ = p .ReadNumSubPackets (1 )
174
- return out [0 ]
175
- }
0 commit comments