From 15de4852fa7f129d095aa0b2b9c0bddd38be6153 Mon Sep 17 00:00:00 2001 From: Louis Vallat Date: Wed, 11 Dec 2024 23:59:45 +0100 Subject: [PATCH] feat: added day 10 part 1 and 2 Signed-off-by: Louis Vallat --- .gitea/workflows/build_and_run.yml | 2 +- day10/Cargo.toml | 6 +++ day10/src/main.rs | 80 ++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 day10/Cargo.toml create mode 100644 day10/src/main.rs diff --git a/.gitea/workflows/build_and_run.yml b/.gitea/workflows/build_and_run.yml index 97ca62c..2f2b049 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, 2, 3, 4, 5, 6, 7, 8, 9] + day_number: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] runs-on: rust-bookworm steps: - name: Check out repository code diff --git a/day10/Cargo.toml b/day10/Cargo.toml new file mode 100644 index 0000000..3c916ef --- /dev/null +++ b/day10/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day10" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/day10/src/main.rs b/day10/src/main.rs new file mode 100644 index 0000000..5d8f7bb --- /dev/null +++ b/day10/src/main.rs @@ -0,0 +1,80 @@ +use std::collections::HashSet; +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>, HashSet<(usize, usize)>) { + let mut map = Vec::new(); + let mut trail_heads = HashSet::new(); + for (row, line) in input.lines().filter(|line| !line.is_empty()).enumerate() { + map.push(Vec::new()); + for (col, char) in line.chars().enumerate() { + map.last_mut() + .unwrap() + .push(char.to_digit(10).unwrap() as usize); + if char == '0' { + trail_heads.insert((row, col)); + } + } + } + (map, trail_heads) +} + +fn trails_count( + map: &Vec>, + current: (usize, usize), + nines: &mut HashSet<(usize, usize)>, +) -> usize { + if map[current.0][current.1] == 9 { + nines.insert(current); + return 1; + } + + let mut sum = 0; + for direction in [(0, 1), (1, 0), (0, -1), (-1, 0)] { + let target = ( + current.0 as i32 + direction.0, + current.1 as i32 + direction.1, + ); + if (0..map.len() as i32).contains(&target.0) + && (0..map[target.0 as usize].len() as i32).contains(&target.1) + { + let target = (target.0 as usize, target.1 as usize); + if map[target.0][target.1] == map[current.0][current.1] + 1 { + sum += trails_count(map, target, nines); + } + } + } + sum +} + +fn part_1(map: &Vec>, trail_heads: &HashSet<(usize, usize)>) -> usize { + trail_heads + .iter() + .map(|(row, col)| { + let mut nines = HashSet::new(); + trails_count(map, (*row, *col), &mut nines); + nines.len() + }) + .sum() +} + +fn part_2(map: &Vec>, trail_heads: &HashSet<(usize, usize)>) -> usize { + trail_heads + .iter() + .map(|(row, col)| trails_count(map, (*row, *col), &mut HashSet::new())) + .sum() +} + +fn main() { + let args: Vec = env::args().collect(); + for arg in args.iter().skip(1) { + let input = read_input(&arg); + let (map, trail_heads) = parse_input(&input); + println!("[{}]", &arg); + println!("\t[Part 1] => Answer is '{}'.", part_1(&map, &trail_heads)); + println!("\t[Part 2] => Answer is '{}'.", part_2(&map, &trail_heads)); + } +}