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 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,
|
||||||
|
|||||||
Reference in New Issue
Block a user