104 lines
3.3 KiB
Rust
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 }
|
|
}
|
|
}
|