finish 81
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
131,673,234,103,18
|
||||
201,96,342,965,150
|
||||
630,803,746,422,111
|
||||
537,699,497,121,956
|
||||
805,732,524,37,331
|
||||
+107
-22
@@ -1,12 +1,19 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
use std::iter::Cycle;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
const LENGTH: usize = 5;
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
const LENGTH: usize = 80;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
const FILENAME: &str = "p081_test.txt";
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
const FILENAME: &str = "p081_matrix.txt";
|
||||
|
||||
type Coordinate = (usize, usize);
|
||||
|
||||
struct Matrix {
|
||||
@@ -26,57 +33,135 @@ impl Matrix {
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
data[0][0].is_infinity = false;
|
||||
let mut start = &mut data[0][0];
|
||||
start.distance = Some(start.value);
|
||||
assert_eq!(data.len(), LENGTH);
|
||||
assert!(data.iter().all(|subvec| subvec.len() == LENGTH));
|
||||
Self { data }
|
||||
}
|
||||
|
||||
fn get(&self, c: &Coordinate) -> &Node {
|
||||
&self.data[c.0][c.1]
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let matrix = Matrix::load(Path::new("p081_matrix.txt"));
|
||||
let dijkstra = Dijkstra::new(matrix);
|
||||
let matrix = Matrix::load(Path::new(FILENAME));
|
||||
let mut dijkstra = Dijkstra::new(matrix);
|
||||
dijkstra.solve();
|
||||
dijkstra.show();
|
||||
}
|
||||
|
||||
struct Dijkstra {
|
||||
initial: Coordinate,
|
||||
matrix: Matrix,
|
||||
unvisited: Vec<Coordinate>,
|
||||
unvisited: HashSet<Coordinate>,
|
||||
}
|
||||
|
||||
impl Dijkstra {
|
||||
fn new(matrix: Matrix) -> Self {
|
||||
let initial = (0, 0);
|
||||
let unvisited: Vec<_> = (0..LENGTH)
|
||||
let unvisited: HashSet<_> = (0..LENGTH)
|
||||
.flat_map(|x| (0..LENGTH).zip([x].into_iter().cycle()))
|
||||
.filter(|value| *value != (0, 0))
|
||||
.collect();
|
||||
assert_eq!(unvisited.len(), LENGTH * LENGTH - 1);
|
||||
Self {
|
||||
initial,
|
||||
matrix,
|
||||
unvisited,
|
||||
Self { matrix, unvisited }
|
||||
}
|
||||
|
||||
fn solve(&mut self) {
|
||||
while !self.unvisited.is_empty() {
|
||||
let coord = self.get_unvisited_coord_with_smallest_distance_from_start();
|
||||
let neighbours = self.get_neighbours(&coord);
|
||||
let previous_distance = self.matrix.get(&coord).distance.unwrap();
|
||||
for neighbour in neighbours {
|
||||
self.update_neighbour(neighbour, coord, previous_distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_unvisited_coord_with_smallest_distance_from_start(&mut self) -> Coordinate {
|
||||
let coord = self
|
||||
.unvisited
|
||||
.iter()
|
||||
.filter_map(|c| {
|
||||
let node = self.matrix.get(c);
|
||||
node.distance.map(|value| (c, value))
|
||||
})
|
||||
.reduce(|(c0, v0), (c1, v1)| if v0 < v1 { (c0, v0) } else { (c1, v1) })
|
||||
.map(|(c, _)| *c)
|
||||
.unwrap_or((0, 0));
|
||||
self.unvisited.remove(&coord);
|
||||
coord
|
||||
}
|
||||
|
||||
fn get_neighbours(&self, coordinate: &Coordinate) -> Vec<Coordinate> {
|
||||
let (x0, y0) = coordinate;
|
||||
let mut result = vec![];
|
||||
if *x0 < LENGTH - 1 {
|
||||
result.push((*x0 + 1, *y0));
|
||||
}
|
||||
if *y0 < LENGTH - 1 {
|
||||
result.push((*x0, *y0 + 1));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn update_neighbour(&mut self, next: Coordinate, previous: Coordinate, previous_distance: u32) {
|
||||
let mut next_node = &mut self.matrix.data[next.0][next.1];
|
||||
let new_distance = previous_distance + next_node.value;
|
||||
match next_node.distance {
|
||||
None => {
|
||||
next_node.distance = Some(new_distance);
|
||||
next_node.previous = Some(previous);
|
||||
}
|
||||
Some(old_distance) => {
|
||||
if new_distance < old_distance {
|
||||
next_node.distance = Some(new_distance);
|
||||
next_node.previous = Some(previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn show(&self) {
|
||||
println!(
|
||||
"{}",
|
||||
self.matrix.data[LENGTH - 1][LENGTH - 1].distance.unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
struct Node {
|
||||
is_infinity: bool,
|
||||
value: u32,
|
||||
distance: Option<u32>,
|
||||
previous: Option<Coordinate>,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
fn smaller_distance(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
match self.distance {
|
||||
Some(v1) => match other.distance {
|
||||
Some(v2) => v1.partial_cmp(&v2),
|
||||
None => Some(std::cmp::Ordering::Less),
|
||||
},
|
||||
None => match other.distance {
|
||||
Some(_) => Some(std::cmp::Ordering::Greater),
|
||||
None => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// fn smaller_value(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
// self.value.partial_cmp(&other.value)
|
||||
// }
|
||||
}
|
||||
|
||||
impl From<u32> for Node {
|
||||
fn from(value: u32) -> Self {
|
||||
Node {
|
||||
is_infinity: true,
|
||||
value,
|
||||
distance: None,
|
||||
previous: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Node> for Rc<RefCell<Node>> {
|
||||
fn from(node: Node) -> Self {
|
||||
Rc::new(RefCell::new(node))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user