day 15
This commit is contained in:
parent
33e9af89be
commit
5633d37773
105
2021/src/day15.rs
Normal file
105
2021/src/day15.rs
Normal file
@ -0,0 +1,105 @@
|
||||
use color_eyre::eyre;
|
||||
|
||||
use std::collections::{HashMap, BinaryHeap};
|
||||
use std::cmp::{Ord, PartialOrd, Ordering};
|
||||
|
||||
use crate::lib::Vec2;
|
||||
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
struct Node {
|
||||
row: usize,
|
||||
col: usize,
|
||||
cost: usize,
|
||||
}
|
||||
|
||||
impl Ord for Node {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
other.cost.cmp(&self.cost)
|
||||
.then_with(|| self.row.cmp(&other.row))
|
||||
.then_with(|| self.col.cmp(&other.col))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Node {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn search(graph: &Vec2<usize>) -> usize {
|
||||
// lifted shamelessly from https://doc.rust-lang.org/std/collections/binary_heap/index.html
|
||||
let mut q = BinaryHeap::new();
|
||||
let start = Node {row: 0, col: 0, cost: 0};
|
||||
q.push(start);
|
||||
let mut costs = HashMap::new();
|
||||
|
||||
while let Some(node) = q.pop() {
|
||||
if node.row == graph.row_count() - 1 && node.col == graph.col_count() - 1 {
|
||||
return node.cost;
|
||||
}
|
||||
if &node.cost > costs.get(&(node.row, node.col)).unwrap_or(&usize::MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (row, col) in graph.rect_neighbors(node.row, node.col) {
|
||||
let hop_cost = graph.get(row, col);
|
||||
let neighbor = Node {row, col, cost: node.cost + hop_cost};
|
||||
if &neighbor.cost < costs.get(&(row, col)).unwrap_or(&usize::MAX) {
|
||||
q.push(neighbor);
|
||||
costs.insert((row, col), neighbor.cost);
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("Could not find a path");
|
||||
}
|
||||
|
||||
|
||||
fn load(data: &str) -> eyre::Result<Vec2<usize>> {
|
||||
let width = data.lines().next().unwrap().len();
|
||||
let mut grid = Vec2::new(width);
|
||||
for line in data.lines() {
|
||||
let chars = line.chars().map(|c| c.to_digit(10).unwrap() as usize);
|
||||
grid.push(chars);
|
||||
}
|
||||
Ok(grid)
|
||||
}
|
||||
|
||||
|
||||
fn tile(grid: &Vec2<usize>) -> Vec2<usize> {
|
||||
let old_cols = grid.col_count();
|
||||
let new_cols = old_cols * 5;
|
||||
let mut result = Vec2::new(new_cols);
|
||||
for row in grid.rows() {
|
||||
let values = (0..new_cols).map(|i| {
|
||||
let v = row[i % old_cols] + i / old_cols;
|
||||
(v - 1) % 9 + 1
|
||||
});
|
||||
result.push(values);
|
||||
}
|
||||
|
||||
let old_rows = grid.row_count();
|
||||
let new_rows = old_rows * 5;
|
||||
for row_n in old_rows..new_rows {
|
||||
let values = (0..new_cols).map(|c| {
|
||||
let r = row_n % old_rows;
|
||||
let v = result.get(r, c) + row_n / old_rows;
|
||||
(v - 1) % 9 + 1
|
||||
})
|
||||
.collect::<Vec<usize>>();
|
||||
result.push(values.into_iter());
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
pub fn run(data: &str) -> eyre::Result<(usize, usize)> {
|
||||
let grid = load(data)?;
|
||||
let grid2 = tile(&grid);
|
||||
|
||||
let one = search(&grid);
|
||||
let two = search(&grid2);
|
||||
|
||||
Ok((one, two))
|
||||
}
|
@ -147,6 +147,26 @@ impl Iterator for NeighborCoords {
|
||||
}
|
||||
|
||||
|
||||
pub struct RectNeighbors {
|
||||
nc: NeighborCoords,
|
||||
}
|
||||
|
||||
impl Iterator for RectNeighbors {
|
||||
type Item = (usize, usize);
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some((row, col)) = self.nc.next() {
|
||||
if row == self.nc.start_row || col == self.nc.start_col {
|
||||
return Some((row, col));
|
||||
}
|
||||
else {
|
||||
return self.next();
|
||||
}
|
||||
}
|
||||
return None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<T> Vec2<T> {
|
||||
pub fn new(columns: usize) -> Vec2<T> {
|
||||
@ -205,6 +225,10 @@ impl<T> Vec2<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rect_neighbors(&self, row: usize, col: usize) -> RectNeighbors {
|
||||
RectNeighbors {nc: self.neighbor_coords(row, col)}
|
||||
}
|
||||
|
||||
pub fn get(&self, row: usize, col: usize) -> &T {
|
||||
&self.data[self.offset(row, col)]
|
||||
}
|
||||
@ -258,7 +282,7 @@ impl<T: Display> Display for Vec2<T> {
|
||||
for row in self.rows() {
|
||||
write!(f, "[")?;
|
||||
for (i, v) in row.iter().enumerate() {
|
||||
if i > 0 {write!(f, ", ")?;}
|
||||
if i > 0 {write!(f, "")?;}
|
||||
write!(f, "{}", v)?;
|
||||
}
|
||||
write!(f, "]\n")?;
|
||||
|
@ -4,14 +4,14 @@ use color_eyre::eyre;
|
||||
|
||||
mod lib;
|
||||
use lib::load;
|
||||
mod day14;
|
||||
mod day15;
|
||||
|
||||
|
||||
fn main() -> eyre::Result<()> {
|
||||
let data = load("data/14.txt")?;
|
||||
let data = load("data/15.txt")?;
|
||||
|
||||
let start = Instant::now();
|
||||
let (one, two) = day14::run(&data)?;
|
||||
let (one, two) = day15::run(&data)?;
|
||||
let (dur, unit) = format_ns(start.elapsed().as_nanos());
|
||||
|
||||
let precision = 2.0 - dur.log10().floor();
|
||||
|
Loading…
x
Reference in New Issue
Block a user