advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

main.rs (4135B)

    1 use std::collections::{HashMap, HashSet};
    2 
    3 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
    4 enum Command {
    5     On,
    6     Off,
    7 }
    8 
    9 #[derive(Debug, Clone, Copy)]
   10 struct Cuboid {
   11     x: (i32, i32),
   12     y: (i32, i32),
   13     z: (i32, i32),
   14 }
   15 
   16 impl Cuboid {
   17     fn new(s: &str) -> Self {
   18         let ranges = s
   19             .split(',')
   20             .map(|x| x.split('=').skip(1).next().unwrap().to_string())
   21             .map(|x| {
   22                 let mut it = x.split("..");
   23                 (
   24                     it.next().unwrap().parse::<i32>().unwrap(),
   25                     it.next().unwrap().parse::<i32>().unwrap(),
   26                 )
   27             })
   28             .collect::<Vec<_>>();
   29         Cuboid {
   30             x: ranges[0],
   31             y: ranges[1],
   32             z: ranges[2],
   33         }
   34     }
   35 
   36     fn within(&self, other: &Cuboid) -> bool {
   37         (self.x.0 >= other.x.0 && self.x.1 <= other.x.1)
   38             && (self.y.0 >= other.y.0 && self.y.1 <= other.y.1)
   39             && (self.z.0 >= other.z.0 && self.z.1 <= other.z.1)
   40     }
   41 }
   42 
   43 fn main() {
   44     let input = std::fs::read_to_string("input.txt")
   45         .unwrap()
   46         .trim()
   47         .split('\n')
   48         .map(|s| {
   49             let mut it = s.split(' ');
   50             let cmd = match it.next().unwrap() {
   51                 "on" => Command::On,
   52                 "off" => Command::Off,
   53                 _ => unreachable!(),
   54             };
   55             let cuboid = Cuboid::new(it.next().unwrap());
   56             (cmd, cuboid)
   57         })
   58         .collect::<Vec<_>>();
   59     // 547648
   60     println!("Part 1: {}", part_1(&input));
   61     // 1206644425246111
   62     println!("Part 2: {}", part_2(&input));
   63 }
   64 
   65 fn run_command(input: &[(Command, Cuboid)]) -> usize {
   66     // decompose input space
   67     let mut xs = HashSet::new();
   68     let mut ys = HashSet::new();
   69     let mut zs = HashSet::new();
   70     for &(_, cubmoid) in input.iter() {
   71         // convert into traditional index format
   72         xs.insert(cubmoid.x.0);
   73         xs.insert(cubmoid.x.1 + 1);
   74         ys.insert(cubmoid.y.0);
   75         ys.insert(cubmoid.y.1 + 1);
   76         zs.insert(cubmoid.z.0);
   77         zs.insert(cubmoid.z.1 + 1);
   78     }
   79     let mut xs = xs.into_iter().collect::<Vec<_>>();
   80     xs.sort();
   81     let mut ys = ys.into_iter().collect::<Vec<_>>();
   82     ys.sort();
   83     let mut zs = zs.into_iter().collect::<Vec<_>>();
   84     zs.sort();
   85     let xs_idx = xs
   86         .iter()
   87         .enumerate()
   88         .map(|(i, x)| (*x, i))
   89         .collect::<HashMap<i32, usize>>();
   90     let ys_idx = ys
   91         .iter()
   92         .enumerate()
   93         .map(|(i, y)| (*y, i))
   94         .collect::<HashMap<i32, usize>>();
   95     let zs_idx = zs
   96         .iter()
   97         .enumerate()
   98         .map(|(i, z)| (*z, i))
   99         .collect::<HashMap<i32, usize>>();
  100 
  101     let mut cuboid_state = HashMap::new();
  102     for &(cmd, cuboid) in input.iter() {
  103         let x_idx_min = xs_idx[&cuboid.x.0];
  104         let x_idx_max = xs_idx[&(cuboid.x.1 + 1)];
  105         let y_idx_min = ys_idx[&cuboid.y.0];
  106         let y_idx_max = ys_idx[&(cuboid.y.1 + 1)];
  107         let z_idx_min = zs_idx[&cuboid.z.0];
  108         let z_idx_max = zs_idx[&(cuboid.z.1 + 1)];
  109 
  110         for x_idx in x_idx_min..x_idx_max {
  111             for y_idx in y_idx_min..y_idx_max {
  112                 for z_idx in z_idx_min..z_idx_max {
  113                     cuboid_state.insert((x_idx, y_idx, z_idx), cmd);
  114                 }
  115             }
  116         }
  117     }
  118     cuboid_state
  119         .iter()
  120         .map(|(&(x_idx, y_idx, z_idx), cmd)| match cmd {
  121             Command::On => {
  122                 (xs[x_idx + 1] - xs[x_idx]) as usize
  123                     * (ys[y_idx + 1] - ys[y_idx]) as usize
  124                     * (zs[z_idx + 1] - zs[z_idx]) as usize
  125             }
  126             Command::Off => 0,
  127         })
  128         .sum()
  129 }
  130 
  131 fn part_1(input: &[(Command, Cuboid)]) -> usize {
  132     let init_region = Cuboid {
  133         x: (-50, 50),
  134         y: (-50, 50),
  135         z: (-50, 50),
  136     };
  137     let init_end = input
  138         .iter()
  139         .enumerate()
  140         .find(|(_, &(_, cuboid))| !cuboid.within(&init_region))
  141         .unwrap()
  142         .0;
  143     run_command(&input[..init_end])
  144 }
  145 
  146 fn part_2(input: &[(Command, Cuboid)]) -> usize {
  147     run_command(input)
  148 }