This commit is contained in:
Andrew Glaze 2023-12-19 16:10:35 -05:00
parent 6e0f7b3c2f
commit 05a71ce349
2 changed files with 116 additions and 0 deletions

115
src/day17.rs Normal file
View 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);
}
}

View File

@ -1,3 +1,4 @@
mod day17;
mod day16;
mod day15;
mod day14;