@@ -4,7 +4,7 @@ pub fn run() {
4
4
let raw_input = util:: read_input ( "inputs/day16.txt" ) . unwrap ( ) ;
5
5
let input = process ( & raw_input) ;
6
6
7
- println ! ( "{:?}" , input) ;
7
+ println ! ( "Part 1: {:?}" , part_1 ( & input) ) ;
8
8
}
9
9
10
10
fn process ( input : & str ) -> Vec < u8 > {
@@ -50,16 +50,71 @@ fn parse_literal(mut bytes: &[u8]) -> &[u8] {
50
50
continues
51
51
} )
52
52
. count ( ) ;
53
-
53
+
54
54
bytes
55
55
}
56
56
57
- fn parse_packet ( bytes : & [ u8 ] ) -> ( & [ u8 ] , u8 ) {
57
+ fn parse_operator ( mut bytes : & [ u8 ] ) -> ( & [ u8 ] , u64 ) {
58
+ let length_type = bytes[ 0 ] ;
59
+ bytes = & bytes[ 1 ..] ;
60
+
61
+ match length_type {
62
+ 0 => {
63
+ let l = bytes
64
+ . iter ( )
65
+ . take ( 15 )
66
+ . fold ( 0 , |l, & bit| ( ( l as usize ) << 1 ) ^ bit as usize ) ;
67
+ bytes = & bytes[ 15 ..] ;
68
+ let rest = & bytes[ l..] ;
69
+ let mut sub_packets = & bytes[ 0 ..l] ;
70
+ let mut sub_packet_version_count = 0 ;
71
+ while !sub_packets. is_empty ( ) {
72
+ let ( new_sub_packets, vers) = parse_packet ( sub_packets) ;
73
+ sub_packet_version_count += vers;
74
+ sub_packets = new_sub_packets;
75
+ }
76
+ ( rest, sub_packet_version_count)
77
+ }
78
+ 1 => {
79
+ let desired_sub_packet_count = bytes
80
+ . iter ( )
81
+ . take ( 11 )
82
+ . fold ( 0 , |l, & bit| ( ( l as u32 ) << 1 ) ^ bit as u32 ) ;
83
+ bytes = & bytes[ 11 ..] ;
84
+ let sub_packet_versions = ( 0 ..desired_sub_packet_count)
85
+ . map ( |_| {
86
+ let ( rem, vers) = parse_packet ( bytes) ;
87
+ bytes = rem;
88
+ vers
89
+ } )
90
+ . sum :: < u64 > ( ) ;
91
+
92
+ ( bytes, sub_packet_versions)
93
+ }
94
+ _ => panic ! ( "unreachable" ) ,
95
+ }
96
+ }
97
+
98
+ fn parse_packet ( bytes : & [ u8 ] ) -> ( & [ u8 ] , u64 ) {
58
99
let ( rest, curr_vers, packet_type) = parse_header ( bytes) ;
59
100
match packet_type {
60
- Type :: Literal => ( parse_literal ( rest) , curr_vers) ,
61
- Type :: Operator => todo ! ( )
101
+ Type :: Literal => ( parse_literal ( rest) , curr_vers as u64 ) ,
102
+ Type :: Operator => {
103
+ let ( rest, sub_packet_versions) = parse_operator ( rest) ;
104
+ ( rest, curr_vers as u64 + sub_packet_versions)
105
+ }
106
+ }
107
+ }
108
+
109
+ fn part_1 ( mut input : & [ u8 ] ) -> u64 {
110
+ let mut vers_sum = 0 ;
111
+ while input. len ( ) > 6 {
112
+ let res = parse_packet ( input) ;
113
+ input = res. 0 ;
114
+ vers_sum += res. 1 ;
62
115
}
116
+
117
+ vers_sum
63
118
}
64
119
65
120
#[ derive( Debug , PartialEq , Eq ) ]
@@ -109,10 +164,19 @@ mod tests {
109
164
110
165
#[ test]
111
166
fn test_parse_literal ( ) {
112
- let rem = parse_literal ( & [ 1 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1 ] ) ;
167
+ let rem = parse_literal ( & [ 1 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1 ] ) ;
113
168
assert ! ( rem. is_empty( ) ) ;
114
169
115
- let rem = parse_literal ( & [ 1 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 0 , 1 ] ) ;
116
- assert_eq ! ( rem, & [ 1 , 0 , 1 ] ) ;
170
+ let rem = parse_literal ( & [ 1 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 0 , 1 ] ) ;
171
+ assert_eq ! ( rem, & [ 1 , 0 , 1 ] ) ;
172
+ }
173
+
174
+ #[ test]
175
+ fn test_part_1 ( ) {
176
+ let input = "8A004A801A8002F478" ;
177
+ let input = process ( input) ;
178
+ let res = part_1 ( & input) ;
179
+ assert_eq ! ( res, 16 ) ;
180
+
117
181
}
118
182
}
0 commit comments