From 75706b14e36164c5c7f975321b9a4e82fec30826 Mon Sep 17 00:00:00 2001 From: Joe Ardent <code@ardent.nebcorp.com> Date: Thu, 2 Jan 2025 16:43:36 -0800 Subject: [PATCH] day8, part2 --- day08/src/main.rs | 101 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 18 deletions(-) diff --git a/day08/src/main.rs b/day08/src/main.rs index 8a01568..7a9e91b 100644 --- a/day08/src/main.rs +++ b/day08/src/main.rs @@ -26,7 +26,7 @@ fn pt1(input: &str) -> usize { if a1 == a2 { continue; } - for antinode in board.antinodes(*a1, *a2) { + for antinode in board.antinodes(*a1, *a2, false) { antinodes.insert(antinode); } } @@ -40,9 +40,35 @@ fn pt1(input: &str) -> usize { } fn pt2(input: &str) -> usize { - let mut total = 0; + let mut board = Board::new(input); + let mut antinodes = HashSet::new(); - total + for f in board.freqs() { + for a1 in board.antennae[&f].iter() { + for a2 in board.antennae[&f].iter() { + if a1 == a2 { + continue; + } + let nodes = board.antinodes(*a1, *a2, true); + antinodes.extend(nodes.into_iter()); + } + } + } + for &antinode in antinodes.iter() { + board.set(antinode, Cell::Antinode); + } + println!("{board}"); + antinodes.len() +} + +fn gcd(mut a: usize, mut b: usize) -> usize { + let mut t = 0; + while b != 0 { + t = b; + b = a % b; + a = t; + } + a } #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -124,31 +150,61 @@ impl Board { false } - fn antinodes(&self, a1: Loc, a2: Loc) -> Vec<Loc> { - let dy = (a1.0 as i64 - a2.0 as i64).unsigned_abs() as usize; - let dx = (a1.1 as i64 - a2.1 as i64).unsigned_abs() as usize; + fn antinodes(&self, a1: Loc, a2: Loc, pt2: bool) -> HashSet<Loc> { + let mut dy = (a1.0 as i64 - a2.0 as i64).unsigned_abs() as usize; + let mut dx = (a1.1 as i64 - a2.1 as i64).unsigned_abs() as usize; + // row 0 is at the top let (top, bottom) = if a1.0 <= a2.0 { (a1, a2) } else { (a2, a1) }; let (left, right) = if a1.1 <= a2.1 { (a1, a2) } else { (a2, a1) }; - let mut antinodes = Vec::new(); + let mut antinodes = HashSet::new(); let ny_top = top.0.wrapping_sub(dy); let ny_bot = bottom.0 + dy; let nx_left = left.1.wrapping_sub(dx); let nx_right = right.1 + dx; + let slopes_up = top == right; - let (n1, n2) = match (a1, a2) { - _ if top == left => (Loc(ny_top, nx_left), Loc(ny_bot, nx_right)), - _ if top == right => (Loc(ny_top, nx_right), Loc(ny_bot, nx_left)), - _ if bottom == left => (Loc(ny_bot, nx_left), Loc(ny_top, nx_right)), - _ => (Loc(ny_bot, nx_right), Loc(ny_top, nx_left)), - }; + if pt2 { + let g = gcd(dy, dx); + dy /= g; + dx /= g; - if n1.0 < self.bottom && n1.1 < self.right { - antinodes.push(n1); - } - if n2.0 < self.bottom && n2.1 < self.right { - antinodes.push(n2); + // start at the left and move right + let mut loc = left; + while loc.0 < self.bottom && loc.1 < self.right { + antinodes.insert(loc); + loc.1 += dx; + if slopes_up { + loc.0 = loc.0.wrapping_sub(dy); + } else { + loc.0 += dy; + } + } + + // now start at the right and move left + let mut loc = right; + while loc.0 < self.bottom && loc.1 < self.right { + antinodes.insert(loc); + loc.1 = loc.1.wrapping_sub(dx); + if slopes_up { + loc.0 += dy; + } else { + loc.0 = loc.0.wrapping_sub(dy); + } + } + } else { + let (n1, n2) = if slopes_up { + (Loc(ny_bot, nx_left), Loc(ny_top, nx_right)) + } else { + (Loc(ny_top, nx_left), Loc(ny_bot, nx_right)) + }; + if n1.0 < self.bottom && n1.1 < self.right { + antinodes.insert(n1); + } + if n2.0 < self.bottom && n2.1 < self.right { + antinodes.insert(n2); + } } antinodes @@ -203,4 +259,13 @@ mod test { fn p2() { assert_eq!(34, pt2(INPUT)); } + + #[test] + fn g() { + let a = gcd(12, 30); + assert_eq!(a, 6); + + let b = gcd(51, 17); + assert_eq!(b, 17); + } }