day8: refactor and cleanup
This commit is contained in:
		
							
								
								
									
										105
									
								
								8/src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								8/src/main.rs
									
									
									
									
									
								
							@@ -39,81 +39,70 @@ fn main() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct AntennaMap {
 | 
					struct AntennaMap {
 | 
				
			||||||
    map: Grid<u8>,
 | 
					    map: Grid<u8>,
 | 
				
			||||||
    antinodes: Grid<u8>,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: BufRead> From<Lines<T>> for AntennaMap {
 | 
					impl<T: BufRead> From<Lines<T>> for AntennaMap {
 | 
				
			||||||
    fn from(input: Lines<T>) -> Self {
 | 
					    fn from(input: Lines<T>) -> Self {
 | 
				
			||||||
        let map = Grid::from(input);
 | 
					        Self { map: Grid::from(input) }
 | 
				
			||||||
        let width = map.width();
 | 
					    }
 | 
				
			||||||
        let height = map.height();
 | 
					}
 | 
				
			||||||
        Self {
 | 
					
 | 
				
			||||||
            map,
 | 
					impl AntennaMap {
 | 
				
			||||||
            antinodes: Grid::with_shape(width, height, b'.'),
 | 
					    fn find_antinodes(&self, start: usize, reps: Option<usize>) -> Grid<bool> {
 | 
				
			||||||
 | 
					        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
 | 
					// PROBLEM 1 solution
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
 | 
					fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
 | 
				
			||||||
    let mut map = AntennaMap::from(input);
 | 
					    let map = AntennaMap::from(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // find the unique frequencies in a dumb way
 | 
					    let antinodes = map.find_antinodes(1, Some(1));
 | 
				
			||||||
    let freq_set: HashSet<&u8> = HashSet::from_iter(map.map.data.iter().filter(|c| **c != b'.'));
 | 
					    antinodes.count(true) as u64
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // 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
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PROBLEM 2 solution
 | 
					// PROBLEM 2 solution
 | 
				
			||||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
 | 
					fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
 | 
				
			||||||
    let mut map = AntennaMap::from(input);
 | 
					    let map = AntennaMap::from(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // find the unique frequencies in a dumb way
 | 
					    let antinodes = map.find_antinodes(0, None);
 | 
				
			||||||
    let freq_set: HashSet<&u8> = HashSet::from_iter(map.map.data.iter().filter(|c| **c != b'.'));
 | 
					    antinodes.count(true) as u64
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // 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
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user