day22: cleanup & nice output
This commit is contained in:
		
							
								
								
									
										110
									
								
								22/src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								22/src/main.rs
									
									
									
									
									
								
							@@ -68,16 +68,6 @@ impl std::fmt::Debug for BrickBlock {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl BrickBlock {
 | 
			
		||||
    fn map_into(&self, mut map: BlockMap) -> BlockMap {
 | 
			
		||||
        // loop over the (inclusive) bounding coordinates and add them all to the map
 | 
			
		||||
        map.slice_mut(s![
 | 
			
		||||
            std::cmp::min(self.c1.x, self.c2.x)..std::cmp::max(self.c1.x, self.c2.x) + 1,
 | 
			
		||||
            std::cmp::min(self.c1.y, self.c2.y)..std::cmp::max(self.c1.y, self.c2.y) + 1,
 | 
			
		||||
            std::cmp::min(self.c1.z, self.c2.z)..std::cmp::max(self.c1.z, self.c2.z) + 1
 | 
			
		||||
        ])
 | 
			
		||||
        .fill(Some(self.to_owned()));
 | 
			
		||||
        map
 | 
			
		||||
    }
 | 
			
		||||
    fn bottom_z_plane(&self) -> usize {
 | 
			
		||||
        std::cmp::min(self.c1.z, self.c2.z)
 | 
			
		||||
    }
 | 
			
		||||
@@ -136,9 +126,9 @@ impl BlockPile {
 | 
			
		||||
        // loop over the (inclusive) bounding coordinates and remove them all from the map
 | 
			
		||||
        self.block_map
 | 
			
		||||
            .slice_mut(s![
 | 
			
		||||
                std::cmp::min(block.c1.x, block.c2.x)..std::cmp::max(block.c1.x, block.c2.x) + 1,
 | 
			
		||||
                std::cmp::min(block.c1.y, block.c2.y)..std::cmp::max(block.c1.y, block.c2.y) + 1,
 | 
			
		||||
                std::cmp::min(block.c1.z, block.c2.z)..std::cmp::max(block.c1.z, block.c2.z) + 1
 | 
			
		||||
                block.bottom_x_plane()..block.top_x_plane() + 1,
 | 
			
		||||
                block.bottom_y_plane()..block.top_y_plane() + 1,
 | 
			
		||||
                block.bottom_z_plane()..block.top_z_plane() + 1,
 | 
			
		||||
            ])
 | 
			
		||||
            .fill(None);
 | 
			
		||||
        self.blocks.remove(self.blocks.iter().position(|b| b == block).unwrap());
 | 
			
		||||
@@ -147,9 +137,9 @@ impl BlockPile {
 | 
			
		||||
        // loop over the (inclusive) bounding coordinates and remove them all from the map
 | 
			
		||||
        self.block_map
 | 
			
		||||
            .slice_mut(s![
 | 
			
		||||
                std::cmp::min(block.c1.x, block.c2.x)..std::cmp::max(block.c1.x, block.c2.x) + 1,
 | 
			
		||||
                std::cmp::min(block.c1.y, block.c2.y)..std::cmp::max(block.c1.y, block.c2.y) + 1,
 | 
			
		||||
                std::cmp::min(block.c1.z, block.c2.z)..std::cmp::max(block.c1.z, block.c2.z) + 1
 | 
			
		||||
                block.bottom_x_plane()..block.top_x_plane() + 1,
 | 
			
		||||
                block.bottom_y_plane()..block.top_y_plane() + 1,
 | 
			
		||||
                block.bottom_z_plane()..block.top_z_plane() + 1,
 | 
			
		||||
            ])
 | 
			
		||||
            .fill(Some(block.to_owned()));
 | 
			
		||||
        self.blocks.push(block.clone());
 | 
			
		||||
@@ -195,11 +185,11 @@ impl BlockPile {
 | 
			
		||||
            block.bottom_y_plane()..block.top_y_plane() + 1,
 | 
			
		||||
            1..z_plane // don't include our own plane
 | 
			
		||||
        ]);
 | 
			
		||||
        // find the highest z value
 | 
			
		||||
        // find the highest top z value of those
 | 
			
		||||
        let block_below = directly_below
 | 
			
		||||
            .indexed_iter()
 | 
			
		||||
            .filter_map(|(idx, v)| if let Some(val) = v { Some((idx, val)) } else { None })
 | 
			
		||||
            .max_by(|(_, a), (_, b)| a.top_z_plane().cmp(&b.top_z_plane()));
 | 
			
		||||
            .max_by_key(|(_idx, v)| v.top_z_plane());
 | 
			
		||||
 | 
			
		||||
        if let Some(block) = block_below {
 | 
			
		||||
            Some(block.1.top_z_plane())
 | 
			
		||||
@@ -247,24 +237,22 @@ impl BlockPile {
 | 
			
		||||
 | 
			
		||||
impl<T: BufRead> From<Lines<T>> for BlockPile {
 | 
			
		||||
    fn from(lines: Lines<T>) -> Self {
 | 
			
		||||
        let mut new: BlockPile = Self {
 | 
			
		||||
            blocks: lines.map(|line| BrickBlock::from(line.unwrap().as_str())).collect(),
 | 
			
		||||
            block_map: Array3::from_elem([0, 0, 0], None),
 | 
			
		||||
            bounds: (0, 0, 0),
 | 
			
		||||
        let blocks = lines.map(|line| BrickBlock::from(line.unwrap().as_str())).collect_vec();
 | 
			
		||||
        let mut bounds = (0, 0, 0);
 | 
			
		||||
        for block in &blocks {
 | 
			
		||||
            bounds.0 = std::cmp::max(block.top_x_plane() + 1, bounds.0);
 | 
			
		||||
            bounds.1 = std::cmp::max(block.top_y_plane() + 1, bounds.1);
 | 
			
		||||
            bounds.2 = std::cmp::max(block.top_z_plane() + 1, bounds.2);
 | 
			
		||||
        }
 | 
			
		||||
        let mut new = BlockPile {
 | 
			
		||||
            blocks: Vec::new(),
 | 
			
		||||
            bounds,
 | 
			
		||||
            block_map: BlockMap::from_elem(bounds, None),
 | 
			
		||||
            graph: Graph::default(),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        for block in &new.blocks {
 | 
			
		||||
            new.bounds.0 = std::cmp::max(block.c1.x + 1, std::cmp::max(block.c2.y + 1, new.bounds.0));
 | 
			
		||||
            new.bounds.1 = std::cmp::max(block.c1.y + 1, std::cmp::max(block.c2.y + 1, new.bounds.1));
 | 
			
		||||
            new.bounds.2 = std::cmp::max(block.c1.z + 1, std::cmp::max(block.c2.z + 1, new.bounds.2));
 | 
			
		||||
        for block in blocks {
 | 
			
		||||
            new.add_block(&block);
 | 
			
		||||
        }
 | 
			
		||||
        let mut block_map = BlockMap::from_elem(new.bounds, None);
 | 
			
		||||
 | 
			
		||||
        for block in &new.blocks {
 | 
			
		||||
            block_map = block.map_into(block_map);
 | 
			
		||||
        }
 | 
			
		||||
        new.block_map = block_map;
 | 
			
		||||
 | 
			
		||||
        new
 | 
			
		||||
    }
 | 
			
		||||
@@ -272,30 +260,36 @@ impl<T: BufRead> From<Lines<T>> for BlockPile {
 | 
			
		||||
 | 
			
		||||
impl Display for BlockPile {
 | 
			
		||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        // XZ view
 | 
			
		||||
        writeln!(f, "XZ: [{}, {}]", self.bounds.0, self.bounds.2)?;
 | 
			
		||||
        for z in (0..self.bounds.2).rev() {
 | 
			
		||||
            for x in 0..self.bounds.0 {
 | 
			
		||||
                let y = self.block_map.slice(s![x..x + 1, .., z..z + 1]);
 | 
			
		||||
                f.write_char(match y.iter().filter(|v| v.is_some()).count() {
 | 
			
		||||
                    0 => '.',
 | 
			
		||||
                    1 => '#',
 | 
			
		||||
                    _ => '?',
 | 
			
		||||
                })?;
 | 
			
		||||
            let z_plane = self.block_map.slice(s![.., .., z..z+1]);
 | 
			
		||||
            if z_plane.iter().all(|b| b.is_none()) { continue };
 | 
			
		||||
            for i in 0..self.bounds.0 {
 | 
			
		||||
                // XZ view
 | 
			
		||||
                let y = z_plane.slice(s![i..i + 1, .., ..]);
 | 
			
		||||
                f.write_char(
 | 
			
		||||
                    match y.iter().enumerate().find_map(|(idx, val)| val.is_some().then(|| idx)) {
 | 
			
		||||
                        None => ' ',
 | 
			
		||||
                        Some(0) | Some(1) => '█',
 | 
			
		||||
                        Some(2) | Some(3) => '▓',
 | 
			
		||||
                        Some(4) | Some(5) => '▒',
 | 
			
		||||
                        Some(6) | Some(7) => '░',
 | 
			
		||||
                        _ => '░',
 | 
			
		||||
                    },
 | 
			
		||||
                )?;
 | 
			
		||||
            }
 | 
			
		||||
            writeln!(f, " {}", z)?;
 | 
			
		||||
        }
 | 
			
		||||
        // YZ view
 | 
			
		||||
        writeln!(f)?;
 | 
			
		||||
        writeln!(f, "YZ: [{}, {}]", self.bounds.1, self.bounds.2)?;
 | 
			
		||||
        for z in (0..self.bounds.2).rev() {
 | 
			
		||||
            write!(f, "  {}  ", z)?;
 | 
			
		||||
            for y in 0..self.bounds.1 {
 | 
			
		||||
                let x = self.block_map.slice(s![.., y..y + 1, z..z + 1]);
 | 
			
		||||
                f.write_char(match x.iter().filter(|v| v.is_some()).count() {
 | 
			
		||||
                    0 => '.',
 | 
			
		||||
                    1 => '#',
 | 
			
		||||
                    _ => '?',
 | 
			
		||||
                })?;
 | 
			
		||||
                let x = z_plane.slice(s![.., y..y + 1, ..]);
 | 
			
		||||
                f.write_char(
 | 
			
		||||
                    match x.iter().enumerate().find_map(|(idx, val)| val.is_some().then(|| idx)) {
 | 
			
		||||
                        None => ' ',
 | 
			
		||||
                        Some(0) | Some(1) => '█',
 | 
			
		||||
                        Some(2) | Some(3) => '▓',
 | 
			
		||||
                        Some(4) | Some(5) => '▒',
 | 
			
		||||
                        Some(6) | Some(7) => '░',
 | 
			
		||||
                        _ => '░',
 | 
			
		||||
                    },
 | 
			
		||||
                )?;
 | 
			
		||||
            }
 | 
			
		||||
            writeln!(f, " {}", z)?;
 | 
			
		||||
        }
 | 
			
		||||
@@ -328,7 +322,6 @@ fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
 | 
			
		||||
    pile.build_graph();
 | 
			
		||||
 | 
			
		||||
    println!("{}", pile);
 | 
			
		||||
    println!("block 0 {:?}", pile.blocks[0]);
 | 
			
		||||
 | 
			
		||||
    let mut accum = 0;
 | 
			
		||||
    let fixed_nodes = pile
 | 
			
		||||
@@ -356,19 +349,12 @@ fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
 | 
			
		||||
            .unique()
 | 
			
		||||
            .count();
 | 
			
		||||
        // we are looking for the nodes that *will* disintegrate
 | 
			
		||||
        println!(
 | 
			
		||||
            "From {}, {} safe, {} disintegrate",
 | 
			
		||||
            node.index(),
 | 
			
		||||
            safe_blocks,
 | 
			
		||||
            pile.graph.node_count() - safe_blocks
 | 
			
		||||
        );
 | 
			
		||||
        accum += pile.graph.node_count() - safe_blocks;
 | 
			
		||||
        // put the graph back how it was
 | 
			
		||||
        for neigh in dependents {
 | 
			
		||||
            pile.graph.add_edge(node, neigh, ());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    println!("blocks: {} nodes: {}", pile.blocks.len(), pile.graph.node_count());
 | 
			
		||||
    accum as u64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user