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 {
 | 
			
		||||
    map: Grid<u8>,
 | 
			
		||||
    antinodes: Grid<u8>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: BufRead> From<Lines<T>> for AntennaMap {
 | 
			
		||||
    fn from(input: Lines<T>) -> 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<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
 | 
			
		||||
 | 
			
		||||
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 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<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 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)]
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user