diff options
author | Tomasz Kramkowski <tomasz@kramkow.ski> | 2024-12-02 17:11:13 +0000 |
---|---|---|
committer | Tomasz Kramkowski <tomasz@kramkow.ski> | 2024-12-02 17:11:13 +0000 |
commit | b4339b5f69909f10db14dc22e9413ba498b4f3d4 (patch) | |
tree | d109c70eadc1b4ef96e77bdf638bc8da8ca6edf1 | |
parent | 9c340e9288d5ad90fa7d582ccafc15c61e985246 (diff) | |
download | aoc2024-b4339b5f69909f10db14dc22e9413ba498b4f3d4.tar.gz aoc2024-b4339b5f69909f10db14dc22e9413ba498b4f3d4.tar.xz aoc2024-b4339b5f69909f10db14dc22e9413ba498b4f3d4.zip |
Day 2
-rw-r--r-- | src/bin/2.rs | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/bin/2.rs b/src/bin/2.rs new file mode 100644 index 0000000..a674c9a --- /dev/null +++ b/src/bin/2.rs @@ -0,0 +1,97 @@ +use std::{ + error::Error, + fs::File, + io::{BufRead, BufReader}, + num::ParseIntError, +}; + +#[derive(PartialEq, Eq)] +enum Dir { + Ascending, + Descending, +} + +impl Dir { + fn characterise(a: i16, b: i16) -> Option<Self> { + let dir = if a < b { + Self::Ascending + } else { + Self::Descending + }; + if dir.diff_ok(a, b) { + Some(dir) + } else { + None + } + } + fn diff_ok(&self, a: i16, b: i16) -> bool { + let diff = match *self { + Self::Ascending => b - a, + Self::Descending => a - b, + }; + diff >= 1 && diff <= 3 + } +} + +fn p1cond(report: &[i16]) -> bool { + if report.len() <= 1 { + return true; + } + let Some(dir) = Dir::characterise(report[0], report[1]) else { + return false; + }; + for win in report[1..].windows(2) { + if !dir.diff_ok(win[0], win[1]) { + return false; + } + } + return true; +} + +fn p2cond(report: &[i16]) -> bool { + if report.len() <= 2 { + // One element can always be removed to make a safe report + return true; + } + 'outer: for skip_i in 0..report.len() { + let it = + report + .iter() + .copied() + .enumerate() + .filter_map(|(i, e)| if i != skip_i { Some(e) } else { None }); + let mut pairs = it.clone().zip(it.skip(1)); + let Some((a, b)) = pairs.next() else { + continue; + }; + let Some(dir) = Dir::characterise(a, b) else { + continue; + }; + for (a, b) in pairs { + if !dir.diff_ok(a, b) { + continue 'outer; + } + } + return true; + } + return false; +} + +fn main() -> Result<(), Box<dyn Error>> { + let f = File::open("input/2")?; + let f = BufReader::new(f); + let mut input = Vec::new(); + for line in f.lines() { + let elems = line? + .trim_end() + .split(' ') + .map(str::parse::<i16>) + .collect::<Result<Vec<_>, ParseIntError>>()? + .into_boxed_slice(); + input.push(elems); + } + let input = input.into_boxed_slice(); + println!("{}", input.iter().filter(|e| p1cond(*e)).count()); + println!("{}", input.iter().filter(|e| p2cond(*e)).count()); + Ok(()) +} |