day22 with hashmaps
slower, but more flexible
This commit is contained in:
@@ -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<Vec<usize>>,
|
||||
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<usize>> = 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<State> = BinaryHeap::new();
|
||||
let mut distances: HashMap<Node, usize> = HashMap::new();
|
||||
@@ -111,7 +117,7 @@ impl Cave {
|
||||
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();
|
||||
// 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,
|
||||
|
||||
Reference in New Issue
Block a user