aoc-rs-2021/src/day_15/model.rs
Jan Christian Grünhage 726f629e30 implement day 15
2021-12-16 00:09:04 +01:00

104 lines
3.3 KiB
Rust

use std::collections::HashSet;
use itertools::Itertools;
pub struct Grid {
pub grid: Vec<Vec<usize>>,
}
impl ToString for Grid {
fn to_string(&self) -> String {
self.grid
.iter()
.map(|line| {
line.iter()
.map(|digit| digit.to_string())
.collect::<String>()
})
.join("\n")
}
}
impl Grid {
pub fn dijkstra(&self, start: (usize, usize), end: (usize, usize)) -> usize {
let mut cost = Vec::new();
let mut prev = Vec::new();
let mut dist = Vec::new();
let mut visited = HashSet::new();
let mut seen = HashSet::new();
for y in 0..self.grid.len() {
let mut cost_line = Vec::new();
let mut prev_line = Vec::new();
let mut dist_line = Vec::new();
for x in 0..self.grid[y].len() {
cost_line.push(self.grid[y][x]);
prev_line.push(None);
dist_line.push(None);
}
cost.push(cost_line);
prev.push(prev_line);
dist.push(dist_line);
}
seen.insert((0, 0));
dist[start.1][start.0] = Some(0);
loop {
let min_square = seen
.iter()
//.filter(|s| !visited.contains(*s))
.min_by(|a, b| {
Ord::cmp(
&dist[a.1][a.0].unwrap_or(usize::MAX),
&dist[b.1][b.0].unwrap_or(usize::MAX),
)
})
.cloned();
if let Some((x, y)) = min_square {
seen.remove(&(x, y));
let current = (x, y);
let current_dist = dist[current.1][current.0].unwrap();
for (x_off, y_off) in [(-1, 0), (1, 0), (0, -1), (0, 1)] {
let neighbour = ((x as isize + x_off) as usize, (y as isize + y_off) as usize);
if !(cost.len() > neighbour.1 && cost[neighbour.1].len() > neighbour.0)
|| visited.contains(&neighbour)
{
continue;
}
let neighbour_dist = dist[neighbour.1][neighbour.0].unwrap_or(usize::MAX);
let neighbour_cost = cost[neighbour.1][neighbour.0];
if neighbour_dist > current_dist + neighbour_cost {
prev[neighbour.1][neighbour.0] = Some(current);
dist[neighbour.1][neighbour.0] = Some(current_dist + neighbour_cost);
seen.insert(neighbour);
}
}
visited.insert(current);
} else {
break;
}
}
dist[end.1][end.0].unwrap()
}
pub fn grow(&self) -> Self {
let mut grid = Vec::new();
let y_max = self.grid.len();
let x_max = self.grid[0].len();
for i in 0..5 {
for y in 0..y_max {
let mut line = Vec::new();
for j in 0..5 {
for x in 0..x_max {
line.push(((self.grid[y][x] + i + j - 1) % 9) + 1)
}
}
grid.push(line);
}
}
Self { grid }
}
}