From b457e10a35e700bfe9576c6a5d76204059c5485f Mon Sep 17 00:00:00 2001 From: Fabian Schmidt Date: Sun, 8 Dec 2024 16:35:33 +0100 Subject: [PATCH] y2024d8 --- Cargo.lock | 1 + y2024/Cargo.toml | 1 + y2024/resources/8_input.txt | 50 ++++++++ y2024/src/bin/d8.rs | 20 ++++ y2024/src/days/d8.rs | 227 ++++++++++++++++++++++++++++++++++++ y2024/src/days/mod.rs | 2 + 6 files changed, 301 insertions(+) create mode 100644 y2024/resources/8_input.txt create mode 100644 y2024/src/bin/d8.rs create mode 100644 y2024/src/days/d8.rs diff --git a/Cargo.lock b/Cargo.lock index 0b7002d..7d4d45c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,6 +123,7 @@ version = "0.1.0" name = "y2024" version = "0.1.0" dependencies = [ + "itertools", "regex", "utils", ] diff --git a/y2024/Cargo.toml b/y2024/Cargo.toml index e774106..8912744 100644 --- a/y2024/Cargo.toml +++ b/y2024/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" [dependencies] regex = "1.11.1" utils = { workspace = true } +itertools = { workspace = true } diff --git a/y2024/resources/8_input.txt b/y2024/resources/8_input.txt new file mode 100644 index 0000000..950ccb9 --- /dev/null +++ b/y2024/resources/8_input.txt @@ -0,0 +1,50 @@ +....K..........................8.................z +.....n..............r...........z................. +.......................w....8.............3...E... +.....Q.....U..4.........8......................... +...............rc...w........i.................... +...........K.........i..2......................... +..................4.....i......................... +K.....n....................w...........z.......... +..U......Q........................I............... +..........i.....I.....Q....g....................5E +..Q......................................5........ +..........c............8......w...g..........5.... +.............................I.O.................. +.Z.............4....b.....................k....... +..n........4......r..g..6..c.............3........ +....Z............c................................ +...................................x.............. +.......................................O.......... +...............U...................E..........5... +.....f..........................OI3......k........ +..m.......o......F.......R........x............... +m...........o..v6..3...............X.............. +..............H6v.....F.g.....................W... +...........o....Fb....v...............E........... +...Z.............a................................ +......U6.............V............................ +.9.............b..............pTk................. +.......m........V.........H1....x................. +...m.................H....................MX...... +............t.a............H...................... +........Z...a............v.....1..T..p.W..X....... +.............................9...x.......p........ +.....J.....................V..1................0.. +...........r..j..........a............pT.......... +.G..................J...N......f.................. +...........G......T....B........W.e...........M... +..........j.............Rk.............M.......... +.........q.............MB......R.F..1..P....X...f. +............................V....o...........h.... +...........................................W...... +......b......u............................e....... +.............................................0.... +..CA....Gt..O........................7.....e....0. +C.u......A..9J..N........................h.....e.. +uj....q..........N.2..................7........... +G....N.....uJ...............................0..... +.................B................P.......h....... +...C....q...........R.........P................... +.....q..tC....2.9.....B............P....f......... +...............2.................................7 diff --git a/y2024/src/bin/d8.rs b/y2024/src/bin/d8.rs new file mode 100644 index 0000000..01c8546 --- /dev/null +++ b/y2024/src/bin/d8.rs @@ -0,0 +1,20 @@ +use std::fs; + +use y2024::days::d8; + +fn main() { + part1(); + part2(); +} + +fn part1() { + let root = env!("CARGO_MANIFEST_DIR"); + let content = fs::read_to_string(format!("{root}/resources/8_input.txt")).unwrap(); + println!("{}", d8::process_part1(&content)); +} + +fn part2() { + let root = env!("CARGO_MANIFEST_DIR"); + let content = fs::read_to_string(format!("{root}/resources/8_input.txt")).unwrap(); + println!("{}", d8::process_part2(&content)); +} diff --git a/y2024/src/days/d8.rs b/y2024/src/days/d8.rs new file mode 100644 index 0000000..5e7e164 --- /dev/null +++ b/y2024/src/days/d8.rs @@ -0,0 +1,227 @@ +use itertools::Itertools; +use std::collections::{HashMap, HashSet}; + +pub fn process_part1(input: &str) -> usize { + let mut antennas_freq_pos = HashMap::new(); + // group all antenna positions by frequency + let grid = input + .lines() + .map(|line| line.chars().collect_vec()) + .collect_vec(); + let width = grid[0].len(); + let height = grid.len(); + for (y, line) in input.lines().enumerate() { + for (x, chara) in line.chars().enumerate() { + if chara == '.' { + continue; + } + antennas_freq_pos + .entry(chara) + .and_modify(|positions: &mut Vec<(isize, isize)>| { + positions.push((x as isize, y as isize)) + }) + .or_insert(vec![(x as isize, y as isize)]); + } + } + // get all combinations of 2 antennas by their frequency + // and get_antinodes + let mut antinodes = HashSet::new(); + for (_freq, positions) in antennas_freq_pos { + let pairs = positions.into_iter().combinations(2); + for pair in pairs { + let (antinode_a, antinode_b) = get_antinodes(pair[0], pair[1]); + if antinode_a.0 >= 0 + && antinode_a.0 < width as isize + && antinode_a.1 >= 0 + && antinode_a.1 < height as isize + { + antinodes.insert(antinode_a); + } + if antinode_b.0 >= 0 + && antinode_b.0 < width as isize + && antinode_b.1 >= 0 + && antinode_b.1 < height as isize + { + antinodes.insert(antinode_b); + } + } + } + let mut antinodes = antinodes.iter().collect_vec(); + antinodes.sort(); + antinodes.len() +} + +fn get_antinodes( + antenna_a: (isize, isize), + antenna_b: (isize, isize), +) -> ((isize, isize), (isize, isize)) { + let vec2 = ((antenna_a.0 - antenna_b.0), (antenna_a.1 - antenna_b.1)); + let antinode_a = { + let antinode_a = ((antenna_a.0 + vec2.0), (antenna_a.1 + vec2.1)); + if antinode_a == antenna_b { + ((antenna_a.0 - vec2.0), (antenna_a.1 - vec2.1)) + } else { + antinode_a + } + }; + let antinode_b = { + let antinode_b = ((antenna_b.0 + vec2.0), (antenna_b.1 + vec2.1)); + if antinode_b == antenna_a { + ((antenna_b.0 - vec2.0), (antenna_b.1 - vec2.1)) + } else { + antinode_b + } + }; + (antinode_a, antinode_b) +} + +fn get_reasonant_antinodes( + antenna_a: (isize, isize), + antenna_b: (isize, isize), + width: isize, + height: isize, +) -> Vec<(isize, isize)> { + let mut antinodes = HashSet::new(); + antinodes.insert(antenna_a); + antinodes.insert(antenna_b); + let vec2 = ((antenna_a.0 - antenna_b.0), (antenna_a.1 - antenna_b.1)); + let (mut a, mut b) = (antenna_a, antenna_b); + loop { + let antinode_a = { + let antinode_a = ((a.0 + vec2.0), (a.1 + vec2.1)); + if antinode_a == b { + ((a.0 - vec2.0), (a.1 - vec2.1)) + } else { + antinode_a + } + }; + if antinode_a.0 >= 0 && antinode_a.0 < width && antinode_a.1 >= 0 && antinode_a.1 < height { + antinodes.insert(antinode_a); + } else { + break; + } + b = a; + a = antinode_a; + } + let (mut a, mut b) = (antenna_a, antenna_b); + loop { + let antinode_b = { + let antinode_b = ((b.0 + vec2.0), (b.1 + vec2.1)); + if antinode_b == a { + ((b.0 - vec2.0), (b.1 - vec2.1)) + } else { + antinode_b + } + }; + if antinode_b.0 >= 0 && antinode_b.0 < width && antinode_b.1 >= 0 && antinode_b.1 < height { + antinodes.insert(antinode_b); + } else { + break; + } + a = b; + b = antinode_b; + } + antinodes.into_iter().collect_vec() +} + +pub fn process_part2(input: &str) -> usize { + let mut antennas_freq_pos = HashMap::new(); + // group all antenna positions by frequency + let grid = input + .lines() + .map(|line| line.chars().collect_vec()) + .collect_vec(); + let width = grid[0].len(); + let height = grid.len(); + for (y, line) in input.lines().enumerate() { + for (x, chara) in line.chars().enumerate() { + if chara == '.' { + continue; + } + antennas_freq_pos + .entry(chara) + .and_modify(|positions: &mut Vec<(isize, isize)>| { + positions.push((x as isize, y as isize)) + }) + .or_insert(vec![(x as isize, y as isize)]); + } + } + // get all combinations of 2 antennas by their frequency + // and get_antinodes + let mut all_antinodes: HashSet<(isize, isize)> = HashSet::new(); + for (_freq, positions) in antennas_freq_pos { + let pairs = positions.into_iter().combinations(2); + for pair in pairs { + let (a, b) = (pair[0], pair[1]); + let antinodes = get_reasonant_antinodes(a, b, width as isize, height as isize); + all_antinodes.extend(antinodes.iter()); + } + } + let mut antinodes = all_antinodes.iter().collect_vec(); + antinodes.sort(); + antinodes.len() +} + +#[cfg(test)] +mod tests { + use super::*; + + const INPUT: &str = "............ +........0... +.....0...... +.......0.... +....0....... +......A..... +............ +............ +........A... +.........A.. +............ +............"; + + #[test] + fn part1() { + let result = process_part1(INPUT); + assert_eq!(result, 14); + } + + #[test] + fn test_get_antinodes_1() { + let antenna_a = (5, 2); + let antenna_b = (7, 3); + let (antinode_a, antinode_b) = get_antinodes(antenna_a, antenna_b); + assert_eq!(antinode_a, (3, 1)); + assert_eq!(antinode_b, (9, 4)); + } + + #[test] + fn test_get_antinodes_2() { + let antenna_a = (5, 2); + let antenna_b = (8, 1); + let (antinode_a, antinode_b) = get_antinodes(antenna_a, antenna_b); + assert_eq!(antinode_a, (2, 3)); + assert_eq!(antinode_b, (11, 0)); + } + + #[test] + fn part2() { + let result = process_part2(INPUT); + assert_eq!(result, 34); + } + + #[test] + fn part2_simple() { + let input = "T......... +...T...... +.T........ +.......... +.......... +.......... +.......... +.......... +.......... +.........."; + let result = process_part2(input); + assert_eq!(result, 9); + } +} diff --git a/y2024/src/days/mod.rs b/y2024/src/days/mod.rs index 823daf8..cb14785 100644 --- a/y2024/src/days/mod.rs +++ b/y2024/src/days/mod.rs @@ -11,3 +11,5 @@ pub mod d5; pub mod d6; pub mod d7; + +pub mod d8;