]> localhost Git - adventofcode2024.git/commitdiff
Complete day 2
authorJack Kinsey <j.jameskinsey@gmail.com>
Tue, 3 Dec 2024 07:01:58 +0000 (02:01 -0500)
committerJack Kinsey <j.jameskinsey@gmail.com>
Wed, 4 Dec 2024 03:23:15 +0000 (22:23 -0500)
src/day02.rs [new file with mode: 0644]
src/main.rs

diff --git a/src/day02.rs b/src/day02.rs
new file mode 100644 (file)
index 0000000..39148fd
--- /dev/null
@@ -0,0 +1,119 @@
+fn input() -> &'static str {
+    include_str!("../input/day02.txt")
+}
+
+fn parse(input: &str) -> Vec<Vec<i32>> {
+    input
+        .split_terminator('\n')
+        .map(|l| l.split_whitespace().map(|n| n.parse().unwrap()).collect())
+        .collect()
+}
+
+fn is_monotonic(d: &[i32]) -> bool {
+    let (inc, dec, _) = d
+        .iter()
+        .fold((0, 0, None as Option<i32>), |(inc, dec, k), n| match k {
+            Some(k) => {
+                if n - k > inc {
+                    (n - k, dec, Some(*n))
+                } else if n - k < dec {
+                    (inc, n - k, Some(*n))
+                } else {
+                    (inc, dec, Some(*n))
+                }
+            }
+            None => (inc, dec, Some(*n)),
+        });
+    inc > 0 && dec == 0 || inc == 0 && dec < 0
+}
+
+fn safe_gaps(d: &[i32]) -> bool {
+    d.iter()
+        .zip(d.iter().skip(1))
+        .map(|(l, &r)| l.abs_diff(r))
+        .all(|t| (1..=3).contains(&t))
+}
+
+fn is_safe(d: &[i32]) -> bool {
+    is_monotonic(d) && safe_gaps(d)
+}
+
+fn is_safe_dampened(d: &[i32]) -> bool {
+    is_safe(d)
+        || (0..d.len())
+            .map(|i| d.iter().take(i).chain(d.iter().skip(i + 1)))
+            .map(|v| is_safe(&v.copied().collect::<Vec<_>>()))
+            .any(|x| x)
+}
+
+pub fn part1() {
+    let vecs = parse(input());
+    let n = vecs.iter().map(|v| is_safe(v)).filter(|&x| x).count();
+    println!("Day 2 Part 1: {}", n);
+}
+
+pub fn part2() {
+    let vecs = parse(input());
+    let n = vecs
+        .iter()
+        .map(|v| is_safe_dampened(v))
+        .filter(|&x| x)
+        .count();
+    println!("Day 2 Part 2: {}", n);
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    const INPUT_STR: &str = concat!(
+        "7 6 4 2 1\n",
+        "1 2 7 8 9\n",
+        "9 7 6 2 1\n",
+        "1 3 2 4 5\n",
+        "8 6 4 4 1\n",
+        "1 3 6 7 9\n",
+    );
+
+    #[test]
+    fn test_parse() {
+        assert_eq!(
+            parse(INPUT_STR),
+            vec![
+                vec![7, 6, 4, 2, 1],
+                vec![1, 2, 7, 8, 9],
+                vec![9, 7, 6, 2, 1],
+                vec![1, 3, 2, 4, 5],
+                vec![8, 6, 4, 4, 1],
+                vec![1, 3, 6, 7, 9],
+            ]
+        )
+    }
+
+    #[test]
+    fn test_monotonicity() {
+        let vecs = parse(INPUT_STR);
+        assert_eq!(
+            vecs.iter().map(|v| is_monotonic(v)).collect::<Vec<_>>(),
+            vec![true, true, true, false, true, true]
+        )
+    }
+
+    #[test]
+    fn test_safe_gaps() {
+        let vecs = parse(INPUT_STR);
+        assert_eq!(
+            vecs.iter().map(|v| safe_gaps(v)).collect::<Vec<_>>(),
+            vec![true, false, false, true, false, true]
+        )
+    }
+
+    #[test]
+    fn test_dampened_gaps() {
+        let vecs = parse(INPUT_STR);
+        assert_eq!(
+            vecs.iter().map(|v| is_safe_dampened(v)).collect::<Vec<_>>(),
+            vec![true, false, false, true, true, true]
+        )
+    }
+}
index d54a6f67af3d6cbbeb023ee61023540421cc83c1..5b055cafc1cd13d02694f511660c482ef94ceea4 100644 (file)
@@ -1,6 +1,9 @@
 pub mod day01;
+pub mod day02;
 
 fn main() {
     day01::part1();
     day01::part2();
+    day02::part1();
+    day02::part2();
 }