y2024d8
This commit is contained in:
		
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -123,6 +123,7 @@ version = "0.1.0"
 | 
			
		||||
name = "y2024"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "itertools",
 | 
			
		||||
 "regex",
 | 
			
		||||
 "utils",
 | 
			
		||||
]
 | 
			
		||||
 
 | 
			
		||||
@@ -6,3 +6,4 @@ edition = "2021"
 | 
			
		||||
[dependencies]
 | 
			
		||||
regex = "1.11.1"
 | 
			
		||||
utils = { workspace = true }
 | 
			
		||||
itertools = { workspace = true }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										50
									
								
								y2024/resources/8_input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								y2024/resources/8_input.txt
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										20
									
								
								y2024/src/bin/d8.rs
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										227
									
								
								y2024/src/days/d8.rs
									
									
									
									
									
										Normal 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -11,3 +11,5 @@ pub mod d5;
 | 
			
		||||
pub mod d6;
 | 
			
		||||
 | 
			
		||||
pub mod d7;
 | 
			
		||||
 | 
			
		||||
pub mod d8;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user