fn adjescent(p: &(usize,usize,usize), mx:usize) -> Vec<(usize,usize,usize)> { let mut v = vec![]; if p.0+1 < mx { v.push((p.0+1,p.1,p.2)); } if p.1+1 < mx { v.push((p.0,p.1+1,p.2)); } if p.2+1 < mx { v.push((p.0,p.1,p.2+1)); } if p.0 > 0 { v.push((p.0-1,p.1,p.2)); } if p.1 > 0 { v.push((p.0,p.1-1,p.2)); } if p.2 > 0 { v.push((p.0,p.1,p.2-1)); } v } #[derive(Debug,PartialEq)] enum State {Rock,Unknown,OutsideAir} fn mark_outside(grid: &mut Vec>>, curr: &(usize,usize,usize), mx: usize) { for cell in adjescent(curr, mx) { if let State::Unknown = grid[cell.0][cell.1][cell.2] { grid[cell.0][cell.1][cell.2] = State::OutsideAir; mark_outside(grid, &cell, mx); } } } fn surface_area(grid: &Vec>>, cubes: &Vec<(usize,usize,usize)>, mx: usize) -> usize { let surface_area: usize = cubes.iter().map(|cube| { let mut score = 6; for p in adjescent(cube, mx) { if let State::Rock = grid[p.0][p.1][p.2] { score -= 1; } } score }).sum(); surface_area } pub fn run(input:String) { let cubes = input.lines() .map(|line| { let res = line.split(",").map(|t| {t.parse::().unwrap()}).collect::>(); if res.len() != 3 { panic!("malformatted line! {}", line); } (res[0], res[1], res[2]) }).collect::>(); let mx: usize = cubes.iter().map(|t| {vec![t.0, t.1, t.2]}).flatten().max().unwrap() + 3; // Allocate a 3d space, and mark the rocky cubes let mut grid: Vec>> = (0..mx).map(|_| {(0..mx).map(|_| {(0..mx).map(|_| {State::Unknown}).collect()}).collect()}).collect(); for cube in cubes.iter() { grid[cube.0][cube.1][cube.2] = State::Rock; } // Now count cubes. Each contributes 6, minus number of adjescent rocky cubes println!("Day 18 pt1: {}", surface_area(&grid, &cubes, mx)); // So... how can I remove pockets of air to get the _outside_ surface area? // ans; fill in the inside areas! // pick a spot definitely on the outside;; iterate out until all the outside is marked. // Anything remaining is pockets, fill it in, re-calculate the outside surface area. grid[0][0][0] = State::OutsideAir; mark_outside(&mut grid, &(0,0,0), mx); // All remaining Unknown cells are air pockets, fill 'em in for x in 0..mx { for y in 0..mx { for z in 0..mx { match grid[x][y][z] { State::Unknown => { grid[x][y][z] = State::Rock; }, _ => () }; } } } // recalculate the surface area println!("Day 18 pt2: {}", surface_area(&grid, &cubes, mx)); }