feat: day 18
This commit is contained in:
parent
3660e45ae5
commit
4c86a3ddae
5 changed files with 2425 additions and 0 deletions
2176
.aoc-cache/18.txt
Normal file
2176
.aoc-cache/18.txt
Normal file
File diff suppressed because it is too large
Load diff
106
Cargo.lock
generated
106
Cargo.lock
generated
|
@ -35,6 +35,7 @@ dependencies = [
|
||||||
"lru-cache",
|
"lru-cache",
|
||||||
"peg",
|
"peg",
|
||||||
"petgraph",
|
"petgraph",
|
||||||
|
"rayon",
|
||||||
"regex",
|
"regex",
|
||||||
"time",
|
"time",
|
||||||
"ureq",
|
"ureq",
|
||||||
|
@ -135,6 +136,55 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "eyre"
|
name = "eyre"
|
||||||
version = "0.6.8"
|
version = "0.6.8"
|
||||||
|
@ -182,6 +232,15 @@ version = "0.12.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -259,6 +318,15 @@ version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.5.4"
|
version = "0.5.4"
|
||||||
|
@ -277,6 +345,16 @@ dependencies = [
|
||||||
"adler",
|
"adler",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.29.0"
|
version = "0.29.0"
|
||||||
|
@ -365,6 +443,28 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.7.0"
|
version = "1.7.0"
|
||||||
|
@ -415,6 +515,12 @@ dependencies = [
|
||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sct"
|
name = "sct"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
|
|
@ -20,3 +20,4 @@ regex = "1.7.0"
|
||||||
petgraph = "0.6.2"
|
petgraph = "0.6.2"
|
||||||
peg = "0.8.1"
|
peg = "0.8.1"
|
||||||
lru-cache = "0.1.2"
|
lru-cache = "0.1.2"
|
||||||
|
rayon = "1.6.1"
|
||||||
|
|
129
src/bin/day_18.rs
Normal file
129
src/bin/day_18.rs
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
use std::{collections::{HashSet, HashMap}, ops::RangeInclusive};
|
||||||
|
|
||||||
|
use aoc_2022::prelude::*;
|
||||||
|
use rayon::prelude::*;
|
||||||
|
|
||||||
|
type Coord = (isize, isize, isize);
|
||||||
|
|
||||||
|
type Input = Vec<Coord>;
|
||||||
|
|
||||||
|
fn parse(s: &str) -> Result<Input> {
|
||||||
|
let mut coords = vec![];
|
||||||
|
for line in s.lines() {
|
||||||
|
let coord = ints(line);
|
||||||
|
let coord = (coord[0], coord[1], coord[2]);
|
||||||
|
coords.push(coord);
|
||||||
|
}
|
||||||
|
Ok(coords)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||||
|
enum Face {
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
Z,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day = 18, parse = parse, test_cases = ["day_18.txt"])]
|
||||||
|
fn day_18(input: Input) -> Result<()> {
|
||||||
|
// Part 1
|
||||||
|
let mut faces = HashSet::<(Face, Coord)>::new();
|
||||||
|
for cube in &input {
|
||||||
|
let cube_faces = [
|
||||||
|
(Face::X, *cube),
|
||||||
|
(Face::X, (cube.0 + 1, cube.1, cube.2)),
|
||||||
|
(Face::Y, *cube),
|
||||||
|
(Face::Y, (cube.0, cube.1 + 1, cube.2)),
|
||||||
|
(Face::Z, *cube),
|
||||||
|
(Face::Z, (cube.0, cube.1, cube.2 + 1)),
|
||||||
|
];
|
||||||
|
for face in cube_faces {
|
||||||
|
if faces.contains(&face) {
|
||||||
|
faces.remove(&face);
|
||||||
|
} else {
|
||||||
|
faces.insert(face);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Part one: {}", faces.len());
|
||||||
|
|
||||||
|
// Part 2
|
||||||
|
let (x_range, y_range, z_range) = {
|
||||||
|
let min_x = input.iter().map(|c| c.0).min().unwrap();
|
||||||
|
let min_y = input.iter().map(|c| c.1).min().unwrap();
|
||||||
|
let min_z = input.iter().map(|c| c.2).min().unwrap();
|
||||||
|
let max_x = input.iter().map(|c| c.0).max().unwrap();
|
||||||
|
let max_y = input.iter().map(|c| c.1).max().unwrap();
|
||||||
|
let max_z = input.iter().map(|c| c.2).max().unwrap();
|
||||||
|
(min_x..=max_x, min_y..=max_y, min_z..=max_z)
|
||||||
|
};
|
||||||
|
|
||||||
|
let corrected_sa = faces.par_iter().filter(|(face, coord)| {
|
||||||
|
let other = match face {
|
||||||
|
Face::X => (coord.0 - 1, coord.1, coord.2),
|
||||||
|
Face::Y => (coord.0, coord.1 - 1, coord.2),
|
||||||
|
Face::Z => (coord.0, coord.1, coord.2 - 1),
|
||||||
|
};
|
||||||
|
let mut cache = HashMap::new();
|
||||||
|
can_reach_outside(&input, (&x_range, &y_range, &z_range), *coord, &HashSet::new(), &mut cache)
|
||||||
|
|| can_reach_outside(&input, (&x_range, &y_range, &z_range), other, &HashSet::new(), &mut cache)
|
||||||
|
}).count();
|
||||||
|
|
||||||
|
println!("Part 2: {corrected_sa}");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_reach_outside(
|
||||||
|
input: &Input,
|
||||||
|
(x_range, y_range, z_range): (
|
||||||
|
&RangeInclusive<isize>,
|
||||||
|
&RangeInclusive<isize>,
|
||||||
|
&RangeInclusive<isize>,
|
||||||
|
),
|
||||||
|
position: Coord,
|
||||||
|
visited: &HashSet<Coord>,
|
||||||
|
cache: &mut HashMap<Coord, bool>,
|
||||||
|
) -> bool {
|
||||||
|
if let Some(result) = cache.get(&position) {
|
||||||
|
*result
|
||||||
|
} else {
|
||||||
|
let result = if x_range.contains(&position.0) && y_range.contains(&position.1) && z_range.contains(&position.2) {
|
||||||
|
if input.contains(&position) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
let mut visited = visited.clone();
|
||||||
|
visited.insert(position);
|
||||||
|
|
||||||
|
const DIRECTIONS: &[(isize, isize, isize)] = &[
|
||||||
|
( 1, 0, 0),
|
||||||
|
(-1, 0, 0),
|
||||||
|
( 0, 1, 0),
|
||||||
|
( 0, -1, 0),
|
||||||
|
( 0, 0, 1),
|
||||||
|
( 0, 0, -1),
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut can_reach = false;
|
||||||
|
|
||||||
|
for direction in DIRECTIONS {
|
||||||
|
let new_position = (position.0 + direction.0, position.1 + direction.1, position.2 + direction.2);
|
||||||
|
if visited.contains(&new_position) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if can_reach_outside(input, (x_range, y_range, z_range), new_position, &visited, cache) {
|
||||||
|
can_reach = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
can_reach
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
cache.insert(position, result);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
13
test_cases/day_18.txt
Normal file
13
test_cases/day_18.txt
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
|
Loading…
Reference in a new issue