1- fn parse_input (
2- input : & str ,
3- ) -> ( Vec < ( & str , Vec < ( u32 , u32 ) > ) > , Vec < u32 > , Vec < Vec < u32 > > ) {
1+ use std:: cmp:: Reverse ;
2+ use std:: collections:: BinaryHeap ;
3+
4+ type Ranges = Vec < ( u64 , u64 ) > ;
5+ type Rule < ' a > = ( & ' a str , Ranges ) ;
6+ type Ticket = Vec < u64 > ;
7+ type Tickets = Vec < Ticket > ;
8+
9+ fn parse_input ( input : & str ) -> ( Vec < Rule > , Ticket , Tickets ) {
410 let sections: Vec < & str > =
511 input. trim ( ) . split ( "\n \n " ) . collect :: < Vec < & str > > ( ) ;
6- let rules: Vec < ( & str , Vec < ( u32 , u32 ) > ) > = sections[ 0 ]
12+ let rules: Vec < Rule > = sections[ 0 ]
713 . trim ( )
814 . lines ( )
915 . map ( |s| {
@@ -21,16 +27,15 @@ fn parse_input(
2127 } )
2228 . collect ( ) ;
2329
24- let ticket: Vec < u32 > = sections[ 1 ]
30+ let ticket: Vec < u64 > = sections[ 1 ]
2531 . lines ( )
26- . skip ( 1 )
27- . next ( )
32+ . nth ( 1 )
2833 . unwrap ( )
2934 . split ( ',' )
3035 . map ( |s| s. parse ( ) . unwrap ( ) )
3136 . collect ( ) ;
3237
33- let nearby_tickets: Vec < Vec < u32 > > = sections[ 2 ]
38+ let nearby_tickets: Vec < Vec < u64 > > = sections[ 2 ]
3439 . lines ( )
3540 . skip ( 1 )
3641 . map ( |s| s. split ( ',' ) . map ( |s| s. parse ( ) . unwrap ( ) ) . collect ( ) )
@@ -39,23 +44,86 @@ fn parse_input(
3944 ( rules, ticket, nearby_tickets)
4045}
4146
42- pub fn part_one ( input : & str ) -> u32 {
47+ pub fn part_one ( input : & str ) -> u64 {
4348 let ( rules, _, nearby_tickets) = parse_input ( input) ;
44-
45- let is_invalid = |value : u32 | -> bool {
49+ let is_invalid = |value : u64 | -> bool {
4650 rules. iter ( ) . all ( |( _, ranges) | {
4751 ranges. iter ( ) . all ( |& ( min, max) | value < min || value > max)
4852 } )
4953 } ;
50-
5154 nearby_tickets
5255 . iter ( )
5356 . flat_map ( |ticket| ticket. iter ( ) . filter ( |& value| is_invalid ( * value) ) )
5457 . sum ( )
5558}
5659
57- pub fn part_two ( input : & str ) -> usize {
58- 0
60+ fn determined_ticket_fields ( input : & str ) -> Vec < ( & str , u64 ) > {
61+ let ( rules, ticket, nearby_tickets) = parse_input ( input) ;
62+
63+ let tickets: Vec < Vec < u64 > > = nearby_tickets
64+ . into_iter ( )
65+ . filter ( |ticket| {
66+ ticket. iter ( ) . all ( |& value| {
67+ rules. iter ( ) . any ( |( _, ranges) | {
68+ ranges
69+ . iter ( )
70+ . any ( |& ( min, max) | value >= min && value <= max)
71+ } )
72+ } )
73+ } )
74+ . collect ( ) ;
75+
76+ let valids: Vec < Vec < Vec < bool > > > = tickets
77+ . iter ( )
78+ . map ( |ticket| {
79+ ticket
80+ . iter ( )
81+ . map ( |value| {
82+ rules
83+ . iter ( )
84+ . map ( |( _, ranges) | {
85+ ranges. iter ( ) . any ( |& ( min, max) | {
86+ * value >= min && * value <= max
87+ } )
88+ } )
89+ . collect ( )
90+ } )
91+ . collect ( )
92+ } )
93+ . collect ( ) ;
94+
95+ let h = valids. len ( ) ;
96+ let w = valids[ 0 ] . len ( ) ;
97+ let valid_fields: Vec < Vec < usize > > = ( 0 ..w)
98+ . map ( |x| {
99+ ( 0 ..rules. len ( ) )
100+ . filter ( |i| ( 0 ..h) . all ( |y| valids[ y] [ x] [ * i] ) )
101+ . collect ( )
102+ } )
103+ . collect ( ) ;
104+
105+ let mut queue = BinaryHeap :: new ( ) ;
106+ let mut visited = vec ! [ false ; valid_fields. len( ) ] ;
107+
108+ for ( i, fields) in valid_fields. iter ( ) . enumerate ( ) {
109+ queue. push ( Reverse ( ( fields. len ( ) , i, fields) ) ) ;
110+ }
111+
112+ let mut ticket_fields = Vec :: new ( ) ;
113+ while let Some ( Reverse ( ( _, i, fields) ) ) = queue. pop ( ) {
114+ let v = fields. iter ( ) . find ( |& & v| !visited[ v] ) . unwrap ( ) ;
115+ visited[ * v] = true ;
116+ ticket_fields. push ( ( rules[ * v] . 0 , ticket[ i] ) ) ;
117+ }
118+ ticket_fields
119+ }
120+
121+ pub fn part_two ( input : & str ) -> u64 {
122+ determined_ticket_fields ( input)
123+ . iter ( )
124+ . filter ( |( s, _) | s. starts_with ( "departure" ) )
125+ . map ( |( _, v) | * v)
126+ . product ( )
59127}
60128
61129#[ cfg( test) ]
@@ -85,4 +153,18 @@ fn example_part_two() {
85153 "15,1,5\n " ,
86154 "5,14,9"
87155 ) ;
156+
157+ let fields = determined_ticket_fields ( & input) ;
158+ assert ! ( fields
159+ . iter( )
160+ . find( |( n, v) | n == & "class" && v == & 12 )
161+ . is_some( ) ) ;
162+ assert ! ( fields
163+ . iter( )
164+ . find( |( n, v) | n == & "row" && v == & 11 )
165+ . is_some( ) ) ;
166+ assert ! ( fields
167+ . iter( )
168+ . find( |( n, v) | n == & "seat" && v == & 13 )
169+ . is_some( ) ) ;
88170}
0 commit comments