Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::cmp::{max, min};
- use std::collections::HashSet;
- use fxhash::FxHashSet;
- use itertools::Itertools;
- pub fn day22_1() {
- let input: Vec<(bool, (i32, i32), (i32, i32), (i32, i32))> = include_str!("../temp22").lines().map(|x| {
- let (state, rest) = x.split_once(" x=").unwrap();
- let (x1, rest) = rest.split_once("..").unwrap();
- let (x2, rest) = rest.split_once(",y=").unwrap();
- let (y1, rest) = rest.split_once("..").unwrap();
- let (y2, rest) = rest.split_once(",z=").unwrap();
- let (z1, z2) = rest.split_once("..").unwrap();
- (state.eq("on"),
- (x1.parse().unwrap(), x2.parse().unwrap()),
- (y1.parse().unwrap(), y2.parse().unwrap()),
- (z1.parse().unwrap(), z2.parse().unwrap()))
- }).collect_vec();
- let mut states = FxHashSet::default();
- for (state, x, y, z) in input {
- if x.1 < -50 || y.1 < -50 || z.1 < -50 || x.0 > 50 || y.0 > 50 || z.0 > 50
- {
- //outside part 1 bounds
- continue;
- }
- //remap the bounds for part 1
- let (x1, x2) = (max(x.0, -50), min(50, x.1));
- let (y1, y2) = (max(y.0, -50), min(50, y.1));
- let (z1, z2) = (max(z.0, -50), min(50, z.1));
- //add stuff
- if state {
- states.extend((x1..=x2).cartesian_product(y1..=y2).cartesian_product(z1..=z2));
- }
- else {
- //remove stuff
- states = states.difference(
- &FxHashSet::from_iter((x1..=x2).cartesian_product(y1..=y2).cartesian_product(z1..=z2))
- ).map(|&x| x).collect();
- }
- }
- println!("ANS: {}", states.len());
- }
- #[derive(Debug)]
- struct Cube {
- x: [i32; 2],
- y: [i32; 2],
- z: [i32; 2]
- }
- impl Cube {
- fn intersects(&self, other: &Cube) -> bool
- {
- let this_corners = self.get_corners();
- for (x, y, z) in this_corners {
- if x >= other.x[0] && x <= other.x[1] && y >= other.y[0] && y <= other.y[1] && z >= other.z[0] && z <= other.z[1]
- {
- return true;
- }
- }
- let other_corners = other.get_corners();
- for (x, y, z) in other_corners {
- if x >= self.x[0] && x <= self.x[1] && y >= self.y[0] && y <= self.y[1] && z >= self.z[0] && z <= self.z[1]
- {
- return true;
- }
- }
- return false;
- }
- fn intersects2(&self, other: &Cube) -> bool
- {
- self.x[0] <= other.x[1] && self.x[1] >= other.x[0]
- && self.y[0] <= other.y[1] && self.y[1] >= other.y[0]
- && self.z[0] <= other.z[1] && self.z[1] >= other.z[0]
- }
- fn get_corners(&self) -> Vec<(i32, i32, i32)> {
- self.x.iter().cartesian_product(self.y.iter()).cartesian_product(self.z.iter()).map(|(xy, (z))| (*xy.0, *xy.1, *z)).collect_vec()
- }
- fn cut(mut self, other: &Cube) -> Vec<Cube>
- {
- //let (selfx, selfy, selfz) = (self.x, self.y, self.z)
- let mut ret = Vec::new();
- if self.x[0] < other.x[0] {
- ret.push(Cube {
- x: [self.x[0], other.x[0] - 1],
- y: self.y,
- z: self.z,
- });
- self.x[0] = other.x[0];
- }
- if self.x[1] > other.x[1] {
- ret.push(Cube {
- x: [other.x[1] + 1, self.x[1]],
- y: self.y,
- z: self.z,
- });
- self.x[1] = other.x[1];
- }
- //y
- if self.y[0] < other.y[0] {
- ret.push(Cube {
- x: self.x,
- y: [self.y[0], other.y[0] - 1],
- z: self.z,
- });
- self.y[0] = other.y[0];
- }
- if self.y[1] > other.y[1] {
- ret.push(Cube {
- x: self.x,
- y: [other.y[1] + 1, self.y[1]],
- z: self.z,
- });
- self.y[1] = other.y[1];
- }
- //z
- if self.z[0] < other.z[0] {
- ret.push(Cube {
- x: self.x,
- y: self.y,
- z: [self.z[0], other.z[0] - 1],
- });
- self.z[0] = other.z[0];
- }
- if self.z[1] > other.z[1] {
- ret.push(Cube {
- x: self.x,
- y: self.y,
- z: [other.z[1] + 1, self.z[1]],
- });
- self.z[1] = other.z[1];
- }
- return ret;
- }
- fn vol(&self) -> usize
- {
- ((self.x[1] - self.x[0]) as usize + 1) *
- ((self.y[1] - self.y[0]) as usize + 1) *
- ((self.z[1] - self.z[0]) as usize + 1)
- }
- }
- pub fn day22_2() {
- let mut states: Vec<Cube> = Vec::default();
- let input: Vec<(bool, [i32; 2], [i32; 2], [i32; 2])> = include_str!("../temp22").lines().map(|x| {
- let (state, rest) = x.split_once(" x=").unwrap();
- let (x1, rest) = rest.split_once("..").unwrap();
- let (x2, rest) = rest.split_once(",y=").unwrap();
- let (y1, rest) = rest.split_once("..").unwrap();
- let (y2, rest) = rest.split_once(",z=").unwrap();
- let (z1, z2) = rest.split_once("..").unwrap();
- (state.eq("on"),
- [x1.parse().unwrap(), x2.parse().unwrap()],
- [y1.parse().unwrap(), y2.parse().unwrap()],
- [z1.parse().unwrap(), z2.parse().unwrap()])
- }).collect_vec();
- for (state, x, y, z) in input {
- let this = Cube{x, y, z};
- //remove all intersections to get rid of overlap
- let mut newCubes = states.drain_filter(|other| other.intersects2(&this)).flat_map(|other| other.cut(&this)).collect();
- states.append(&mut newCubes);
- if state {
- //add the now non intersected thing.
- states.push(this)
- }
- }
- println!("ANS: {}", states.iter().fold(0, |acc, x | acc + x.vol()));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement