Reduce runtime by 90% by eliminating hashsets

This commit is contained in:
2023-12-25 00:58:40 +01:00
parent 898f8dce25
commit 0af116920b

View File

@@ -1,5 +1,4 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::HashSet;
use crate::common::Grid; use crate::common::Grid;
use crate::common::IndexSet; use crate::common::IndexSet;
@@ -121,7 +120,7 @@ fn longest_path(
pos: usize, pos: usize,
travelled: u32, travelled: u32,
graph: &[Vec<(Slope, usize, u32)>], graph: &[Vec<(Slope, usize, u32)>],
visited: &mut HashSet<usize>, visited: u64,
) -> u32 { ) -> u32 {
if pos == 1 { if pos == 1 {
return travelled; return travelled;
@@ -130,9 +129,12 @@ fn longest_path(
let mut best = 0; let mut best = 0;
for &(slope, other, dist) in &graph[pos] { for &(slope, other, dist) in &graph[pos] {
if !matches!(slope, Slope::Up) && visited.insert(other) { let index = 1u64 << other;
best = Ord::max(best, longest_path(other, travelled + dist, graph, visited)); if !matches!(slope, Slope::Up) && (visited & index) == 0 {
visited.remove(&other); best = Ord::max(
best,
longest_path(other, travelled + dist, graph, visited | index),
);
} }
} }
@@ -142,14 +144,14 @@ fn longest_path(
pub fn part1(input: &[u8]) -> anyhow::Result<String> { pub fn part1(input: &[u8]) -> anyhow::Result<String> {
let graph = simplify_graph(input)?; let graph = simplify_graph(input)?;
Ok(longest_path(0, 0, &graph, &mut HashSet::new()).to_string()) Ok(longest_path(0, 0, &graph, 0).to_string())
} }
fn longer_longest_path( fn longer_longest_path(
pos: usize, pos: usize,
travelled: u32, travelled: u32,
graph: &[Vec<(Slope, usize, u32)>], graph: &[Vec<(Slope, usize, u32)>],
visited: &mut HashSet<usize>, visited: u64,
) -> u32 { ) -> u32 {
if pos == 1 { if pos == 1 {
return travelled; return travelled;
@@ -158,12 +160,12 @@ fn longer_longest_path(
let mut best = 0; let mut best = 0;
for &(_, other, dist) in &graph[pos] { for &(_, other, dist) in &graph[pos] {
if visited.insert(other) { let index = 1u64 << other;
if (visited & index) == 0 {
best = Ord::max( best = Ord::max(
best, best,
longer_longest_path(other, travelled + dist, graph, visited), longer_longest_path(other, travelled + dist, graph, visited | index),
); );
visited.remove(&other);
} }
} }
@@ -173,7 +175,7 @@ fn longer_longest_path(
pub fn part2(input: &[u8]) -> anyhow::Result<String> { pub fn part2(input: &[u8]) -> anyhow::Result<String> {
let graph = simplify_graph(input)?; let graph = simplify_graph(input)?;
Ok(longer_longest_path(0, 0, &graph, &mut HashSet::new()).to_string()) Ok(longer_longest_path(0, 0, &graph, 0).to_string())
} }
#[cfg(test)] #[cfg(test)]