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)]
|
#[allow(dead_code)]
|
||||||
impl<T> Vec2<T> {
|
impl<T> Vec2<T> {
|
||||||
pub fn new(columns: usize) -> 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 {
|
pub fn get(&self, row: usize, col: usize) -> &T {
|
||||||
&self.data[self.offset(row, col)]
|
&self.data[self.offset(row, col)]
|
||||||
}
|
}
|
||||||
@ -258,7 +282,7 @@ impl<T: Display> Display for Vec2<T> {
|
|||||||
for row in self.rows() {
|
for row in self.rows() {
|
||||||
write!(f, "[")?;
|
write!(f, "[")?;
|
||||||
for (i, v) in row.iter().enumerate() {
|
for (i, v) in row.iter().enumerate() {
|
||||||
if i > 0 {write!(f, ", ")?;}
|
if i > 0 {write!(f, "")?;}
|
||||||
write!(f, "{}", v)?;
|
write!(f, "{}", v)?;
|
||||||
}
|
}
|
||||||
write!(f, "]\n")?;
|
write!(f, "]\n")?;
|
||||||
|
@ -4,14 +4,14 @@ use color_eyre::eyre;
|
|||||||
|
|
||||||
mod lib;
|
mod lib;
|
||||||
use lib::load;
|
use lib::load;
|
||||||
mod day14;
|
mod day15;
|
||||||
|
|
||||||
|
|
||||||
fn main() -> eyre::Result<()> {
|
fn main() -> eyre::Result<()> {
|
||||||
let data = load("data/14.txt")?;
|
let data = load("data/15.txt")?;
|
||||||
|
|
||||||
let start = Instant::now();
|
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 (dur, unit) = format_ns(start.elapsed().as_nanos());
|
||||||
|
|
||||||
let precision = 2.0 - dur.log10().floor();
|
let precision = 2.0 - dur.log10().floor();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user