y2024d8
This commit is contained in:
		| @@ -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