retroactive, to derust my rust

day8 part2

+71 -7
+7
Cargo.lock
··· 15 15 name = "aoc2024" 16 16 version = "0.1.0" 17 17 dependencies = [ 18 + "gcd", 18 19 "itertools", 19 20 "regex", 20 21 ] ··· 24 25 version = "1.15.0" 25 26 source = "registry+https://github.com/rust-lang/crates.io-index" 26 27 checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 28 + 29 + [[package]] 30 + name = "gcd" 31 + version = "2.3.0" 32 + source = "registry+https://github.com/rust-lang/crates.io-index" 33 + checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" 27 34 28 35 [[package]] 29 36 name = "itertools"
+1
Cargo.toml
··· 4 4 edition = "2024" 5 5 6 6 [dependencies] 7 + gcd = "2.3.0" 7 8 itertools = "0.14.0" 8 9 regex = "1.12.2"
+56 -7
src/day8.rs
··· 1 - use std::{collections::{HashMap, HashSet}, convert::Infallible, str::FromStr}; 1 + use std::{ 2 + collections::{HashMap, HashSet}, 3 + convert::Infallible, 4 + str::FromStr, 5 + }; 2 6 7 + use gcd::Gcd; 3 8 use itertools::Itertools; 4 9 5 10 pub fn day8_part1(input: &str) -> String { ··· 9 14 } 10 15 11 16 pub fn day8_part2(input: &str) -> String { 12 - todo!() 17 + let city: City = input.parse().unwrap(); 18 + let antinodes: HashSet<Point> = city.resonant_antinodes().collect(); 19 + antinodes.len().to_string() 13 20 } 14 21 15 22 fn antinodes(antenna1: Point, antenna2: Point) -> (Option<Point>, Option<Point>) { 16 23 let distance: Vector2 = (antenna1, antenna2).into(); 17 24 let antinode1 = antenna2 + distance; 18 25 let antinode2 = antenna1 - distance; 19 - dbg!(antenna1, antenna2, distance, antinode1, antinode2); 20 26 (antinode1, antinode2) 21 27 } 22 28 29 + fn resonant_antinodes(antenna1: Point, antenna2: Point, width: usize, height: usize) -> Vec<Point> { 30 + let distance: Vector2 = (antenna1, antenna2).into(); 31 + let distance = distance.simplified(); 32 + let mut last_antinode = antenna1; 33 + let mut antinodes = vec![last_antinode]; 34 + while let Some(next_antinode) = last_antinode + distance { 35 + if next_antinode.row >= height || next_antinode.col >= width { 36 + break; 37 + } else { 38 + antinodes.push(next_antinode); 39 + last_antinode = next_antinode; 40 + } 41 + } 42 + let mut last_antinode = antenna1; 43 + while let Some(next_antinode) = last_antinode - distance { 44 + if next_antinode.row >= height || next_antinode.col >= width { 45 + break; 46 + } else { 47 + antinodes.push(next_antinode); 48 + last_antinode = next_antinode; 49 + } 50 + } 51 + antinodes 52 + } 53 + 23 54 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)] 24 55 struct Point { 25 56 row: usize, ··· 74 105 } 75 106 } 76 107 108 + impl Vector2 { 109 + fn simplified(&self) -> Self { 110 + let mut retval = *self; 111 + let pos_col_distance: usize = retval.col_distance.unsigned_abs(); 112 + let pos_row_distance: usize = retval.row_distance.unsigned_abs(); 113 + let gcd = pos_col_distance.gcd(pos_row_distance); 114 + if gcd != 1 { 115 + retval.col_distance /= gcd as isize; 116 + retval.row_distance /= gcd as isize; 117 + } 118 + retval 119 + } 120 + } 121 + 77 122 #[derive(Debug)] 78 123 struct City { 79 124 width: usize, ··· 116 161 retval.into_values().collect() 117 162 } 118 163 fn antenna_pairs(&self) -> impl Iterator<Item = (Point, Point)> { 119 - let ap: Vec<(Point, Point)> = self.antenna_groups 164 + self 165 + .antenna_groups 120 166 .iter() 121 167 .flat_map(|group| group.iter().combinations(2)) 122 - .map(|combination| (*combination[0], *combination[1])).collect(); 123 - dbg!(&ap); 124 - ap.into_iter() 168 + .map(|combination| (*combination[0], *combination[1])) 125 169 } 126 170 fn antinodes(&self) -> impl Iterator<Item = Point> { 127 171 self.antenna_pairs() 128 172 .map(|(from, to)| antinodes(from, to)) 129 173 .flat_map(|(a1, a2)| [a1, a2]) 130 174 .flatten() 175 + .filter(|p| p.row < self.height && p.col < self.width) 176 + } 177 + fn resonant_antinodes(&self) -> impl Iterator<Item = Point> { 178 + self.antenna_pairs() 179 + .flat_map(|(from, to)| resonant_antinodes(from, to, self.width, self.height)) 131 180 .filter(|p| p.row < self.height && p.col < self.width) 132 181 } 133 182 }
+7
src/lib.rs
··· 361 361 // assert!(result.parse::<u64>().unwrap() < 414); //too high 362 362 assert_eq!(result, "369"); 363 363 } 364 + #[test] 365 + fn day8_part2_test() { 366 + let test_result = day8::day8_part2(include_str!("../input/day8.test.txt")); 367 + assert_eq!(test_result, "34"); 368 + let result = day8::day8_part2(include_str!("../input/day8.txt")); 369 + assert_eq!(result, "1169"); 370 + } 364 371 365 372 #[test] 366 373 fn day7_part1_test() {