Advertisement
nairby

Day 22 Code

Dec 31st, 2021 (edited)
325
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.25 KB | None | 0 0
  1. use std::env;
  2. use std::io::{prelude::*, BufReader};
  3. use std::fs::File;
  4. use std::ops::RangeInclusive;
  5. use std::collections::HashMap;
  6. use std::cmp::{min,max};
  7.  
  8. extern crate regex;
  9. use regex::Regex;
  10.  
  11. #[derive(Clone,Debug)]
  12. struct Cuboid {
  13.     status: bool,
  14.     x: RangeInclusive<i64>,
  15.     y: RangeInclusive<i64>,
  16.     z: RangeInclusive<i64>,
  17. }
  18. impl From<&String> for Cuboid {
  19.     fn from(s: &String) -> Self {
  20.         let re = Regex::new(r"(on|off) x=(\-*\d+)\.\.(\-*\d+),y=(\-*\d+)\.\.(\-*\d+),z=(\-*\d+)\.\.(\-*\d+)").unwrap();
  21.         let matches = re.captures(s).unwrap();
  22.         let status = match &matches[1] {
  23.             "on" => true,
  24.             "off" => false,
  25.             _ => unreachable!()
  26.         };
  27.         Self {
  28.             status: status,
  29.             x: (matches[2].parse().unwrap()..=matches[3].parse().unwrap()),
  30.             y: (matches[4].parse().unwrap()..=matches[5].parse().unwrap()),
  31.             z: (matches[6].parse().unwrap()..=matches[7].parse().unwrap()),
  32.         }
  33.     }
  34. }
  35. impl Cuboid {
  36.     pub fn new(x: RangeInclusive<i64>, y: RangeInclusive<i64>, z: RangeInclusive<i64>, status: bool) -> Self {
  37.         Self { status: status, x: x, y: y, z: z }
  38.     }
  39.  
  40.     pub fn raw_volume(&self) -> i64 {
  41.         range_size(&self.x) * range_size(&self.y) * range_size(&self.z)
  42.     }
  43.  
  44.     pub fn signed_volume(&self) -> i64 {
  45.         self.raw_volume() * if self.status { 1 } else { -1 }
  46.     }
  47.  
  48.     pub fn intersection(&self, other: &Cuboid, status: bool) -> Cuboid {
  49.         let xsect = RangeInclusive::new(*max(self.x.start(), other.x.start()), *min(self.x.end(), other.x.end()));
  50.         let ysect = RangeInclusive::new(*max(self.y.start(), other.y.start()), *min(self.y.end(), other.y.end()));
  51.         let zsect = RangeInclusive::new(*max(self.z.start(), other.z.start()), *min(self.z.end(), other.z.end()));
  52.         Cuboid::new(xsect, ysect, zsect, status)
  53.     }
  54.  
  55.     pub fn intersects(&self, other: &Cuboid) -> bool {
  56.         // intersection: (max(a.begin, b.begin), min(a.end, b.end))
  57.         let xsect = RangeInclusive::new(*max(self.x.start(), other.x.start()), *min(self.x.end(), other.x.end()));
  58.         let ysect = RangeInclusive::new(*max(self.y.start(), other.y.start()), *min(self.y.end(), other.y.end()));
  59.         let zsect = RangeInclusive::new(*max(self.z.start(), other.z.start()), *min(self.z.end(), other.z.end()));
  60.         !xsect.is_empty() && !ysect.is_empty() && !zsect.is_empty()
  61.     }
  62. }
  63.  
  64. fn range_size(range: &RangeInclusive<i64>) -> i64 {
  65.     if !range.is_empty() { range.end() - range.start() + 1 } else { 0 }
  66. }
  67.  
  68. fn solve2(input: &str) {
  69.     let file = File::open(input).expect("Input file not found.");
  70.     let reader = BufReader::new(file);
  71.  
  72.     // Input
  73.     let input: Vec<String> = match reader.lines().collect() {
  74.         Err(err) => panic!("Unknown error reading input: {}", err),
  75.         Ok(result) => result,
  76.     };
  77.     let cuboids: Vec<_> = input.iter().map(Cuboid::from).collect();
  78.  
  79.     // Process instructions
  80.     let mut final_cuboids: Vec<Cuboid> = Vec::new();
  81.     for cuboid in &cuboids {
  82.         let mut new_cuboids: Vec<Cuboid> = Vec::new();
  83.         for final_cuboid in &final_cuboids {
  84.             if cuboid.intersects(final_cuboid) {
  85.                 let new_status = if cuboid.status && final_cuboid.status { false }
  86.                            else if !cuboid.status && !final_cuboid.status { true }
  87.                            else { cuboid.status };
  88.                 new_cuboids.push(cuboid.intersection(&final_cuboid,new_status));
  89.             }
  90.         }
  91.         if cuboid.status { final_cuboids.push(cuboid.clone()); }
  92.         final_cuboids.append(&mut new_cuboids);
  93.     }
  94.  
  95.     // Count volumes
  96.     let part2: i64 = final_cuboids
  97.         .iter()
  98.         .map(|s| s.signed_volume())
  99.         .sum();
  100.     println!("Part 2: {}", part2); // 1334238660555542
  101. }
  102.  
  103.  
  104. fn solve1(input: &str) {
  105.     let file = File::open(input).expect("Input file not found.");
  106.     let reader = BufReader::new(file);
  107.  
  108.     // Input
  109.     let input: Vec<String> = match reader.lines().collect() {
  110.         Err(err) => panic!("Unknown error reading input: {}", err),
  111.         Ok(result) => result,
  112.     };
  113.  
  114.     let steps: Vec<_> = input.iter().map(Cuboid::from).collect();
  115.  
  116.     // Reboot
  117.     let mut reactor: HashMap<(i64,i64,i64),bool> = HashMap::new();
  118.     steps.iter().for_each(|s| {
  119.         let xmin = std::cmp::max(s.x.start(),&-50i64);
  120.         let xmax = std::cmp::min(s.x.end(),&50i64);
  121.         let ymin = std::cmp::max(s.y.start(),&-50i64);
  122.         let ymax = std::cmp::min(s.y.end(),&50i64);
  123.         let zmin = std::cmp::max(s.z.start(),&-50i64);
  124.         let zmax = std::cmp::min(s.z.end(),&50i64);
  125.         for z in *zmin..=*zmax {
  126.             for y in *ymin..=*ymax {
  127.                 for x in *xmin..=*xmax {
  128.                     if s.status {
  129.                         reactor.insert((x,y,z),true);
  130.                     } else {
  131.                         reactor.remove(&(x,y,z));
  132.                     }
  133.                 }
  134.             }
  135.         }
  136.     });
  137.  
  138.     let part1 = reactor.iter().filter(|&(_,v)| *v).count();
  139.     println!("Part 1: {}", part1); // 580012
  140.  
  141. }
  142.  
  143. fn main() {
  144.     let args: Vec<String> = env::args().collect();
  145.     let filename = &args[1];
  146.     solve1(&filename);
  147.     solve2(&filename);
  148. }
  149.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement