11use aoc_rust_common:: Solution ;
22use std:: fmt:: Display ;
33use std:: collections:: { HashMap , HashSet } ;
4- use serde_scan:: scan;
4+ use nom:: {
5+ bytes:: complete:: tag,
6+ character:: complete:: anychar,
7+ sequence:: { preceded, separated_pair} ,
8+ IResult ,
9+ } ;
510
611pub struct Day07 ;
712
813type Step = char ;
914
15+ fn parse_dependency ( input : & str ) -> IResult < & str , ( Step , Step ) > {
16+ let ( input, _) = tag ( "Step " ) ( input) ?;
17+ let ( input, req) = anychar ( input) ?;
18+ let ( input, _) = tag ( " must be finished before step " ) ( input) ?;
19+ let ( input, step) = anychar ( input) ?;
20+ let ( input, _) = tag ( " can begin." ) ( input) ?;
21+ Ok ( ( input, ( req, step) ) )
22+ }
23+
1024fn get_deps ( input : & str ) -> ( HashSet < Step > , HashMap < Step , HashSet < Step > > ) {
1125 let mut all_steps = HashSet :: new ( ) ;
1226 let mut requirements: HashMap < Step , HashSet < Step > > = HashMap :: new ( ) ;
1327
1428 for line in input. lines ( ) {
15- let ( req , step ) : ( Step , Step ) = scan ! ( "Step {} must be finished before step {} can begin." <- line) . unwrap ( ) ;
29+ let ( _ , ( req , step ) ) = parse_dependency ( line) . unwrap ( ) ;
1630 all_steps. insert ( req) ;
1731 all_steps. insert ( step) ;
1832 requirements. entry ( step) . or_default ( ) . insert ( req) ;
@@ -39,6 +53,8 @@ impl Solution for Day07 {
3953 if let Some ( next_step) = available. first ( ) {
4054 ordered. push ( * next_step) ;
4155 done. insert ( * next_step) ;
56+ } else {
57+ break ; // No available steps
4258 }
4359 }
4460 Box :: new ( ordered)
@@ -56,7 +72,7 @@ impl Solution for Day07 {
5672 . filter ( |s| !done. contains ( s) && !workers. iter ( ) . any ( |& ( _, w) | w == * * s) )
5773 . filter ( |s| requirements. get ( s) . map_or ( true , |reqs| reqs. is_subset ( & done) ) )
5874 . copied ( ) . collect ( ) ;
59- available. sort_unstable ( ) ;
75+ available. sort_unstable_by ( |a , b| b . cmp ( a ) ) ; // So we can pop from the end
6076
6177 for ( time_free, step) in workers. iter_mut ( ) . filter ( |( tf, _) | * tf <= time) {
6278 if * step != '.' { done. insert ( * step) ; }
@@ -66,8 +82,20 @@ impl Solution for Day07 {
6682 * time_free = time + base_duration + ( next_step as u32 - 'A' as u32 + 1 ) ;
6783 }
6884 }
69- time = workers. iter ( ) . filter ( |& & ( _, s) | s != '.' ) . map ( |( tf, _) | * tf) . min ( ) . unwrap_or ( time) ;
85+
86+ let next_event_time = workers. iter ( ) . filter ( |& & ( _, s) | s != '.' ) . map ( |( tf, _) | * tf) . min ( ) ;
87+ if let Some ( t) = next_event_time {
88+ time = t;
89+ } else if !available. is_empty ( ) {
90+ // All workers are idle, but there are still steps to do. This can happen if we are waiting for a dependency.
91+ // In this case, we need to advance time.
92+ time += 1 ;
93+ } else if done. len ( ) == all_steps. len ( ) {
94+ break ;
95+ }
7096 }
71- Box :: new ( time)
97+
98+ let final_time = workers. iter ( ) . map ( |( tf, _) | * tf) . max ( ) . unwrap_or ( time) ;
99+ Box :: new ( final_time)
72100 }
73101}
0 commit comments