diff --git a/2023/all.sh b/2023/all.sh index f2531fe..d8c0023 100755 --- a/2023/all.sh +++ b/2023/all.sh @@ -35,6 +35,10 @@ run() { echo "day8" ./day8/target/release/day8 1 ./day8/target/release/day8 2 + + echo "day9" + ./day9/target/release/day9 1 + ./day9/target/release/day9 2 } time run diff --git a/2023/day9/.gitignore b/2023/day9/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/2023/day9/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/2023/day9/Cargo.lock b/2023/day9/Cargo.lock new file mode 100644 index 0000000..a412849 --- /dev/null +++ b/2023/day9/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day9" +version = "0.1.0" +dependencies = [ + "indoc", +] + +[[package]] +name = "indoc" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" diff --git a/2023/day9/Cargo.toml b/2023/day9/Cargo.toml new file mode 100644 index 0000000..778615e --- /dev/null +++ b/2023/day9/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day9" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +indoc = "2.0.4" diff --git a/2023/day9/src/main.rs b/2023/day9/src/main.rs new file mode 100644 index 0000000..6479c44 --- /dev/null +++ b/2023/day9/src/main.rs @@ -0,0 +1,131 @@ +use std::num::ParseIntError; + +fn part1(input: &str) -> Result { + let mut sum = 0; + for line in input.lines() { + let mut map: Vec> = vec![]; + + map.push( + line.split_whitespace() + .map(str::parse::) + .collect::, ParseIntError>>() + .unwrap(), + ); + + for i in 0.. { + let reduced = map[i] + .windows(2) + .map(|w| w[1] - w[0]) + .collect::>(); + + let all_zero = reduced.iter().all(|e| *e == 0); + + map.push(reduced); + + if all_zero { + break; + } + } + + let len = map.len(); + + map[len - 1].push(0); + + for i in (0..map.len() - 1).rev() { + let j = map[i].len(); + let left = map[i][j - 1]; + let below = map[i + 1][j - 1]; + map[i].push(left + below); + } + + sum += map[0].last().unwrap(); + } + + Ok(sum as usize) +} + +fn part2(input: &str) -> Result { + let mut sum = 0; + for line in input.lines() { + let mut map: Vec> = vec![]; + + map.push( + line.split_whitespace() + .map(str::parse::) + .collect::, ParseIntError>>() + .unwrap(), + ); + + for i in 0.. { + let reduced = map[i] + .windows(2) + .map(|w| w[1] - w[0]) + .collect::>(); + + let all_zero = reduced.iter().all(|e| *e == 0); + + map.push(reduced); + + if all_zero { + break; + } + } + + let len = map.len(); + + map[len - 1].insert(0, 0); + + for i in (0..map.len() - 1).rev() { + let right = map[i][0]; + let below = map[i + 1][0]; + map[i].insert(0, right - below); + } + + sum += map[0].first().unwrap(); + } + + Ok(sum as usize) +} + +fn main() -> Result<(), String> { + let input = include_str!("../input"); + + let args = std::env::args().skip(1).collect::>(); + let part = args[0].parse::().unwrap(); + + if part == 1 { + println!("Part 1 : {}", part1(input)?); + } else if part == 2 { + println!("Part 2 : {}", part2(input)?); + } else { + return Err("unknown part".into()); + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use indoc::indoc; + + #[test] + fn part_1_example_1() { + let input = indoc! {" + 0 3 6 9 12 15 + 1 3 6 10 15 21 + 10 13 16 21 30 45 + "}; + assert_eq!(part1(input).unwrap(), 114); + } + + #[test] + fn part_2_example_1() { + let input = indoc! {" + 0 3 6 9 12 15 + 1 3 6 10 15 21 + 10 13 16 21 30 45 + "}; + assert_eq!(part2(input).unwrap(), 2); + } +}