@@ -42,7 +42,56 @@ pub fn part_one(input: &str) -> Option<u32> {
4242}
4343
4444pub fn part_two ( input : & str ) -> Option < u32 > {
45- None
45+ let parts = input. splitn ( 2 , "\n \n " ) . collect :: < Vec < & str > > ( ) ;
46+ let rules_section = parts[ 0 ] ;
47+ let updates_section = parts[ 1 ] ;
48+ let rules: Vec < ( i32 , i32 ) > = rules_section
49+ . lines ( )
50+ . map ( |line| {
51+ let l: Vec < & str > = line. splitn ( 2 , '|' ) . collect ( ) ;
52+ ( l[ 0 ] . parse ( ) . unwrap ( ) , l[ 1 ] . parse ( ) . unwrap ( ) )
53+ } )
54+ . collect ( ) ;
55+
56+ let updates: Vec < Vec < i32 > > = updates_section
57+ . lines ( )
58+ . map ( |line| {
59+ line. split ( ',' )
60+ . filter_map ( |x| x. parse :: < i32 > ( ) . ok ( ) )
61+ . collect :: < Vec < i32 > > ( )
62+ } )
63+ . collect ( ) ;
64+
65+ updates
66+ . iter ( )
67+ . filter ( |update| {
68+ // combinations will keep pairs in their relative ordering from the original vector
69+ // keep all updates with any invalid pair
70+ update. iter ( ) . combinations ( 2 ) . any ( |pair| {
71+ let first = pair[ 0 ] ;
72+ let second = pair[ 1 ] ;
73+ let invalid = rules. iter ( ) . any ( |( x, y) | first == y && second == x) ;
74+
75+ invalid
76+ } )
77+ } )
78+ . map ( |update| {
79+ let mut sorted_update = update. clone ( ) ;
80+ // if a pair is invalid, swap them
81+ sorted_update. sort_by ( |first, second| {
82+ if rules. iter ( ) . any ( |( x, y) | first == y && second == x) {
83+ std:: cmp:: Ordering :: Less
84+ } else {
85+ std:: cmp:: Ordering :: Equal
86+ }
87+ } ) ;
88+
89+ sorted_update
90+ } )
91+ . map ( |update| update[ update. len ( ) / 2 ] )
92+ . sum :: < i32 > ( )
93+ . try_into ( )
94+ . ok ( )
4695}
4796
4897#[ cfg( test) ]
@@ -58,6 +107,6 @@ mod tests {
58107 #[ test]
59108 fn test_part_two ( ) {
60109 let result = part_two ( & advent_of_code:: template:: read_file ( "examples" , DAY ) ) ;
61- assert_eq ! ( result, None ) ;
110+ assert_eq ! ( result, Some ( 123 ) ) ;
62111 }
63112}
0 commit comments