summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tomasz@kramkow.ski>2024-12-02 17:11:13 +0000
committerTomasz Kramkowski <tomasz@kramkow.ski>2024-12-02 17:11:13 +0000
commitb4339b5f69909f10db14dc22e9413ba498b4f3d4 (patch)
treed109c70eadc1b4ef96e77bdf638bc8da8ca6edf1
parent9c340e9288d5ad90fa7d582ccafc15c61e985246 (diff)
downloadaoc2024-b4339b5f69909f10db14dc22e9413ba498b4f3d4.tar.gz
aoc2024-b4339b5f69909f10db14dc22e9413ba498b4f3d4.tar.xz
aoc2024-b4339b5f69909f10db14dc22e9413ba498b4f3d4.zip
Day 2
-rw-r--r--src/bin/2.rs97
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(())
+}