day22 with hashmaps

slower, but more flexible
This commit is contained in:
Johannes
2018-12-25 14:04:03 +01:00
parent 12f32ed232
commit 719db128cf

View File

@@ -2,11 +2,18 @@ use crate::tasks::day22::Equipment::*;
use core::cmp::Ordering; use core::cmp::Ordering;
use std::collections::BinaryHeap; use std::collections::BinaryHeap;
use std::collections::HashMap; use std::collections::HashMap;
use std::time::Instant;
pub fn both() { 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!("Sum of erosion indexes: {}", cave.erosion_sum());
println!("{:?}", Instant::now() - start);
let start = Instant::now();
println!("Shortest path length: {}", cave.shortest_path_length()); println!("Shortest path length: {}", cave.shortest_path_length());
println!("{:?}", Instant::now() - start);
} }
#[derive(PartialEq, Clone, Copy, Debug, Eq, Hash)] #[derive(PartialEq, Clone, Copy, Debug, Eq, Hash)]
@@ -20,8 +27,9 @@ enum Equipment {
struct Node(usize, usize, Equipment); struct Node(usize, usize, Equipment);
struct Cave { struct Cave {
map: Vec<Vec<usize>>, map: HashMap<(usize, usize), usize>,
target: Node, target: Node,
depth: usize,
} }
impl Cave { impl Cave {
@@ -29,31 +37,12 @@ impl Cave {
if target.2 != Torch { if target.2 != Torch {
panic!("A valid target point needs the torch equipped"); panic!("A valid target point needs the torch equipped");
} }
let width = 5000; let map = HashMap::with_capacity(target.0 * target.1);
let height = 5000;
let mut map: Vec<Vec<usize>> = Vec::with_capacity(width);
let mut inner_vec = Vec::with_capacity(height);
inner_vec.resize(height, 0);
map.resize(width, inner_vec);
for x in 0..width { Cave { map, target, depth }
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 } fn erosion_sum(&mut self) -> usize {
}
fn erosion_sum(&self) -> usize {
(0..=self.target.0) (0..=self.target.0)
.map(|x| { .map(|x| {
(0..=self.target.1) (0..=self.target.1)
@@ -63,11 +52,28 @@ impl Cave {
.sum() .sum()
} }
fn field_type(&self, x: usize, y: usize) -> usize { fn field_type(&mut self, x: usize, y: usize) -> usize {
self.map[x][y] % 3 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 start = Node(0, 0, Torch);
let mut open: BinaryHeap<State> = BinaryHeap::new(); let mut open: BinaryHeap<State> = BinaryHeap::new();
let mut distances: HashMap<Node, usize> = HashMap::new(); let mut distances: HashMap<Node, usize> = HashMap::new();
@@ -111,7 +117,7 @@ impl Cave {
unreachable!("There is always a path"); unreachable!("There is always a path");
} }
fn neighbors(&self, position: Node) -> Vec<Edge> { fn neighbors(&mut self, position: Node) -> Vec<Edge> {
let mut result = Vec::new(); let mut result = Vec::new();
// add all variants of the current position // add all variants of the current position
result.push(Edge { result.push(Edge {
@@ -146,7 +152,7 @@ impl Cave {
result 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); let field_type = self.field_type(x, y);
match field_type { match field_type {
// rocky // 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); let field_type = self.field_type(position.0, position.1);
Node( Node(
position.0, position.0,