1- pub fn parse_input ( input : & str ) -> Vec < Problem > {
1+ // split into columns. the operator in the last line indicates the start of each column
2+ pub fn parse_input ( input : & str ) -> Vec < Problem < ' _ > > {
23 let mut lines: Vec < & str > = input. lines ( ) . collect ( ) ;
3- let mut problems: Vec < Problem > = lines
4- . pop ( )
5- . unwrap ( )
6- . split_whitespace ( )
7- . map ( Operation :: from)
8- . map ( |operation| Problem {
9- operation,
10- numbers : vec ! [ ] ,
11- } )
12- . collect ( ) ;
134
14- for line in lines {
15- for ( i, n) in line
16- . split_whitespace ( )
17- . map ( |s| s. parse ( ) . unwrap ( ) )
18- . enumerate ( )
19- {
20- problems[ i] . numbers . push ( n) ;
21- }
22- }
5+ let op_line = lines. pop ( ) . unwrap ( ) ;
6+
7+ let mut indexes: Vec < _ > = op_line
8+ . char_indices ( )
9+ . filter ( |( _i, c) | !c. is_whitespace ( ) )
10+ . collect ( ) ;
11+ indexes. push ( ( op_line. len ( ) + 1 , '\n' ) ) ;
2312
24- problems
13+ indexes
14+ . windows ( 2 )
15+ . map ( |col| Problem {
16+ operation : Operation :: from ( col[ 0 ] . 1 ) ,
17+ column : lines
18+ . iter ( )
19+ . map ( |line| & line[ col[ 0 ] . 0 ..( col[ 1 ] . 0 - 1 ) ] )
20+ . collect ( ) ,
21+ } )
22+ . collect ( )
2523}
2624
2725#[ derive( Debug ) ]
28- pub struct Problem {
26+ pub struct Problem < ' a > {
2927 operation : Operation ,
30- numbers : Vec < u64 > ,
28+ column : Vec < & ' a str > ,
3129}
3230
3331#[ derive( Debug ) ]
@@ -36,33 +34,59 @@ pub enum Operation {
3634 Mul ,
3735}
3836
39- impl From < & str > for Operation {
40- fn from ( s : & str ) -> Self {
41- if s == "+" {
37+ impl From < char > for Operation {
38+ fn from ( c : char ) -> Self {
39+ if c == '+' {
4240 Operation :: Add
43- } else if s == "*" {
41+ } else if c == '*' {
4442 Operation :: Mul
4543 } else {
4644 panic ! ( )
4745 }
4846 }
4947}
5048
51- impl Problem {
52- fn solve ( & self ) -> u64 {
49+ impl Problem < ' _ > {
50+ fn solve1 ( & self ) -> u64 {
51+ let numbers: Vec < u64 > = self
52+ . column
53+ . iter ( )
54+ . map ( |s| s. trim ( ) . parse ( ) . unwrap ( ) )
55+ . collect ( ) ;
56+ match self . operation {
57+ Operation :: Add => numbers. iter ( ) . fold ( 0 , |acc, e| acc + * e) ,
58+ Operation :: Mul => numbers. iter ( ) . fold ( 1 , |acc, e| acc * * e) ,
59+ }
60+ }
61+
62+ // for part 2, the digits are in columns
63+ fn solve2 ( & self ) -> u64 {
64+ let numbers: Vec < u64 > = ( 0 ..self . column [ 0 ] . len ( ) )
65+ . map ( |i| {
66+ let mut n = 0 ;
67+ for row in & self . column {
68+ let digit = row. chars ( ) . nth ( i) . unwrap ( ) ;
69+ if !digit. is_whitespace ( ) {
70+ n *= 10 ;
71+ n += digit. to_digit ( 10 ) . unwrap ( ) ;
72+ }
73+ }
74+ n as u64
75+ } )
76+ . collect ( ) ;
5377 match self . operation {
54- Operation :: Add => self . numbers . iter ( ) . fold ( 0 , |acc, e| acc + * e) ,
55- Operation :: Mul => self . numbers . iter ( ) . fold ( 1 , |acc, e| acc * * e) ,
78+ Operation :: Add => numbers. iter ( ) . fold ( 0 , |acc, e| acc + * e) ,
79+ Operation :: Mul => numbers. iter ( ) . fold ( 1 , |acc, e| acc * * e) ,
5680 }
5781 }
5882}
5983
6084pub fn part1 ( input : & [ Problem ] ) -> u64 {
61- input. iter ( ) . map ( |p| p. solve ( ) ) . sum ( )
85+ input. iter ( ) . map ( |p| p. solve1 ( ) ) . sum ( )
6286}
6387
64- pub fn part2 ( input : & [ Problem ] ) -> & str {
65- "unimplemented"
88+ pub fn part2 ( input : & [ Problem ] ) -> u64 {
89+ input . iter ( ) . map ( |p| p . solve2 ( ) ) . sum ( )
6690}
6791
6892#[ test]
@@ -75,4 +99,5 @@ fn test() {
7599" ;
76100 let input = parse_input ( test_input) ;
77101 assert_eq ! ( 4277556 , part1( & input) ) ;
102+ assert_eq ! ( 3263827 , part2( & input) ) ;
78103}
0 commit comments