day17
This commit is contained in:
parent
6e0f7b3c2f
commit
05a71ce349
115
src/day17.rs
Normal file
115
src/day17.rs
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
use std::{collections::BinaryHeap, cmp::Reverse};
|
||||||
|
|
||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Grid {
|
||||||
|
data: Box<[u8]>,
|
||||||
|
offset: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Grid {
|
||||||
|
fn from_str(s: &str) -> Self {
|
||||||
|
let mut lines = s.lines().peekable();
|
||||||
|
let line_len = lines.peek().map_or(0, |line| line.len());
|
||||||
|
Self {
|
||||||
|
data: lines.flat_map(str::as_bytes).map(|&char| char - b'0').collect::<Box<_>>(),
|
||||||
|
offset: line_len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_pos(&self, p: usize, dir: u8) -> Option<usize> {
|
||||||
|
Some(match dir {
|
||||||
|
0 if p > self.offset => p - self.offset,
|
||||||
|
1 if (p + 1) % self.offset != 0 => p + 1,
|
||||||
|
2 if p < self.data.len() - self.offset => p + self.offset,
|
||||||
|
3 if p % self.offset != 0 => p - 1,
|
||||||
|
_ => { return None }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, dmin: usize, dmax: usize) -> Option<usize> {
|
||||||
|
let lp = self.data.len() - 1;
|
||||||
|
let mut visit = vec![0u8; self.data.len()];
|
||||||
|
let mut ccache = vec![usize::MAX; 2 * self.data.len()];
|
||||||
|
let mut q = BinaryHeap::new();
|
||||||
|
q.push((Reverse(0), 0, 0));
|
||||||
|
q.push((Reverse(0), 0, 1));
|
||||||
|
|
||||||
|
while let Some((Reverse(cost), p, dir)) = q.pop() {
|
||||||
|
if p == lp {
|
||||||
|
return Some(cost)
|
||||||
|
}
|
||||||
|
if visit[p] & (1u8 << dir) != 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
visit[p] |= 1u8 << dir;
|
||||||
|
let odir = dir ^ 1;
|
||||||
|
for nd in [odir, odir ^ 2] {
|
||||||
|
let mut costsum = 0;
|
||||||
|
let mut np = p;
|
||||||
|
for dist in 1..=dmax {
|
||||||
|
if let Some(op) = self.next_pos(np, nd) {
|
||||||
|
costsum += self.data[op] as usize;
|
||||||
|
if dist >= dmin {
|
||||||
|
let ncost = cost + costsum;
|
||||||
|
let cache_idx = (op << 1) | odir as usize;
|
||||||
|
if ccache[cache_idx] > ncost {
|
||||||
|
ccache[cache_idx] = ncost;
|
||||||
|
q.push((Reverse(ncost), op, odir));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
np = op;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[aoc_generator(day17)]
|
||||||
|
fn parse(input: &str) -> Grid {
|
||||||
|
Grid::from_str(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day17, part1)]
|
||||||
|
fn part1(input: &Grid) -> usize {
|
||||||
|
input.run(1, 3).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day17, part2)]
|
||||||
|
fn part2(input: &Grid) -> usize {
|
||||||
|
input.run(4, 10).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const EX: &str = r"2413432311323
|
||||||
|
3215453535623
|
||||||
|
3255245654254
|
||||||
|
3446585845452
|
||||||
|
4546657867536
|
||||||
|
1438598798454
|
||||||
|
4457876987766
|
||||||
|
3637877979653
|
||||||
|
4654967986887
|
||||||
|
4564679986453
|
||||||
|
1224686865563
|
||||||
|
2546548887735
|
||||||
|
4322674655533";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part1_example() {
|
||||||
|
assert_eq!(part1(&parse(EX)), 102);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_example() {
|
||||||
|
assert_eq!(part2(&parse(EX)), 94);
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
mod day17;
|
||||||
mod day16;
|
mod day16;
|
||||||
mod day15;
|
mod day15;
|
||||||
mod day14;
|
mod day14;
|
||||||
|
Loading…
Reference in New Issue
Block a user