Something went wrong. Try again.
retroactive, to derust my rust
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183use std::{ collections::{HashMap, HashSet}, convert::Infallible, str::FromStr,};
use gcd::Gcd;use itertools::Itertools;
pub fn day8_part1(input: &str) -> String { let city: City = input.parse().unwrap(); let antinodes: HashSet<Point> = city.antinodes().collect(); antinodes.len().to_string()}
pub fn day8_part2(input: &str) -> String { let city: City = input.parse().unwrap(); let antinodes: HashSet<Point> = city.resonant_antinodes().collect(); antinodes.len().to_string()}
fn antinodes(antenna1: Point, antenna2: Point) -> (Option<Point>, Option<Point>) { let distance: Vector2 = (antenna1, antenna2).into(); let antinode1 = antenna2 + distance; let antinode2 = antenna1 - distance; (antinode1, antinode2)}
fn resonant_antinodes(antenna1: Point, antenna2: Point, width: usize, height: usize) -> Vec<Point> { let distance: Vector2 = (antenna1, antenna2).into(); let distance = distance.simplified(); let mut last_antinode = antenna1; let mut antinodes = vec![last_antinode]; while let Some(next_antinode) = last_antinode + distance { if next_antinode.row >= height || next_antinode.col >= width { break; } else { antinodes.push(next_antinode); last_antinode = next_antinode; } } let mut last_antinode = antenna1; while let Some(next_antinode) = last_antinode - distance { if next_antinode.row >= height || next_antinode.col >= width { break; } else { antinodes.push(next_antinode); last_antinode = next_antinode; } } antinodes}
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]struct Point { row: usize, col: usize,}
impl std::ops::Add<Vector2> for Point { type Output = Option<Self>;
fn add(self, rhs: Vector2) -> Self::Output { let row = self.row as isize + rhs.row_distance; let col = self.col as isize + rhs.col_distance; if row >= 0 && col >= 0 { Some(Self { row: row as usize, col: col as usize, }) } else { None } }}impl std::ops::Sub<Vector2> for Point { type Output = Option<Self>;
fn sub(self, rhs: Vector2) -> Self::Output { let row = self.row as isize - rhs.row_distance; let col = self.col as isize - rhs.col_distance; if row >= 0 && col >= 0 { Some(Self { row: row as usize, col: col as usize, }) } else { None } }}
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]struct Vector2 { row_distance: isize, col_distance: isize,}
impl From<(Point, Point)> for Vector2 { fn from((start, end): (Point, Point)) -> Self { Self { row_distance: end.row as isize - start.row as isize, col_distance: end.col as isize - start.col as isize, } }}
impl Vector2 { fn simplified(&self) -> Self { let mut retval = *self; let pos_col_distance: usize = retval.col_distance.unsigned_abs(); let pos_row_distance: usize = retval.row_distance.unsigned_abs(); let gcd = pos_col_distance.gcd(pos_row_distance); if gcd != 1 { retval.col_distance /= gcd as isize; retval.row_distance /= gcd as isize; } retval }}
#[derive(Debug)]struct City { width: usize, height: usize, antenna_groups: Vec<Vec<Point>>, inner: Vec<Vec<Option<char>>>,}
impl FromStr for City { type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> { let inner = s .lines() .map(|line| { line.chars() .map(|c| if c == '.' || c == '#' { None } else { Some(c) }) .collect() }) .collect_vec(); Ok(Self { antenna_groups: Self::make_antenna_groups(&inner), inner, width: s.lines().next().unwrap().len(), height: s.lines().count(), }) }}
impl City { fn make_antenna_groups(inner: &[Vec<Option<char>>]) -> Vec<Vec<Point>> { let mut retval: HashMap<char, Vec<Point>> = HashMap::new(); for row in 0..inner.len() { for col in 0..inner[0].len() { let cell = inner[row][col]; let Some(cell) = cell else { continue }; retval.entry(cell).or_default().push(Point { row, col }) } } retval.into_values().collect() } fn antenna_pairs(&self) -> impl Iterator<Item = (Point, Point)> { self .antenna_groups .iter() .flat_map(|group| group.iter().combinations(2)) .map(|combination| (*combination[0], *combination[1])) } fn antinodes(&self) -> impl Iterator<Item = Point> { self.antenna_pairs() .map(|(from, to)| antinodes(from, to)) .flat_map(|(a1, a2)| [a1, a2]) .flatten() .filter(|p| p.row < self.height && p.col < self.width) } fn resonant_antinodes(&self) -> impl Iterator<Item = Point> { self.antenna_pairs() .flat_map(|(from, to)| resonant_antinodes(from, to, self.width, self.height)) .filter(|p| p.row < self.height && p.col < self.width) }}