2018-12-04 18:36:08 +01:00
#[ macro_use ] extern crate text_io ;
2018-12-05 01:41:55 +01:00
use std ::collections ::HashMap ;
2018-12-04 20:36:22 +01:00
mod types ;
use types ::* ;
2018-12-04 18:36:08 +01:00
fn parse_action ( input : & String ) -> GuardAction {
2018-12-04 20:36:22 +01:00
match input . chars ( ) . next ( ) . unwrap ( ) {
'f' = > GuardAction ::FallAsleep ,
'w' = > GuardAction ::WakeUp ,
'G' = > {
2018-12-04 19:33:07 +01:00
let gid : i32 ;
scan! ( input . bytes ( ) = > " Guard #{} begins shift " , gid ) ;
GuardAction ::BeginShift ( gid )
}
2018-12-04 20:36:22 +01:00
_ = > std ::panic! ( )
2018-12-04 19:33:07 +01:00
}
2018-12-04 18:36:08 +01:00
}
2018-12-05 01:41:55 +01:00
fn event_from_line ( line : String ) -> Event {
2018-12-04 18:36:08 +01:00
let ( month , day , hour , minute , unparsed_action ) : ( i32 , i32 , i32 , i32 , String ) ;
2018-12-05 01:41:55 +01:00
// I’m only adding the \n here to use it as a marker for scan!,
// which would otherwise stop at the first space.
let line2 = line . to_string ( ) + " \n " ;
scan! ( line2 . bytes ( ) = > " [1518-{}-{} {}:{}] {} \n " , month , day , hour , minute , unparsed_action ) ;
2018-12-04 20:36:22 +01:00
let datetime = types ::DateTime ::new ( month , day , hour , minute ) ;
2018-12-04 18:36:08 +01:00
return Event ::new ( datetime , parse_action ( & unparsed_action ) ) ;
}
2018-12-05 01:41:55 +01:00
fn events_to_shifts ( events : Vec < Event > ) -> Vec < Shift > {
let mut shifts : Vec < Shift > = Vec ::new ( ) ;
// It was easier to parse by just adding a dummy shift at the beginning
let mut current_shift = Shift ::new ( - 1 ) ;
for event in events {
match event . action {
GuardAction ::BeginShift ( gid ) = > {
shifts . push ( current_shift ) ;
current_shift = Shift ::new ( gid ) ;
} ,
_ = > current_shift . events . push ( event )
}
}
// Remove the dummy we added earlier
shifts . remove ( 0 ) ;
return shifts ;
}
fn group_shifts_by_guard ( shifts : Vec < Shift > ) -> HashMap < i32 , Vec < Shift > > {
let mut shifts_by_guard : HashMap < i32 , Vec < Shift > > = HashMap ::new ( ) ;
for shift in shifts {
let shifts_for_guard = shifts_by_guard . entry ( shift . guard . id ) . or_insert_with ( Vec ::new ) ;
shifts_for_guard . push ( shift ) ;
}
return shifts_by_guard ;
}
fn calculate_sleep ( events : Vec < Event > ) -> Vec < bool > {
let mut minutes = vec! [ false ; 60 ] ;
let mut sleeping = false ;
let mut last = 0 ;
for e in events {
if sleeping {
for i in ( last .. e . datetime . minute ) {
minutes [ i as usize ] = true ;
}
}
last = e . datetime . minute ;
sleeping = match e . action {
GuardAction ::FallAsleep = > true ,
_ = > false
}
}
return minutes ;
}
2018-12-04 18:36:08 +01:00
fn main ( ) {
2018-12-05 01:41:55 +01:00
let lines : Vec < & str > = include_str! ( " ../input " ) . split ( " \n " ) . collect ( ) ;
2018-12-04 18:36:08 +01:00
let mut events : Vec < Event > = Vec ::new ( ) ;
for line in lines {
2018-12-05 01:41:55 +01:00
events . push ( event_from_line ( line . to_string ( ) ) ) ;
}
events . sort ( ) ;
let shifts = events_to_shifts ( events ) ;
/*
for shift in shifts {
for event in shift . events {
println! ( " {} " , event . datetime ) ;
}
2018-12-04 18:36:08 +01:00
}
2018-12-05 01:41:55 +01:00
* /
let shifts_by_guard = group_shifts_by_guard ( shifts ) ;
let sleepy_guard = find_sleepy_guard ( & shifts_by_guard ) ;
2018-12-04 18:36:08 +01:00
}
2018-12-04 20:36:22 +01:00