From 013414d7a3276d616de15356b3d713e0d2ad34c4 Mon Sep 17 00:00:00 2001 From: Louis Vallat Date: Sun, 8 Dec 2024 20:12:56 +0100 Subject: [PATCH] feat: added day 8 part 1 and 2 Signed-off-by: Louis Vallat --- .gitea/workflows/build_and_run.yml | 2 +- day8/Cargo.toml | 6 ++ day8/src/main.rs | 114 +++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 day8/Cargo.toml create mode 100644 day8/src/main.rs diff --git a/.gitea/workflows/build_and_run.yml b/.gitea/workflows/build_and_run.yml index c898a80..a70ba0c 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] + day_number: [1, 2, 3, 4, 5, 6, 7, 8] runs-on: rust-bookworm steps: - name: Check out repository code diff --git a/day8/Cargo.toml b/day8/Cargo.toml new file mode 100644 index 0000000..cc06d1e --- /dev/null +++ b/day8/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day8" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/day8/src/main.rs b/day8/src/main.rs new file mode 100644 index 0000000..dfedce3 --- /dev/null +++ b/day8/src/main.rs @@ -0,0 +1,114 @@ +use std::collections::{HashMap, 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) -> (HashMap>, (i32, i32)) { + let mut antenna_positions: HashMap> = HashMap::new(); + let mut dimensions = (0, 0); + for (row, line) in input.lines().filter(|line| !line.is_empty()).enumerate() { + dimensions.0 = row + 1; + for (col, c) in line.chars().enumerate() { + dimensions.1 = col + 1; + if c != '.' { + if let Some(positions) = antenna_positions.get_mut(&c) { + positions.insert((row as i32, col as i32)); + } else { + antenna_positions.insert(c, HashSet::from_iter(vec![(row as i32, col as i32)])); + } + } + } + } + + ( + antenna_positions, + (dimensions.0 as i32, dimensions.1 as i32), + ) +} + +fn get_anti_nodes_positions_in_map( + start: &(i32, i32), + direction: &(i32, i32), + map_size: &(i32, i32), + limit: Option, +) -> HashSet<(i32, i32)> { + let mut anti_nodes_locations = HashSet::new(); + let init = if limit.is_some() { 1 } else { 0 }; + + for i in init.. { + let x = (start.0 + direction.0 * i, start.1 + direction.1 * i); + if !(0..map_size.0).contains(&x.0) || !(0..map_size.1).contains(&x.1) { + return anti_nodes_locations; + } + anti_nodes_locations.insert(x); + if limit.is_some() && i >= limit.unwrap() { + return anti_nodes_locations; + } + } + anti_nodes_locations +} + +fn compute_anti_nodes_count( + antenna_positions: &HashMap>, + map_size: &(i32, i32), + limit: Option, +) -> usize { + let mut computed_pairs = HashSet::new(); + let mut anti_nodes_locations: HashSet<(i32, i32)> = HashSet::new(); + + for positions in antenna_positions.values() { + for x in positions.iter() { + for y in positions.iter() { + if x != y && !computed_pairs.contains(&(y, x)) { + computed_pairs.insert((x, y)); + anti_nodes_locations.extend( + get_anti_nodes_positions_in_map( + &y, + &(y.0 - x.0, y.1 - x.1), + map_size, + limit, + ) + .iter(), + ); + anti_nodes_locations.extend( + get_anti_nodes_positions_in_map( + &x, + &(x.0 - y.0, x.1 - y.1), + map_size, + limit, + ) + .iter(), + ); + } + } + } + } + anti_nodes_locations.len() +} + +fn part_1(antenna_positions: &HashMap>, map_size: &(i32, i32)) -> usize { + compute_anti_nodes_count(antenna_positions, map_size, Some(1)) +} + +fn part_2(antenna_positions: &HashMap>, map_size: &(i32, i32)) -> usize { + compute_anti_nodes_count(antenna_positions, map_size, None) +} + +fn main() { + let args: Vec = env::args().collect(); + for arg in args.iter().skip(1) { + let input = read_input(&arg); + let (antenna_positions, map_size) = parse_input(&input); + println!("[{}]", &arg); + println!( + "\t[Part 1] => Answer is '{}'.", + part_1(&antenna_positions, &map_size) + ); + println!( + "\t[Part 2] => Answer is '{}'.", + part_2(&antenna_positions, &map_size) + ); + } +}