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 day15;
|
||||
mod day14;
|
||||
|
Loading…
Reference in New Issue
Block a user