2022 - Day 18 [Part 1]
This commit is contained in:
parent
ea2949c2c6
commit
27d845d8ff
2170
2022/input/18/input
Normal file
2170
2022/input/18/input
Normal file
File diff suppressed because it is too large
Load Diff
2
2022/input/18/test-1
Normal file
2
2022/input/18/test-1
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
1,1,1
|
||||||
|
2,1,1
|
13
2022/input/18/test-2
Normal file
13
2022/input/18/test-2
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
2,2,2
|
||||||
|
1,2,2
|
||||||
|
3,2,2
|
||||||
|
2,1,2
|
||||||
|
2,3,2
|
||||||
|
2,2,1
|
||||||
|
2,2,3
|
||||||
|
2,2,4
|
||||||
|
2,2,6
|
||||||
|
1,2,5
|
||||||
|
3,2,5
|
||||||
|
2,1,5
|
||||||
|
2,3,5
|
248
2022/src/bin/day18.rs
Normal file
248
2022/src/bin/day18.rs
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
#![feature(test)]
|
||||||
|
use std::{collections::HashSet, ops::Add};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use aoc::Solver;
|
||||||
|
|
||||||
|
// -- Runners --
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
Day::solve()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_test1() -> Result<()> {
|
||||||
|
Day::test(Day::part1, "test-1", 10)
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn part1_test2() -> Result<()> {
|
||||||
|
Day::test(Day::part1, "test-2", 64)
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn part1_solution() -> Result<()> {
|
||||||
|
Day::test(Day::part1, "input", 3550)
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn part2_test1() -> Result<()> {
|
||||||
|
Day::test(Day::part2, "test-1", 10)
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn part2_test2() -> Result<()> {
|
||||||
|
Day::test(Day::part2, "test-2", 58)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Benchmarks
|
||||||
|
extern crate test;
|
||||||
|
#[bench]
|
||||||
|
#[ignore]
|
||||||
|
fn part1_bench(b: &mut test::Bencher) {
|
||||||
|
Day::benchmark(Day::part1, b)
|
||||||
|
}
|
||||||
|
#[bench]
|
||||||
|
#[ignore]
|
||||||
|
fn part2_bench(b: &mut test::Bencher) {
|
||||||
|
Day::benchmark(Day::part2, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||||
|
struct Vec3 {
|
||||||
|
x: isize,
|
||||||
|
y: isize,
|
||||||
|
z: isize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vec3 {
|
||||||
|
fn new(x: isize, y: isize, z: isize) -> Self {
|
||||||
|
Self { x, y, z }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for &Vec3 {
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Vec3::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(input: &str) -> HashSet<Vec3> {
|
||||||
|
// Create a hashmap containing all occupied spaces
|
||||||
|
input
|
||||||
|
.trim()
|
||||||
|
.lines()
|
||||||
|
.map(|line| line.split(',').map(|num| num.parse().unwrap()).collect::<Vec<isize>>())
|
||||||
|
.map(|coords| {
|
||||||
|
if let &[x, y, z] = coords.as_slice() {
|
||||||
|
return Vec3::new(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("Invalid!");
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn offset() -> [Vec3; 6] {
|
||||||
|
// Offset from cube for each side
|
||||||
|
[
|
||||||
|
Vec3::new(-1, 0, 0),
|
||||||
|
Vec3::new(1, 0, 0),
|
||||||
|
Vec3::new(0, -1, 0),
|
||||||
|
Vec3::new(0, 1, 0),
|
||||||
|
Vec3::new(0, 0, -1),
|
||||||
|
Vec3::new(0, 0, 1),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_surface(cubes: HashSet<Vec3>) -> usize {
|
||||||
|
let offset = offset();
|
||||||
|
|
||||||
|
// Calculate the sum of exposed sides
|
||||||
|
cubes
|
||||||
|
.iter()
|
||||||
|
.map(|pos| {
|
||||||
|
// Check for each side of the cube if it is exposed
|
||||||
|
offset.iter()
|
||||||
|
.filter(|offset| {
|
||||||
|
// Only keep the side if it is exposed
|
||||||
|
!cubes.contains(&(pos + offset))
|
||||||
|
})
|
||||||
|
.count()
|
||||||
|
}).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Solution --
|
||||||
|
pub struct Day;
|
||||||
|
impl aoc::Solver for Day {
|
||||||
|
type Output1 = usize;
|
||||||
|
type Output2 = usize;
|
||||||
|
|
||||||
|
fn day() -> u8 {
|
||||||
|
18
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part1(input: &str) -> Self::Output1 {
|
||||||
|
let cubes = parse(input);
|
||||||
|
|
||||||
|
calculate_surface(cubes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part2(input: &str) -> Self::Output2 {
|
||||||
|
let cubes = parse(input);
|
||||||
|
|
||||||
|
let size = cubes
|
||||||
|
.iter()
|
||||||
|
.fold(Vec3::new(0, 0, 0), |mut acc, cube| {
|
||||||
|
acc.x = acc.x.max(cube.x+1);
|
||||||
|
acc.y = acc.y.max(cube.y+1);
|
||||||
|
acc.z = acc.z.max(cube.z+1);
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut check = vec![vec![vec![[false; 6]; size.z as usize]; size.y as usize]; size.x as usize];
|
||||||
|
|
||||||
|
// Z+
|
||||||
|
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 y in 0..size.y {
|
||||||
|
for z in 0..size.z {
|
||||||
|
if check[x as usize][y as usize][z as usize].iter().all(|v| *v) {
|
||||||
|
cubes.insert(Vec3::new(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate_surface(cubes)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user