Skip to content

Commit

Permalink
Pre-search to depth 2 iteratively to use rayon
Browse files Browse the repository at this point in the history
  • Loading branch information
kcaffrey committed Dec 23, 2023
1 parent 596d63e commit cffbc83
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 15 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
| [Day 20](./src/bin/20.rs) | `323.9µs` | `1.2ms` |
| [Day 21](./src/bin/21.rs) | `64.1µs` | `494.7µs` |
| [Day 22](./src/bin/22.rs) | `78.3µs` | `194.8µs` |
| [Day 23](./src/bin/23.rs) | `330.7µs` | `67.4ms` |
| [Day 23](./src/bin/23.rs) | `331.0µs` | `19.6ms` |

**Total: 84.34ms**
**Total: 36.54ms**
<!--- benchmarking table --->

---
Expand Down
55 changes: 42 additions & 13 deletions src/bin/23.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{
fmt::{Display, Write},
};

use rayon::iter::{IntoParallelIterator, ParallelIterator};
use tinyvec::ArrayVec;

advent_of_code::solution!(23);
Expand All @@ -28,25 +29,53 @@ pub fn part_one(input: &str) -> Option<u16> {
}

pub fn part_two(input: &str) -> Option<u16> {
let (mut graph, start, mut goal) = build_graph(input, false);
let (mut graph, mut start, mut goal) = build_graph(input, false);

debug_assert!(graph.vertices <= 64, "some optimizations only work with 64 vertices or less. plus it will be too slow with high vertex counts");

// The goal usually only has one connection, so trim it to save on the search space.
// The start and goal usually only has one connection, so trim it to save on the search space.
let mut trimmed_length = 0;
while graph.adjacency[goal].len() == 1 {
let (new_goal, distance) = graph.adjacency[goal][0];
trimmed_length += distance;
graph.adjacency[goal].clear();
let idx = graph.adjacency[new_goal]
.iter()
.position(|&(adj, _)| adj == goal)
.unwrap();
graph.adjacency[new_goal].remove(idx);
goal = new_goal;
let mut trim = |mut cur: usize| {
while graph.adjacency[cur].len() == 1 {
let (new_cur, distance) = graph.adjacency[cur][0];
trimmed_length += distance;
graph.adjacency[cur].clear();
let idx = graph.adjacency[new_cur]
.iter()
.position(|&(adj, _)| adj == cur)
.unwrap();
graph.adjacency[new_cur].remove(idx);
cur = new_cur;
}
cur
};
goal = trim(goal);
start = trim(start);

// Find all paths to depth N iteratively to use rayon on the resulting paths.
const PRESEARCH_DEPTH: u8 = 2;
let mut paths = Vec::new();
let mut stack = Vec::new();
stack.push((start, 1u64 << start, 0, 0));
while let Some((cur, visited, distance, depth)) = stack.pop() {
if depth >= PRESEARCH_DEPTH || cur == goal {
paths.push((cur, visited, distance));
continue;
}
for &(neighbor, cost) in &graph.adjacency[cur] {
let neighbor_bit = 1u64 << neighbor;
if visited & neighbor_bit == 0 {
stack.push((neighbor, visited | neighbor_bit, distance + cost, depth + 1));
}
}
}

Some(trimmed_length + part_two_recursive_brute_force(&graph, start, goal, 1 << start, 0))
paths
.into_par_iter()
.map(|(start, visited, distance)| {
trimmed_length + part_two_recursive_brute_force(&graph, start, goal, visited, distance)
})
.max()
}

fn part_two_recursive_brute_force(
Expand Down

0 comments on commit cffbc83

Please sign in to comment.