Advertisement
nairby

2022 Day 18

Dec 18th, 2022
1,499
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 3.69 KB | None | 0 0
  1. use std::env;
  2. use std::io::{self, prelude::*, BufReader};
  3. use std::fs::File;
  4. use std::collections::HashMap;
  5.  
  6. use point3d::point3d::Point3D;
  7.  
  8. #[derive(Eq,PartialEq)]
  9. enum Voxel {
  10.     Lava,
  11.     Air,
  12. }
  13.  
  14. fn neighbors(pt: &Point3D) -> Vec<Point3D> {
  15.     vec![
  16.         Point3D { x: pt.x+1, y: pt.y  , z: pt.z   },
  17.         Point3D { x: pt.x-1, y: pt.y  , z: pt.z   },
  18.         Point3D { x: pt.x  , y: pt.y+1, z: pt.z   },
  19.         Point3D { x: pt.x  , y: pt.y-1, z: pt.z   },
  20.         Point3D { x: pt.x  , y: pt.y  , z: pt.z+1 },
  21.         Point3D { x: pt.x  , y: pt.y  , z: pt.z-1 },
  22.     ]
  23. }
  24.  
  25. fn coords_voxel(s: &str) -> (Point3D,Voxel) {
  26.     let coords: Vec<_> = s.split(",").collect();
  27.     let (x,y,z) = (coords[0].parse().unwrap(), coords[1].parse().unwrap(), coords[2].parse().unwrap());
  28.     (Point3D { x: x, y: y, z: z }, Voxel::Lava)
  29. }
  30.  
  31. fn flood_fill(pt: &Point3D, map: &mut HashMap<Point3D,Voxel>, xrange: (i64,i64), yrange: (i64,i64), zrange: (i64,i64)) {
  32.     let (xmin,xmax) = xrange;
  33.     let (ymin,ymax) = yrange;
  34.     let (zmin,zmax) = zrange;
  35.     if pt.x == xmin || pt.x == xmax || pt.y == ymin || pt.y == ymax || pt.z == zmin || pt.z == zmax { return }
  36.     match &map.get(&pt) {
  37.         Some(Voxel::Lava) | Some(Voxel::Air) => return,
  38.         _ => &map.insert(*pt,Voxel::Air),
  39.     };
  40.     flood_fill(&Point3D { x: pt.x + 1, y: pt.y    , z: pt.z    }, map, xrange, yrange, zrange);
  41.     flood_fill(&Point3D { x: pt.x - 1, y: pt.y    , z: pt.z    }, map, xrange, yrange, zrange);
  42.     flood_fill(&Point3D { x: pt.x    , y: pt.y + 1, z: pt.z    }, map, xrange, yrange, zrange);
  43.     flood_fill(&Point3D { x: pt.x    , y: pt.y - 1, z: pt.z    }, map, xrange, yrange, zrange);
  44.     flood_fill(&Point3D { x: pt.x    , y: pt.y    , z: pt.z + 1}, map, xrange, yrange, zrange);
  45.     flood_fill(&Point3D { x: pt.x    , y: pt.y    , z: pt.z - 1}, map, xrange, yrange, zrange);
  46. }
  47.  
  48. fn solve(input: &str) -> io::Result<()> {
  49.     let file = File::open(input).expect("Input file not found.");
  50.     let reader = BufReader::new(file);
  51.  
  52.     // Input
  53.     let input: Vec<String> = match reader.lines().collect() {
  54.         Err(err) => panic!("Unknown error reading input: {}", err),
  55.         Ok(result) => result,
  56.     };
  57.  
  58.     // Build map
  59.     let mut voxels: HashMap<Point3D,Voxel> = input.iter().map(|s| coords_voxel(s)).collect();
  60.  
  61.     // Part 1
  62.     let part1 = &voxels.len()*6
  63.               - &voxels.iter().map(|(pt,_)| {
  64.                     neighbors(&pt).iter().map(|n| match &voxels.get(&n) {
  65.                         Some(_) => 1, None => 0,
  66.                     }).sum::<usize>()
  67.               }).sum::<usize>();
  68.     println!("Part 1: {part1}"); // 3610
  69.  
  70.     // Determine maximum extents
  71.     let (xmin,xmax) = (&voxels.keys().map(|pt| pt.x).min().unwrap() - 2, &voxels.keys().map(|pt| pt.x).max().unwrap() + 2);
  72.     let (ymin,ymax) = (&voxels.keys().map(|pt| pt.y).min().unwrap() - 2, &voxels.keys().map(|pt| pt.y).max().unwrap() + 2);
  73.     let (zmin,zmax) = (&voxels.keys().map(|pt| pt.z).min().unwrap() - 2, &voxels.keys().map(|pt| pt.z).max().unwrap() + 2);
  74.  
  75.     // Flood the outer area with air
  76.     flood_fill(&Point3D { x: xmin+1, y: ymin+1, z: zmin+1 },&mut voxels, (xmin,xmax), (ymin,ymax), (zmin,zmax));
  77.  
  78.     // Calculate surface area
  79.     let part2 = &voxels
  80.         .iter()
  81.         .filter(|(_,v)| **v == Voxel::Lava)
  82.         .map(|(pt,_)| {
  83.             neighbors(&pt).iter().map(|n| match &voxels.get(&n) {
  84.                 Some(Voxel::Air) => 1, _ => 0,
  85.             }).sum::<usize>()
  86.         }).sum::<usize>();
  87.     println!("Part 2: {part2}"); // 2082
  88.  
  89.  
  90.     Ok(())
  91. }
  92.  
  93. fn main() {
  94.     let args: Vec<String> = env::args().collect();
  95.     let filename = &args[1];
  96.     solve(&filename).unwrap();
  97. }
  98.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement