This commit is contained in:
Fabian Schmidt 2024-12-08 16:35:33 +01:00
parent 2a91587ae5
commit 0dec0bbf82
6 changed files with 301 additions and 0 deletions

1
Cargo.lock generated
View File

@ -123,6 +123,7 @@ version = "0.1.0"
name = "y2024"
version = "0.1.0"
dependencies = [
"itertools",
"regex",
"utils",
]

View File

@ -6,3 +6,4 @@ edition = "2021"
[dependencies]
regex = "1.11.1"
utils = { workspace = true }
itertools = { workspace = true }

View File

@ -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

20
y2024/src/bin/d8.rs Normal file
View File

@ -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));
}

227
y2024/src/days/d8.rs Normal file
View File

@ -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);
}
}

View File

@ -11,3 +11,5 @@ pub mod d5;
pub mod d6;
pub mod d7;
pub mod d8;