2022 - Day 18
This commit is contained in:
parent
27d845d8ff
commit
8915fb135e
|
@ -33,6 +33,10 @@ mod tests {
|
||||||
fn part2_test2() -> Result<()> {
|
fn part2_test2() -> Result<()> {
|
||||||
Day::test(Day::part2, "test-2", 58)
|
Day::test(Day::part2, "test-2", 58)
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
|
fn part2_solution() -> Result<()> {
|
||||||
|
Day::test(Day::part2, "input", 2028)
|
||||||
|
}
|
||||||
|
|
||||||
// Benchmarks
|
// Benchmarks
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
@ -113,6 +117,53 @@ fn calculate_surface(cubes: HashSet<Vec3>) -> usize {
|
||||||
}).sum()
|
}).sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Check(Vec<Vec<Vec<(bool, bool)>>>);
|
||||||
|
|
||||||
|
impl Check {
|
||||||
|
fn new(size: &Vec3) -> Self {
|
||||||
|
Check(vec![vec![vec![(false, false); size.z as usize]; size.y as usize]; size.x as usize])
|
||||||
|
}
|
||||||
|
fn get_mut(&mut self, p: &Vec3) -> &mut (bool, bool) {
|
||||||
|
&mut self.0[p.x as usize][p.y as usize][p.z as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&self, p: &Vec3) -> &(bool, bool) {
|
||||||
|
&self.0[p.x as usize][p.y as usize][p.z as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn fill(check: &mut Check, cubes: &HashSet<Vec3>, size: &Vec3, pos: Vec3) {
|
||||||
|
// Mark current space as air and checked
|
||||||
|
*check.get_mut(&pos) = (true, true); // (is_checked, is_air)
|
||||||
|
|
||||||
|
let offsets = offset();
|
||||||
|
|
||||||
|
for offset in offsets.iter() {
|
||||||
|
let next = &pos + offset;
|
||||||
|
|
||||||
|
// Check if the location is within bounds
|
||||||
|
if next.x < 0 || next.x >= size.x || next.y < 0 || next.y >= size.y || next.z < 0 || next.z >= size.z {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we have already checked the location
|
||||||
|
if check.get(&next).0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the space is filled with lava
|
||||||
|
if cubes.contains(&next) {
|
||||||
|
// Mark the space as checked and not containing air
|
||||||
|
*check.get_mut(&next) = (true, false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explore the next location
|
||||||
|
fill(check, cubes, size, next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -- Solution --
|
// -- Solution --
|
||||||
pub struct Day;
|
pub struct Day;
|
||||||
impl aoc::Solver for Day {
|
impl aoc::Solver for Day {
|
||||||
|
@ -130,7 +181,7 @@ impl aoc::Solver for Day {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(input: &str) -> Self::Output2 {
|
fn part2(input: &str) -> Self::Output2 {
|
||||||
let cubes = parse(input);
|
let mut cubes = parse(input);
|
||||||
|
|
||||||
let size = cubes
|
let size = cubes
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -142,107 +193,22 @@ impl aoc::Solver for Day {
|
||||||
return acc;
|
return acc;
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut check = vec![vec![vec![[false; 6]; size.z as usize]; size.y as usize]; size.x as usize];
|
// (is_checked, is_air)
|
||||||
|
let mut check = Check::new(&size);
|
||||||
|
|
||||||
// Z+
|
fill(&mut check, &cubes, &size, Vec3::new(0, 0, 0));
|
||||||
for x in 0..size.x {
|
|
||||||
for y in 0..size.y {
|
|
||||||
if let Some(end) = (0..size.z)
|
|
||||||
.position(|z| {
|
|
||||||
cubes.contains(&Vec3::new(x, y, z))
|
|
||||||
}) {
|
|
||||||
for z in end..size.z as usize {
|
|
||||||
check[x as usize][y as usize][z][0] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Z-
|
|
||||||
for x in 0..size.x {
|
|
||||||
for y in 0..size.y {
|
|
||||||
if let Some(end) = (0..size.z)
|
|
||||||
.rev()
|
|
||||||
.position(|z| {
|
|
||||||
cubes.contains(&Vec3::new(x, y, z))
|
|
||||||
}) {
|
|
||||||
for z in 0..size.z as usize - end {
|
|
||||||
check[x as usize][y as usize][z][1] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Y+
|
|
||||||
for z in 0..size.z {
|
|
||||||
for x in 0..size.x {
|
|
||||||
if let Some(end) = (0..size.y)
|
|
||||||
.position(|y| {
|
|
||||||
cubes.contains(&Vec3::new(x, y, z))
|
|
||||||
}) {
|
|
||||||
for y in end..size.y as usize {
|
|
||||||
check[x as usize][y][z as usize][2] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Y-
|
|
||||||
for z in 0..size.z {
|
|
||||||
for x in 0..size.x {
|
|
||||||
if let Some(end) = (0..size.y)
|
|
||||||
.rev()
|
|
||||||
.position(|y| {
|
|
||||||
cubes.contains(&Vec3::new(x, y, z))
|
|
||||||
}) {
|
|
||||||
for y in 0..size.y as usize - end {
|
|
||||||
check[x as usize][y][z as usize][3] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// X+
|
|
||||||
for y in 0..size.y {
|
|
||||||
for z in 0..size.z {
|
|
||||||
if let Some(end) = (0..size.x)
|
|
||||||
.position(|x| {
|
|
||||||
cubes.contains(&Vec3::new(x, y, z))
|
|
||||||
}) {
|
|
||||||
for x in end..size.x as usize {
|
|
||||||
check[x][y as usize][z as usize][4] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// X-
|
|
||||||
for y in 0..size.y {
|
|
||||||
for z in 0..size.z {
|
|
||||||
if let Some(end) = (0..size.x)
|
|
||||||
.rev()
|
|
||||||
.position(|x| {
|
|
||||||
cubes.contains(&Vec3::new(x, y, z))
|
|
||||||
}) {
|
|
||||||
for x in 0..size.x as usize - end {
|
|
||||||
check[x][y as usize][z as usize][5] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut cubes = HashSet::new();
|
|
||||||
|
|
||||||
for x in 0..size.x {
|
for x in 0..size.x {
|
||||||
for y in 0..size.y {
|
for y in 0..size.y {
|
||||||
for z in 0..size.z {
|
for z in 0..size.z {
|
||||||
if check[x as usize][y as usize][z as usize].iter().all(|v| *v) {
|
if !check.get(&Vec3::new(x, y, z)).1 {
|
||||||
cubes.insert(Vec3::new(x, y, z));
|
cubes.insert(Vec3::new(x, y, z));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
calculate_surface(cubes)
|
calculate_surface(cubes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user