11advent_of_code:: solution!( 3 ) ;
22
3- use advent_of_code:: maneatingape:: parse:: * ;
4-
5- use regex:: Regex ;
6-
73enum Command {
84 Enable ,
95 Disable ,
106 Multiply ( u32 , u32 ) ,
117}
128
139fn parse_data ( input : & str ) -> Vec < Command > {
14- let mut commands = vec ! [ ] ;
10+ ( 0 ..input. len ( ) )
11+ . filter_map ( |i| {
12+ let value = & input[ i..] ;
13+
14+ // Enable
15+ if value. starts_with ( "do()" ) {
16+ return Some ( Command :: Enable ) ;
17+ }
1518
16- let mul_re = Regex :: new ( r"^mul\((\d{1,3}),(\d{1,3})\)" ) . unwrap ( ) ;
19+ // Disable
20+ if value. starts_with ( "don't()" ) {
21+ return Some ( Command :: Disable ) ;
22+ }
1723
18- for i in 0 ..input. len ( ) {
19- if input[ i..] . starts_with ( "mul" ) {
20- if let Some ( m) = mul_re. captures ( & input[ i..] ) {
21- let [ x, y] = m. extract ( ) . 1 . map ( |x| x. unsigned ( ) ) ;
22- commands. push ( Command :: Multiply ( x, y) ) ;
24+ // Multiply
25+ if value. starts_with ( "mul(" ) {
26+ let mut first_number = None ;
27+ let mut number = 0 ;
28+
29+ for c in value. bytes ( ) . skip ( 4 ) {
30+ match c {
31+ b'0' ..=b'9' => {
32+ if number > 1000 {
33+ return None ;
34+ }
35+
36+ number = number * 10 + ( c - b'0' ) as u32 ;
37+ }
38+ b',' => {
39+ if number == 0 || first_number. is_some ( ) {
40+ return None ;
41+ }
42+
43+ first_number = Some ( number) ;
44+ number = 0 ;
45+ }
46+ b')' => {
47+ if number == 0 {
48+ return None ;
49+ }
50+
51+ return Some ( Command :: Multiply ( first_number?, number) ) ;
52+ }
53+ _ => {
54+ return None ;
55+ }
56+ }
57+ }
2358 }
24- } else if input[ i..] . starts_with ( "do()" ) {
25- commands. push ( Command :: Enable ) ;
26- } else if input[ i..] . starts_with ( "don't()" ) {
27- commands. push ( Command :: Disable ) ;
28- }
29- }
3059
31- commands
60+ None
61+ } )
62+ . collect ( )
3263}
3364
3465pub fn part_one ( input : & str ) -> Option < u32 > {
@@ -48,16 +79,15 @@ pub fn part_one(input: &str) -> Option<u32> {
4879pub fn part_two ( input : & str ) -> Option < u32 > {
4980 let data = parse_data ( input) ;
5081
51- let mut enabled = true ;
52-
53- let mut result = 0 ;
54- for c in data {
55- match c {
56- Command :: Multiply ( x, y) => result += if enabled { x * y } else { 0 } ,
57- Command :: Enable => enabled = true ,
58- Command :: Disable => enabled = false ,
59- }
60- }
82+ let result = data
83+ . into_iter ( )
84+ . fold ( ( 0 , true ) , |acc, c| match ( c, acc. 1 ) {
85+ ( Command :: Enable , false ) => ( acc. 0 , true ) ,
86+ ( Command :: Disable , true ) => ( acc. 0 , false ) ,
87+ ( Command :: Multiply ( x, y) , true ) => ( acc. 0 + x * y, true ) ,
88+ _ => acc,
89+ } )
90+ . 0 ;
6191
6292 Some ( result)
6393}
@@ -68,13 +98,15 @@ mod tests {
6898
6999 #[ test]
70100 fn test_part_one ( ) {
71- let result = part_one ( & advent_of_code:: template:: read_file ( "examples" , DAY ) ) ;
101+ let input = advent_of_code:: template:: read_file ( "examples" , DAY ) ;
102+ let result = part_one ( & input) ;
72103 assert_eq ! ( result, Some ( 161 ) ) ;
73104 }
74105
75106 #[ test]
76107 fn test_part_two ( ) {
77- let result = part_two ( & advent_of_code:: template:: read_file ( "examples" , DAY ) ) ;
108+ let input = advent_of_code:: template:: read_file ( "examples" , DAY ) ;
109+ let result = part_two ( & input) ;
78110 assert_eq ! ( result, Some ( 48 ) ) ;
79111 }
80112}
0 commit comments