diff --git a/src/day5/main.rs b/src/day5/main.rs index ae03f91..6c30a19 100644 --- a/src/day5/main.rs +++ b/src/day5/main.rs @@ -20,65 +20,93 @@ impl Extend> for RangeInclusive { } } +struct ReduceUtilFold +where + P: FnMut(Over::Item, Option) -> (Option, Option), +{ + over: Over, + cur: Option, + perdicate: P, +} + +impl ReduceUtilFold +where + P: FnMut(Over::Item, Option) -> (Option, Option), +{ + fn new(over: Over, perdicate: P) -> ReduceUtilFold { + ReduceUtilFold { + over, + perdicate, + cur: None, + } + } +} + +impl< + Return, + Over: Iterator, + P: FnMut(Over::Item, Option) -> (Option, Option), +> Iterator for ReduceUtilFold +{ + type Item = Return; + fn next(&mut self) -> Option { + let mut first: Option = None; + std::mem::swap(&mut first, &mut self.cur); + let mut first = first.or_else(|| self.over.next())?; + loop { + let (cont, ret) = (self.perdicate)(first, self.over.next()); + if ret.is_some() { + self.cur = cont; + return ret; + } + first = cont?; + } + } +} + fn main() -> Result<()> { let text = fs::read_to_string("src/day5/act.txt")?; - let mut valid_ids: Vec>> = text + let mut valid_ids: Vec> = text .split("\n") .take_while(|s| s.len() > 0) .map(|s| { let mut v = s.split('-').map(|a| a.parse().unwrap()); let start: u64 = v.next().unwrap(); let end: u64 = v.next().unwrap(); - return Some(start..=end); + return start..=end; }) .collect(); + valid_ids.sort_by(|a, b| a.start().cmp(b.start())); - let mut expanded = true; - while expanded { - expanded = false; - for i in 0..valid_ids.len() { - let range_to_extend = &valid_ids[i]; - if range_to_extend.is_some() { - let mut range_to_extend = valid_ids[i].as_ref().unwrap().clone(); - for j in (i + 1)..valid_ids.len() { - if let Some(maybe_comp) = valid_ids[j].as_ref() { - if let Some(extended) = range_to_extend.extend(&maybe_comp) { - println!( - "{:?} expanded by {:?} into {:?}", - range_to_extend, maybe_comp, extended - ); - expanded = true; - range_to_extend = extended; - valid_ids[j] = None; - } - } - } - valid_ids[i] = Some(range_to_extend); + let valid_ids: Vec> = ReduceUtilFold::new(valid_ids.into_iter(), |a, b| { + if let Some(b) = b { + if let Some(extended) = a.extend(&b) { + (Some(extended), None) + } else { + (Some(b), Some(a)) } + } else { + (None, Some(a)) } - valid_ids = valid_ids.into_iter().filter(|a| a.is_some()).collect(); - } + }) + .collect(); - let valid_ids = valid_ids.into_iter().map(|a| a.unwrap()); - - valid_ids.clone().for_each(|a| println!("{:?}", a)); - - let ids_to_check = text + let fresh_ids = text .split("\n") .skip_while(|s| s.len() > 0) .skip(1) .filter(|s| s.len() > 0) .fold(0, |sum, line| { let i: u64 = line.parse().unwrap(); - sum + valid_ids.clone().any(|range| range.contains(&i)) as i64 + sum + valid_ids.iter().any(|range| range.contains(&i)) as i64 }); - let num_valid_ids = valid_ids.fold(0, |sum, range_id| { + let num_valid_ids = valid_ids.iter().fold(0, |sum, range_id| { sum + range_id.end() - range_id.start() + 1 }); - println!("sol1: {}! sol2: {}", ids_to_check, num_valid_ids); + println!("sol1: {}! sol2: {}", fresh_ids, num_valid_ids); Ok(()) }