diff --git a/src/days.rs b/src/days.rs index 0958165..21b6c99 100644 --- a/src/days.rs +++ b/src/days.rs @@ -1,7 +1,7 @@ pub mod d1; pub mod d2; pub mod d3; -// pub mod d4; +pub mod d4; // pub mod d5; // pub mod d6; // pub mod d7; diff --git a/src/days/d4.rs b/src/days/d4.rs new file mode 100644 index 0000000..850f52a --- /dev/null +++ b/src/days/d4.rs @@ -0,0 +1,86 @@ +use crate::prelude::*; + +pub type T = (String, M, Vec, u32); +pub type I = Vec; +pub type O = u32; + +fn _parse (data: &str) -> I { + data.lines().map(|line| { + let mut parts = line.split('-').collect_vec(); + let last = parts.pop().unwrap(); + let rest = parts.join(" "); + let m = parts.into_iter().map(|p| p.chars()).flatten().counts(); + + let (number, checksum) = last.split_once('[').unwrap(); + + let number = number.parse().unwrap(); + let checksum = checksum.trim_matches(']').chars().collect(); + + (rest, m, checksum, number) + }).collect() +} + +fn _solve <'a> (data: &'a I) -> impl Iterator { + data.into_iter().filter_map(|(st, m, checksum, num)| { + let mut m = m.into_iter().collect_vec(); + + m.sort_by(|a, b| match b.1.cmp(&a.1) { + Or::Equal => a.0.cmp(&b.0), + e => e + }); + + if checksum.into_iter().zip(m.into_iter()).all(|(&l, (&r, _))| l == r) { + Some((st, num)) + } else { + None + } + }) +} + +fn _silver (data: &I) -> O { + _solve(data).map(|(_, num)| num).sum() +} + +fn _gold (data: &I) -> O { + *_solve(data).find(|(s, num)| { + + let mut s = s.chars().collect_vec(); + + for c in s.iter_mut() { + match *c { + ' ' => (), + a => { + *c = ((((a as u8 - b'a') as u32 + *num) % 26) + b'a' as u32) as u8 as char; + } + } + } + let s = s.into_iter().collect::(); + s.contains("north") + }).unwrap().1 +} + +#[cfg(test)] +mod test { + use super::*; + + fn read () -> I { + let data = inc!(4); + _parse(data) + } + + #[test] + fn silver () { + let data = read(); + let ans = _silver(&data); + + assert_eq!(ans, 278221) + } + + #[test] + fn gold () { + let data = read(); + let ans = _gold(&data); + + assert_eq!(ans, 267) + } +}