y2024d8
This commit is contained in:
		
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -123,6 +123,7 @@ version = "0.1.0"
 | 
				
			|||||||
name = "y2024"
 | 
					name = "y2024"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "itertools",
 | 
				
			||||||
 "regex",
 | 
					 "regex",
 | 
				
			||||||
 "utils",
 | 
					 "utils",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,3 +6,4 @@ edition = "2021"
 | 
				
			|||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
regex = "1.11.1"
 | 
					regex = "1.11.1"
 | 
				
			||||||
utils = { workspace = true }
 | 
					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 d6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod d7;
 | 
					pub mod d7;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod d8;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user