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::collections::HashSet;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::iter::Cycle;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
const LENGTH: usize = 5;
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
const LENGTH: usize = 80;
|
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);
|
type Coordinate = (usize, usize);
|
||||||
|
|
||||||
struct Matrix {
|
struct Matrix {
|
||||||
@@ -26,57 +33,135 @@ impl Matrix {
|
|||||||
.collect()
|
.collect()
|
||||||
})
|
})
|
||||||
.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_eq!(data.len(), LENGTH);
|
||||||
assert!(data.iter().all(|subvec| subvec.len() == LENGTH));
|
assert!(data.iter().all(|subvec| subvec.len() == LENGTH));
|
||||||
Self { data }
|
Self { data }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get(&self, c: &Coordinate) -> &Node {
|
||||||
|
&self.data[c.0][c.1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let matrix = Matrix::load(Path::new("p081_matrix.txt"));
|
let matrix = Matrix::load(Path::new(FILENAME));
|
||||||
let dijkstra = Dijkstra::new(matrix);
|
let mut dijkstra = Dijkstra::new(matrix);
|
||||||
|
dijkstra.solve();
|
||||||
|
dijkstra.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Dijkstra {
|
struct Dijkstra {
|
||||||
initial: Coordinate,
|
|
||||||
matrix: Matrix,
|
matrix: Matrix,
|
||||||
unvisited: Vec<Coordinate>,
|
unvisited: HashSet<Coordinate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dijkstra {
|
impl Dijkstra {
|
||||||
fn new(matrix: Matrix) -> Self {
|
fn new(matrix: Matrix) -> Self {
|
||||||
let initial = (0, 0);
|
let unvisited: HashSet<_> = (0..LENGTH)
|
||||||
let unvisited: Vec<_> = (0..LENGTH)
|
|
||||||
.flat_map(|x| (0..LENGTH).zip([x].into_iter().cycle()))
|
.flat_map(|x| (0..LENGTH).zip([x].into_iter().cycle()))
|
||||||
.filter(|value| *value != (0, 0))
|
.filter(|value| *value != (0, 0))
|
||||||
.collect();
|
.collect();
|
||||||
assert_eq!(unvisited.len(), LENGTH * LENGTH - 1);
|
assert_eq!(unvisited.len(), LENGTH * LENGTH - 1);
|
||||||
Self {
|
Self { matrix, unvisited }
|
||||||
initial,
|
}
|
||||||
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)]
|
#[derive(PartialEq, Eq, Hash)]
|
||||||
struct Node {
|
struct Node {
|
||||||
is_infinity: bool,
|
|
||||||
value: u32,
|
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 {
|
impl From<u32> for Node {
|
||||||
fn from(value: u32) -> Self {
|
fn from(value: u32) -> Self {
|
||||||
Node {
|
Node {
|
||||||
is_infinity: true,
|
|
||||||
value,
|
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