diff --git a/src/days.rs b/src/days.rs index ddf2ee7..f591d7d 100644 --- a/src/days.rs +++ b/src/days.rs @@ -17,7 +17,7 @@ pub mod d16; pub mod d17; pub mod d18; pub mod d19; -// pub mod d20; +pub mod d20; // pub mod d21; // pub mod d22; // pub mod d23; diff --git a/src/days/d20.rs b/src/days/d20.rs new file mode 100644 index 0000000..7afbffc --- /dev/null +++ b/src/days/d20.rs @@ -0,0 +1,74 @@ +#![allow(unused_imports)] +use std::ops::RangeInclusive; +use crate::prelude::*; + +pub type I = Vec>; +pub type O = u64; + +fn _parse (data: &str) -> I { + data.trim().lines().map(|e| e.trim().split_once('-').map(|(a, b)| a.parse().unwrap()..=b.parse().unwrap()).unwrap()).collect() +} + +fn _silver (mut data: I) -> O { + data.sort_by_key(|d| *d.start()); + let mut start = data[0].end() + 1; + + for d in &data[1..] { + if *d.start() <= start { + start = start.max(d.end() + 1); + continue; + } + + return start; + } + + Default::default() +} + +fn _gold (mut data: I) -> O { + data.sort_by_key(|d| *d.start()); + let mut start = data[0].end() + 1; + let mut gaps = 0; + + for d in &data[1..] { + if *d.start() <= start { + start = start.max(d.end() + 1); + continue; + } + + let l = d.start() - start; + gaps += l; + start = d.end() + 1; + } + + // doesn't matter in my input, but for a general case where there's a gap between last + // blocked ip and last possible ip will matter. check is here to ensure it won't overflow + if start <= u32::MAX as u64 { + gaps += u32::MAX as u64 - start; + } + gaps +} + +#[cfg(test)] +mod test { + use super::*; + + fn read () -> I { + let data = inc!(20); + _parse(data) + } + + #[test] + fn silver () { + let data = read(); + let ans = _silver(data); + assert_eq!(ans, 17348574) + } + + #[test] + fn gold () { + let data = read(); + let ans = _gold(data); + assert_eq!(ans, 104) + } +}