From 719db128cf180f543d53821e0d290358f6f07a6d Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 25 Dec 2018 14:04:03 +0100 Subject: [PATCH] day22 with hashmaps slower, but more flexible --- src/tasks/day22.rs | 66 +++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/src/tasks/day22.rs b/src/tasks/day22.rs index ad359c0..73e8c5f 100644 --- a/src/tasks/day22.rs +++ b/src/tasks/day22.rs @@ -2,11 +2,18 @@ use crate::tasks::day22::Equipment::*; use core::cmp::Ordering; use std::collections::BinaryHeap; use std::collections::HashMap; +use std::time::Instant; pub fn both() { - let cave = Cave::create(3879, Node(8, 713, Torch)); + let start = Instant::now(); + let mut cave = Cave::create(3879, Node(8, 713, Torch)); + println!("{:?}", Instant::now() - start); + let start = Instant::now(); println!("Sum of erosion indexes: {}", cave.erosion_sum()); + println!("{:?}", Instant::now() - start); + let start = Instant::now(); println!("Shortest path length: {}", cave.shortest_path_length()); + println!("{:?}", Instant::now() - start); } #[derive(PartialEq, Clone, Copy, Debug, Eq, Hash)] @@ -20,8 +27,9 @@ enum Equipment { struct Node(usize, usize, Equipment); struct Cave { - map: Vec>, + map: HashMap<(usize, usize), usize>, target: Node, + depth: usize, } impl Cave { @@ -29,31 +37,12 @@ impl Cave { if target.2 != Torch { panic!("A valid target point needs the torch equipped"); } - let width = 5000; - let height = 5000; - let mut map: Vec> = Vec::with_capacity(width); - let mut inner_vec = Vec::with_capacity(height); - inner_vec.resize(height, 0); - map.resize(width, inner_vec); + let map = HashMap::with_capacity(target.0 * target.1); - for x in 0..width { - for y in 0..height { - let geo_index = match (x, y) { - (0, 0) => 0, - _ if target.0 == x && target.1 == y => 0, - (x, 0) => x * 16807, - (0, y) => y * 48271, - (x, y) => map[x - 1][y] * map[x][y - 1], - }; - let erosion_index = (geo_index + depth) % 20183; - map[x][y] = erosion_index; - } - } - - Cave { map, target } + Cave { map, target, depth } } - fn erosion_sum(&self) -> usize { + fn erosion_sum(&mut self) -> usize { (0..=self.target.0) .map(|x| { (0..=self.target.1) @@ -63,11 +52,28 @@ impl Cave { .sum() } - fn field_type(&self, x: usize, y: usize) -> usize { - self.map[x][y] % 3 + fn field_type(&mut self, x: usize, y: usize) -> usize { + self.erosion_index(x, y) % 3 } - fn shortest_path_length(&self) -> usize { + fn erosion_index(&mut self, x: usize, y: usize) -> usize { + if let Some(value) = self.map.get(&(x, y)) { + return *value; + } else { + let geo_index = match (x, y) { + (0, 0) => 0, + _ if self.target.0 == x && self.target.1 == y => 0, + (x, 0) => x * 16807, + (0, y) => y * 48271, + (x, y) => self.erosion_index(x - 1, y) * self.erosion_index(x, y - 1), + }; + let erosion_index = (geo_index + self.depth) % 20183; + self.map.insert((x, y), erosion_index); + return erosion_index; + } + } + + fn shortest_path_length(&mut self) -> usize { let start = Node(0, 0, Torch); let mut open: BinaryHeap = BinaryHeap::new(); let mut distances: HashMap = HashMap::new(); @@ -111,7 +117,7 @@ impl Cave { unreachable!("There is always a path"); } - fn neighbors(&self, position: Node) -> Vec { + fn neighbors(&mut self, position: Node) -> Vec { let mut result = Vec::new(); // add all variants of the current position result.push(Edge { @@ -146,7 +152,7 @@ impl Cave { result } - fn equipment_allowed_for_region(&self, x: usize, y: usize, equipment: Equipment) -> bool { + fn equipment_allowed_for_region(&mut self, x: usize, y: usize, equipment: Equipment) -> bool { let field_type = self.field_type(x, y); match field_type { // rocky @@ -159,7 +165,7 @@ impl Cave { } } - fn other_node_for_region(&self, position: Node) -> Node { + fn other_node_for_region(&mut self, position: Node) -> Node { let field_type = self.field_type(position.0, position.1); Node( position.0,