2022 - Day 18

This commit is contained in:
Dreaded_X 2022-12-18 21:32:02 +01:00
parent 27d845d8ff
commit 8915fb135e
Signed by: Dreaded_X
GPG Key ID: 76BDEC4E165D8AD9

View File

@ -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)
} }
} }