From da36b80be45e7c8d9bc207b92dfc0a27bad67924 Mon Sep 17 00:00:00 2001 From: Louis Vallat Date: Tue, 3 Dec 2024 22:04:35 +0100 Subject: [PATCH] feat: added day 2 part 1 and 2 Signed-off-by: Louis Vallat --- .gitea/workflows/build_and_run.yml | 2 +- day2/Cargo.toml | 6 +++ day2/src/main.rs | 65 ++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 day2/Cargo.toml create mode 100644 day2/src/main.rs diff --git a/.gitea/workflows/build_and_run.yml b/.gitea/workflows/build_and_run.yml index 9d2283d..b46b6f2 100644 --- a/.gitea/workflows/build_and_run.yml +++ b/.gitea/workflows/build_and_run.yml @@ -11,7 +11,7 @@ jobs: name: Challenge for day strategy: matrix: - day_number: [1] + day_number: [1, 2] runs-on: rust-bookworm steps: - name: Check out repository code diff --git a/day2/Cargo.toml b/day2/Cargo.toml new file mode 100644 index 0000000..cd3d088 --- /dev/null +++ b/day2/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day2" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/day2/src/main.rs b/day2/src/main.rs new file mode 100644 index 0000000..5cf9111 --- /dev/null +++ b/day2/src/main.rs @@ -0,0 +1,65 @@ +use std::{env, fs}; + +fn read_input(path: &str) -> String { + fs::read_to_string(path).expect("Cannot read file.") +} + +fn parse_input(input: &str) -> Vec> { + input + .lines() + .filter(|line| !line.is_empty()) + .map(|line| { + line.split(" ") + .map(|num| num.parse().expect("Could not parse as i32.")) + .collect() + }) + .collect() +} + +fn is_safe(levels: &Vec, allowed_errors: u32) -> bool { + if levels.len() < 2 { + return true; + } + + if levels.len() == 2 { + return (1..=3).contains(&(levels[0] - levels[1]).abs()); + } + + let mut diff: i32 = levels[1] - levels[2]; + for i in 1..levels.len() { + let local_diff = levels[i - 1] - levels[i]; + if local_diff.signum() != diff.signum() || !(1..=3).contains(&local_diff.abs()) { + return if allowed_errors == 0 { + false + } else { + let mut levels_low = levels.clone(); + levels_low.remove(i - 1); + let mut levels_high = levels.clone(); + levels_high.remove(i); + is_safe(&levels_low, allowed_errors - 1) + || is_safe(&levels_high, allowed_errors - 1) + }; + } + diff = local_diff; + } + true +} + +fn part_1(levels: &Vec>) -> usize { + levels.iter().filter(|level| is_safe(level, 0)).count() +} + +fn part_2(levels: &Vec>) -> usize { + levels.iter().filter(|level| is_safe(level, 1)).count() +} + +fn main() { + let args: Vec = env::args().collect(); + for arg in args.iter().skip(1) { + let input = read_input(&arg); + let levels = parse_input(&input); + println!("[{}]", &arg); + println!("\t[Part 1] => Answer is '{}'.", part_1(&levels)); + println!("\t[Part 2] => Answer is '{}'.", part_2(&levels)); + } +}