diff --git a/README.md b/README.md index 50e1d3d..ab26403 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ https://adventofcode.com/2024 | 04 | Ceres Search | :pushpin: | :pushpin: | Matrix multidirectional search | | 05 | Print Queue | :pushpin: | :pushpin: | Queue order | | 06 | Guard Gallivant | :pushpin: | :pushpin: | 2D navigation | -| 07 | Bridge Repair | :pushpin: | | Equation parsing | -| 08 | | | | | +| 07 | Bridge Repair | :pushpin: | :pushpin: | Equation parsing | +| 08 | Resonant Collinearity | | | | | 09 | | | | | | 10 | | | | | | 11 | | | | | diff --git a/assets/day_8_antena_map_input b/assets/day_8_antena_map_input new file mode 100644 index 0000000..78a1e91 --- /dev/null +++ b/assets/day_8_antena_map_input @@ -0,0 +1,12 @@ +............ +........0... +.....0...... +.......0.... +....0....... +......A..... +............ +............ +........A... +.........A.. +............ +............ diff --git a/src/advent_of_code/mod.rs b/src/advent_of_code/mod.rs index 210d401..de79212 100644 --- a/src/advent_of_code/mod.rs +++ b/src/advent_of_code/mod.rs @@ -4,7 +4,8 @@ // mod thu_05; // mod tue_03; // mod wed_04; -mod sat_07; +// mod sat_07; +mod sun_08; mod types; mod utils; @@ -57,6 +58,10 @@ pub fn historian_hysteria() { // println!("The guard would loop on {} positions", loop_obstacle_count); // Saturday 07 - let calibration_result = sat_07::bridge_repair("./assets/day_7_calibrations_input"); - println!("The total calibration result is {}", calibration_result); + // let calibration_result = sat_07::bridge_repair("./assets/day_7_calibrations_input"); + // println!("The total calibration result is {}", calibration_result); + + // Sunday 08 + let antinode_count = sun_08::resonant_collinearity("./assets/day_8_antena_map_input"); + println!("The total antinode positions is {}", antinode_count); } diff --git a/src/advent_of_code/sun_08.rs b/src/advent_of_code/sun_08.rs new file mode 100644 index 0000000..d6141bf --- /dev/null +++ b/src/advent_of_code/sun_08.rs @@ -0,0 +1,232 @@ +use std::collections::HashSet; + +use utils::read_antena_map_input; + +use super::*; + +pub fn resonant_collinearity(input: &str) -> AntinodeCount { + let (roof_map, antena_list) = read_antena_map_input(input); + + get_antinode_set_of_aligned_position(&antena_list, &roof_map).len() +} + +pub fn get_antinode_set_of_aligned_position( + antena_list: &AntenaList, + map: &RoofMap, +) -> AntinodeList { + let mut antinode_list: AntinodeList = HashSet::new(); + + for antena in antena_list { + for complementary_antena in antena_list { + if antena != complementary_antena { + let distance_x = (antena.1 as i32 - complementary_antena.1 as i32).abs() as usize; + let distance_y = (antena.0 as i32 - complementary_antena.0 as i32).abs() as usize; + + println!( + "For antenas: {:?} and {:?} the distances are x: {}, y: {}", + antena, complementary_antena, distance_x, distance_y + ); + + let (a, b) = get_extremes_with_variance( + (antena.0, antena.1), + (complementary_antena.0, complementary_antena.1), + distance_y, + distance_x, + map.len(), + map[0].len(), + ); + + if let Some(pair) = a { + antinode_list.insert(pair); + } + if let Some(pair) = b { + antinode_list.insert(pair); + } + } + } + } + + println!("Aninode list: {:?}", antinode_list); + + antinode_list +} + +// FIXME: too many if / else, this is easier treating it as a real vector +pub fn get_extremes_with_variance( + a: (usize, usize), + b: (usize, usize), + variance_y: usize, + variance_x: usize, + max_y: usize, + max_x: usize, +) -> (Option<(usize, usize)>, Option<(usize, usize)>) { + if a.1 > b.1 { + if a.0 > b.0 { + // |b_| + // |_a| + let first = + if b.0 as i32 - variance_y as i32 >= 0 && b.1 as i32 - variance_x as i32 >= 0 { + Some((b.0 - variance_y, b.1 - variance_x)) + } else { + None + }; + let second = if a.0 + variance_y < max_y && a.1 + variance_x < max_x { + Some((a.0 + variance_y, a.1 + variance_x)) + } else { + None + }; + + (first, second) + } else { + // |_a| + // |b_| + let first = if a.0 as i32 - variance_y as i32 >= 0 && a.1 + variance_x < max_x { + Some((a.0 - variance_y, a.1 + variance_x)) + } else { + None + }; + let second = if b.0 + variance_y < max_y && b.1 as i32 - variance_x as i32 >= 0 { + Some((b.0 + variance_y, b.1 - variance_x)) + } else { + None + }; + + (first, second) + } + } else { + if a.0 > b.0 { + // |_b| + // |a_| + let first = if b.0 as i32 - variance_y as i32 >= 0 && b.1 + variance_x < max_x { + Some((b.0 - variance_y, b.1 + variance_x)) + } else { + None + }; + let second = if a.0 + variance_y < max_y && a.1 as i32 - variance_x as i32 >= 0 { + Some((a.0 + variance_y, a.1 - variance_x)) + } else { + None + }; + + (first, second) + } else { + // |a_| + // |_b| + let first = + if a.0 as i32 - variance_y as i32 >= 0 && a.1 as i32 - variance_x as i32 >= 0 { + Some((a.0 - variance_y, a.1 - variance_x)) + } else { + None + }; + let second = if b.0 + variance_y < max_y && b.1 + variance_x < max_x { + Some((b.0 + variance_y, b.1 + variance_x)) + } else { + None + }; + + (first, second) + } + } +} + +// NOTE: this might be the ugliest piece of code ever +// pub fn get_antinode_set_of_position( +// x: usize, +// y: usize, +// freq: &char, +// map: &RoofMap, +// ) -> AntinodeList { +// println!("Checking {},{}", y, x); +// let mut antinode_list: AntinodeList = HashSet::new(); + +// let mut scroll_count: i32 = 1; +// 'all_directions_check: loop { +// let new_pos_x = x as i32 + scroll_count; +// let new_pos_y = y as i32 + scroll_count; +// let new_neg_x = x as i32 - scroll_count; +// let new_neg_y = y as i32 - scroll_count; + +// if new_pos_x >= map[0].len() as i32 +// && new_pos_y >= map.len() as i32 +// && new_neg_x < 0 +// && new_neg_y < 0 +// { +// break 'all_directions_check; +// } + +// // bottom right +// if new_pos_x < map[0].len() as i32 && new_pos_y < map.len() as i32 { +// if let Some(map_freq) = map[new_pos_y as usize][new_pos_x as usize] { +// println!("Map_freq: {}", map_freq); +// if map_freq == *freq { +// let distance_between_antenas = (x as i32 - new_pos_x).abs(); +// let antinode_x = new_pos_x + distance_between_antenas; +// let antinode_y = new_pos_y + distance_between_antenas; + +// if antinode_x < map[0].len() as i32 && antinode_y < map.len() as i32 { +// if let None = map[antinode_y as usize][antinode_x as usize] { +// antinode_list.insert((antinode_y as usize, antinode_x as usize)); +// } +// } +// } +// } +// } + +// if new_pos_x < map[0].len() as i32 && new_neg_y >= 0 { +// if let Some(map_freq) = map[new_neg_y as usize][new_pos_x as usize] { +// println!("Map_freq: {}", map_freq); +// if map_freq == *freq { +// let distance_between_antenas = (x as i32 - new_pos_x).abs(); +// let antinode_x = new_pos_x + distance_between_antenas; +// let antinode_y = new_neg_y - distance_between_antenas; + +// if antinode_x < map[0].len() as i32 && antinode_y > 0 { +// if let None = map[antinode_y as usize][antinode_x as usize] { +// antinode_list.insert((antinode_y as usize, antinode_x as usize)); +// } +// } +// } +// } +// } + +// if new_neg_x >= 0 && new_neg_y >= 0 { +// if let Some(map_freq) = map[new_neg_y as usize][new_neg_x as usize] { +// println!("Map_freq: {}", map_freq); +// if map_freq == *freq { +// let distance_between_antenas = (x as i32 - new_neg_x).abs(); +// let antinode_x = new_neg_x - distance_between_antenas; +// let antinode_y = new_neg_y - distance_between_antenas; + +// if antinode_x >= 0 && antinode_y >= 0 { +// if let None = map[antinode_y as usize][antinode_x as usize] { +// antinode_list.insert((antinode_y as usize, antinode_x as usize)); +// } +// } +// } +// } +// } + +// if new_neg_x >= 0 && new_pos_y < map.len() as i32 { +// if let Some(map_freq) = map[new_pos_y as usize][new_neg_x as usize] { +// println!("Map_freq: {}", map_freq); +// if map_freq == *freq { +// let distance_between_antenas = (x as i32 - new_neg_x).abs(); +// let antinode_x = new_neg_x - distance_between_antenas; +// let antinode_y = new_pos_y + distance_between_antenas; + +// if antinode_x >= 0 && antinode_y < map.len() as i32 { +// if let None = map[antinode_y as usize][antinode_x as usize] { +// antinode_list.insert((antinode_y as usize, antinode_x as usize)); +// } +// } +// } +// } +// } + +// scroll_count += 1; +// } + +// println!("Antinode_list: {:?}", antinode_list); + +// antinode_list +// } diff --git a/src/advent_of_code/types.rs b/src/advent_of_code/types.rs index 79ae986..11aab12 100644 --- a/src/advent_of_code/types.rs +++ b/src/advent_of_code/types.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + // Historian Hysteria - Day 1 pub type Id = i32; pub type Key = Id; @@ -57,3 +59,15 @@ pub enum Operation { MUL, COMB, } + +// Resonant collinearity +pub type RoofRow = Vec>; +pub type RoofMap = Vec; + +#[derive(Debug, PartialEq)] +pub struct Antena(pub usize, pub usize, pub char); //y,x,freq +pub type AntenaList = Vec; + +pub type AntinodeCount = usize; +pub type Antinode = (usize, usize); +pub type AntinodeList = HashSet; diff --git a/src/advent_of_code/utils.rs b/src/advent_of_code/utils.rs index 815fa0d..d33af92 100644 --- a/src/advent_of_code/utils.rs +++ b/src/advent_of_code/utils.rs @@ -144,6 +144,26 @@ pub fn read_calibration_equations(input: &str) -> Vec { calibration_list } +pub fn read_antena_map_input(input: &str) -> (RoofMap, AntenaList) { + let mut roof_map: RoofMap = vec![]; + let mut antena_list: AntenaList = vec![]; + + for (line_index, line) in read_to_string(input).unwrap().lines().enumerate() { + let mut line_vec: RoofRow = vec![]; + for (character_index, character) in line.chars().into_iter().enumerate() { + if character == '.' { + line_vec.push(None); + } else { + line_vec.push(Some(character)); + antena_list.push(Antena(line_index, character_index, character)); + } + } + roof_map.push(line_vec); + } + + (roof_map, antena_list) +} + pub fn calc_distance(num_1: T, num_2: T) -> T where T: PartialOrd + Sub,