From 74592d2b32598f9718337fcd833f1baff82d2cef Mon Sep 17 00:00:00 2001 From: "Dr. Matthias Ratajczak" Date: Fri, 23 Sep 2022 17:56:02 +0200 Subject: [PATCH] finish 81 --- src/euler81/p081_test.txt | 5 ++ src/euler81/src/main.rs | 129 +++++++++++++++++++++++++++++++------- 2 files changed, 112 insertions(+), 22 deletions(-) create mode 100644 src/euler81/p081_test.txt diff --git a/src/euler81/p081_test.txt b/src/euler81/p081_test.txt new file mode 100644 index 0000000..76167d9 --- /dev/null +++ b/src/euler81/p081_test.txt @@ -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 diff --git a/src/euler81/src/main.rs b/src/euler81/src/main.rs index 9d1eab2..3e0b558 100644 --- a/src/euler81/src/main.rs +++ b/src/euler81/src/main.rs @@ -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, + unvisited: HashSet, } 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 { + 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, + previous: Option, +} + +impl Node { + fn smaller_distance(&self, other: &Self) -> Option { + 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 { + // self.value.partial_cmp(&other.value) + // } } impl From for Node { fn from(value: u32) -> Self { Node { - is_infinity: true, value, + distance: None, + previous: None, } } } - -impl From for Rc> { - fn from(node: Node) -> Self { - Rc::new(RefCell::new(node)) - } -}