diff --git a/8/src/main.rs b/8/src/main.rs index 69c2aa0..68a03ac 100644 --- a/8/src/main.rs +++ b/8/src/main.rs @@ -39,81 +39,70 @@ fn main() { struct AntennaMap { map: Grid, - antinodes: Grid, } impl From> for AntennaMap { fn from(input: Lines) -> Self { - let map = Grid::from(input); - let width = map.width(); - let height = map.height(); - Self { - map, - antinodes: Grid::with_shape(width, height, b'.'), + Self { map: Grid::from(input) } + } +} + +impl AntennaMap { + fn find_antinodes(&self, start: usize, reps: Option) -> Grid { + let mut antinodes = Grid::with_shape(self.map.width(), self.map.height(), false); + // find the unique frequencies in a dumb way + // NOTE: The dumb way is faster than the slightly-smarter ways I tried + let freq_set: HashSet<&u8> = HashSet::from_iter(self.map.data.iter().filter(|c| **c != b'.')); + + // for each unique frequency, get all the pairs' positions + for freq in freq_set { + for pair in self + .map + .data + .iter() + .enumerate() + .filter(|(_, c)| *c == freq) + .map(|(i, _)| self.map.coord(i as i64).unwrap()) + .permutations(2) + { + // permutations generates both pairs, ie. ((1,2),(2,1)) and ((2,1),(1,2)) so we don't need + // to consider the 'negative' side of the line, which will be generated by the other pair + let (a, b) = (pair[0], pair[1]); + let offset = (a.0 - b.0, a.1 - b.1); + for i in (start..).map_while(|i| { + if Some(i - start) != reps { + Some(i as i64) + } else { + None + } + }) { + let node_pos = (a.0 + i * offset.0, a.1 + i * offset.1); + if !antinodes.set(node_pos.0, node_pos.1, true) { + // left the grid + break; + } + } + } } + antinodes } } // PROBLEM 1 solution fn problem1(input: Lines) -> u64 { - let mut map = AntennaMap::from(input); + let map = AntennaMap::from(input); - // find the unique frequencies in a dumb way - let freq_set: HashSet<&u8> = HashSet::from_iter(map.map.data.iter().filter(|c| **c != b'.')); - - // for each unique frequency, get all the pairs' positions - for freq in freq_set { - let coords = map - .map - .data - .iter() - .enumerate() - .filter(|(_, c)| *c == freq) - .map(|(i, _)| map.map.coord(i as i64).unwrap()) - .collect_vec(); - - for pair in coords.iter().permutations(2).collect_vec() { - let (a, b) = (pair[0], pair[1]); - let node_pos = (a.0 + a.0 - b.0, a.1 + a.1 - b.1); - map.antinodes.set(node_pos.0, node_pos.1, b'#'); - } - } - map.antinodes.count(b'#') as u64 + let antinodes = map.find_antinodes(1, Some(1)); + antinodes.count(true) as u64 } // PROBLEM 2 solution fn problem2(input: Lines) -> u64 { - let mut map = AntennaMap::from(input); + let map = AntennaMap::from(input); - // find the unique frequencies in a dumb way - let freq_set: HashSet<&u8> = HashSet::from_iter(map.map.data.iter().filter(|c| **c != b'.')); - - // for each unique frequency, get all the pairs' positions - for freq in freq_set { - let coords = map - .map - .data - .iter() - .enumerate() - .filter(|(_, c)| *c == freq) - .map(|(i, _)| map.map.coord(i as i64).unwrap()) - .collect_vec(); - - for pair in coords.iter().permutations(2).collect_vec() { - let (a, b) = (pair[0], pair[1]); - let offset = (a.0 - b.0, a.1 - b.1); - let mut i = 0; - loop { - let node_pos = (a.0 + i * offset.0, a.1 + i * offset.1); - if !map.antinodes.set(node_pos.0, node_pos.1, b'#') { - break; - } - i += 1; - } - } - } - map.antinodes.count(b'#') as u64 + let antinodes = map.find_antinodes(0, None); + antinodes.count(true) as u64 } #[cfg(test)]