Parallel day20
This commit is contained in:
parent
1baa3342cc
commit
dfa6d05f59
52
day20/Cargo.lock
generated
52
day20/Cargo.lock
generated
@ -2,15 +2,67 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "day20"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.29.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
@ -5,3 +5,4 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
glam = "0.29.2"
|
||||
rayon = "1.10.0"
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use glam::IVec2;
|
||||
use rayon::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
enum Direction {
|
||||
@ -25,52 +24,25 @@ impl Direction {
|
||||
vec![Up, Left, Down, Right]
|
||||
}
|
||||
|
||||
fn orthogonal(&self) -> Vec<Self> {
|
||||
fn turn_right(&self) -> Self {
|
||||
match self {
|
||||
Up | Down => vec![Left, Right],
|
||||
Left | Right => vec![Up, Down],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
enum TileType {
|
||||
Free,
|
||||
Wall,
|
||||
Start,
|
||||
End,
|
||||
}
|
||||
use TileType::*;
|
||||
|
||||
impl Display for TileType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Free => write!(f, "."),
|
||||
Wall => write!(f, "#"),
|
||||
Start => write!(f, "S"),
|
||||
End => write!(f, "E"),
|
||||
Up => Right,
|
||||
Left => Up,
|
||||
Down => Left,
|
||||
Right => Down,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
struct Tile {
|
||||
tiletype: TileType,
|
||||
tiletype: bool,
|
||||
distance: usize,
|
||||
}
|
||||
|
||||
impl Display for Tile {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if self.distance < usize::MAX {
|
||||
write!(f, ",")
|
||||
} else {
|
||||
write!(f, "{}", self.tiletype)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(input: &str) -> (Vec<Vec<Tile>>, IVec2) {
|
||||
fn parse(input: &str) -> (Vec<Vec<Tile>>, IVec2, IVec2) {
|
||||
let mut start_pos = IVec2::new(0, 0);
|
||||
let mut end_pos = IVec2::new(0, 0);
|
||||
(
|
||||
input
|
||||
.lines()
|
||||
@ -80,14 +52,18 @@ fn parse(input: &str) -> (Vec<Vec<Tile>>, IVec2) {
|
||||
.enumerate()
|
||||
.map(|(c_idx, c)| Tile {
|
||||
tiletype: match c {
|
||||
'#' => Wall,
|
||||
'#' => true,
|
||||
'S' => {
|
||||
start_pos.x = l_idx as i32;
|
||||
start_pos.y = c_idx as i32;
|
||||
Start
|
||||
false
|
||||
}
|
||||
'E' => End,
|
||||
_ => Free,
|
||||
'E' => {
|
||||
end_pos.x = l_idx as i32;
|
||||
end_pos.y = c_idx as i32;
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
distance: usize::MAX,
|
||||
})
|
||||
@ -95,65 +71,71 @@ fn parse(input: &str) -> (Vec<Vec<Tile>>, IVec2) {
|
||||
})
|
||||
.collect(),
|
||||
start_pos,
|
||||
end_pos,
|
||||
)
|
||||
}
|
||||
|
||||
fn get_distances(map: &mut [Vec<Tile>], pos: &IVec2, distance: &usize, path: &mut Vec<IVec2>) {
|
||||
fn get_distances(
|
||||
map: &mut [Vec<Tile>],
|
||||
pos: &IVec2,
|
||||
distance: &usize,
|
||||
path: &mut Vec<IVec2>,
|
||||
end_pos: &IVec2,
|
||||
) {
|
||||
let curr_tile = &mut map[pos.x as usize][pos.y as usize];
|
||||
curr_tile.distance = *distance;
|
||||
if curr_tile.tiletype == End {
|
||||
if pos == end_pos {
|
||||
return;
|
||||
}
|
||||
for direction in Direction::all() {
|
||||
let new_tile_pos = pos + direction.to_vec();
|
||||
let new_tile = map[new_tile_pos.x as usize][new_tile_pos.y as usize];
|
||||
if new_tile.tiletype != Wall && new_tile.distance > distance + 1 {
|
||||
if !new_tile.tiletype && new_tile.distance > distance + 1 {
|
||||
path.push(new_tile_pos);
|
||||
get_distances(map, &new_tile_pos, &(distance + 1), path);
|
||||
get_distances(map, &new_tile_pos, &(distance + 1), path, end_pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn part12(map: &[Vec<Tile>], path: &[IVec2], max_distance: i32) -> usize {
|
||||
let mut res = 0;
|
||||
for tile in path {
|
||||
let mut cheated_targets = vec![];
|
||||
for direction in Direction::all() {
|
||||
for i in 2..=max_distance {
|
||||
for j in 0..=(max_distance - i) {
|
||||
for other_direction in direction.orthogonal() {
|
||||
let new_tile_pos =
|
||||
tile + i * direction.to_vec() + j * other_direction.to_vec();
|
||||
let Some(Some(t)) = map
|
||||
.get(new_tile_pos.x as usize)
|
||||
.map(|l| l.get(new_tile_pos.y as usize))
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
if t.tiletype == Wall || cheated_targets.contains(&new_tile_pos) {
|
||||
continue;
|
||||
}
|
||||
if t.distance
|
||||
>= map[tile.x as usize][tile.y as usize].distance
|
||||
path.par_iter()
|
||||
.map(|tile| {
|
||||
Direction::all()
|
||||
.iter()
|
||||
.map(|direction| {
|
||||
(1..=max_distance)
|
||||
.map(|i| {
|
||||
(0..=(max_distance - i))
|
||||
.filter(|j| {
|
||||
let new_tile_pos = tile
|
||||
+ i * direction.to_vec()
|
||||
+ j * direction.turn_right().to_vec();
|
||||
map.get(new_tile_pos.x as usize)
|
||||
.and_then(|l| l.get(new_tile_pos.y as usize))
|
||||
.map_or(false, |t| {
|
||||
!t.tiletype
|
||||
&& t.distance
|
||||
>= map[tile.x as usize][tile.y as usize]
|
||||
.distance
|
||||
+ 100
|
||||
+ i as usize
|
||||
+ j as usize
|
||||
{
|
||||
cheated_targets.push(new_tile_pos);
|
||||
res += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res
|
||||
+ *j as usize
|
||||
})
|
||||
})
|
||||
.count()
|
||||
})
|
||||
.sum::<usize>()
|
||||
})
|
||||
.sum::<usize>()
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (mut map, start_pos) = parse(include_str!("../input.txt"));
|
||||
let (mut map, start_pos, end_pos) = parse(include_str!("../input.txt"));
|
||||
let mut path = vec![start_pos];
|
||||
get_distances(&mut map, &start_pos, &0, &mut path);
|
||||
get_distances(&mut map, &start_pos, &0, &mut path, &end_pos);
|
||||
println!("{}", part12(&map, &path, 2));
|
||||
println!("{}", part12(&map, &path, 20));
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user