[Rust/2023/17] Add solution
This commit is contained in:
parent
a12b0cca76
commit
7e481f6aea
10 changed files with 121 additions and 10 deletions
File diff suppressed because one or more lines are too long
|
@ -4,15 +4,15 @@ use aoc::{grid::Direction, iter_ext::IterExt};
|
|||
|
||||
type Input = Vec<Vec<u8>>;
|
||||
|
||||
struct CoordIterator<'a> {
|
||||
struct CoordIterator {
|
||||
x: usize,
|
||||
y: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
direction: &'a Direction,
|
||||
direction: Direction,
|
||||
}
|
||||
|
||||
impl Iterator for CoordIterator<'_> {
|
||||
impl Iterator for CoordIterator {
|
||||
type Item = (usize, usize);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
|
60
Rust/2023/17.rs
Normal file
60
Rust/2023/17.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
#![feature(test)]
|
||||
|
||||
use std::{cmp::Reverse, collections::BinaryHeap};
|
||||
|
||||
use aoc::grid::Direction;
|
||||
|
||||
type Input = Vec<Vec<u8>>;
|
||||
|
||||
fn setup(input: &str) -> Input {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| line.bytes().map(|b| b - b'0').collect())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn dijkstra<const MIN: usize, const MAX: usize>(input: &Input) -> u32 {
|
||||
let h = input.len();
|
||||
let w = input[0].len();
|
||||
|
||||
let mut queue = BinaryHeap::from_iter([
|
||||
(Reverse(0), (0, 0), Direction::East),
|
||||
(Reverse(0), (0, 0), Direction::South),
|
||||
]);
|
||||
let mut visited = vec![false; h * w * 4];
|
||||
while let Some((Reverse(c), (x, y), pd)) = queue.pop() {
|
||||
if x == input[0].len() - 1 && y == input.len() - 1 {
|
||||
return c;
|
||||
}
|
||||
let i = (x + y * w) * 4 + pd as usize;
|
||||
if visited[i] {
|
||||
continue;
|
||||
}
|
||||
visited[i] = true;
|
||||
queue.extend(
|
||||
[pd.rotate_left(), pd.rotate_right()]
|
||||
.into_iter()
|
||||
.flat_map(|d| {
|
||||
std::iter::successors(Some((c, x, y)), move |&(c, x, y)| {
|
||||
let (x, y) = d.step(x, y, w, h)?;
|
||||
Some((c + input[y][x] as u32, x, y))
|
||||
})
|
||||
.take(MAX + 1)
|
||||
.skip(MIN)
|
||||
.map(move |(c, x, y)| (Reverse(c), (x, y), d))
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn part1(input: &Input) -> u32 {
|
||||
dijkstra::<1, 3>(input)
|
||||
}
|
||||
|
||||
fn part2(input: &Input) -> u32 {
|
||||
dijkstra::<4, 10>(input)
|
||||
}
|
||||
|
||||
aoc::main!(2023, 17, ex: 1, 2[b]);
|
|
@ -272,3 +272,6 @@ path = "2023/15.rs"
|
|||
[[bin]]
|
||||
name = "2023_16"
|
||||
path = "2023/16.rs"
|
||||
[[bin]]
|
||||
name = "2023_17"
|
||||
path = "2023/17.rs"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum Direction {
|
||||
North,
|
||||
East,
|
||||
|
@ -7,7 +7,7 @@ pub enum Direction {
|
|||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn step(&self, x: usize, y: usize, width: usize, height: usize) -> Option<(usize, usize)> {
|
||||
pub fn step(self, x: usize, y: usize, width: usize, height: usize) -> Option<(usize, usize)> {
|
||||
Some(match self {
|
||||
Direction::North if y > 0 => (x, y - 1),
|
||||
Direction::East if x < width - 1 => (x + 1, y),
|
||||
|
@ -17,7 +17,7 @@ impl Direction {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn step_signed(&self, (x, y): (isize, isize)) -> (isize, isize) {
|
||||
pub fn step_signed(self, (x, y): (isize, isize)) -> (isize, isize) {
|
||||
match self {
|
||||
Direction::North => (x, y - 1),
|
||||
Direction::East => (x + 1, y),
|
||||
|
@ -26,8 +26,35 @@ impl Direction {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn iter() -> std::slice::Iter<'static, Direction> {
|
||||
[Self::North, Self::East, Self::South, Self::West].iter()
|
||||
pub fn invert(self) -> Self {
|
||||
match self {
|
||||
Direction::North => Direction::South,
|
||||
Direction::East => Direction::West,
|
||||
Direction::South => Direction::North,
|
||||
Direction::West => Direction::East,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rotate_left(self) -> Self {
|
||||
match self {
|
||||
Direction::North => Direction::West,
|
||||
Direction::East => Direction::North,
|
||||
Direction::South => Direction::East,
|
||||
Direction::West => Direction::South,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rotate_right(self) -> Self {
|
||||
match self {
|
||||
Direction::North => Direction::East,
|
||||
Direction::East => Direction::South,
|
||||
Direction::South => Direction::West,
|
||||
Direction::West => Direction::North,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter() -> impl Iterator<Item = Self> {
|
||||
[Self::North, Self::East, Self::South, Self::West].into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
13
examples/2023/17/1
Normal file
13
examples/2023/17/1
Normal file
|
@ -0,0 +1,13 @@
|
|||
2413432311323
|
||||
3215453535623
|
||||
3255245654254
|
||||
3446585845452
|
||||
4546657867536
|
||||
1438598798454
|
||||
4457876987766
|
||||
3637877979653
|
||||
4654967986887
|
||||
4564679986453
|
||||
1224686865563
|
||||
2546548887735
|
||||
4322674655533
|
1
examples/2023/17/1.1
Normal file
1
examples/2023/17/1.1
Normal file
|
@ -0,0 +1 @@
|
|||
102
|
1
examples/2023/17/1.2
Normal file
1
examples/2023/17/1.2
Normal file
|
@ -0,0 +1 @@
|
|||
94
|
5
examples/2023/17/2
Normal file
5
examples/2023/17/2
Normal file
|
@ -0,0 +1,5 @@
|
|||
111111111111
|
||||
999999999991
|
||||
999999999991
|
||||
999999999991
|
||||
999999999991
|
1
examples/2023/17/2.2
Normal file
1
examples/2023/17/2.2
Normal file
|
@ -0,0 +1 @@
|
|||
71
|
Loading…
Add table
Add a link
Reference in a new issue