Using Rayon gets 6b runtime down to only five seconds

This commit is contained in:
Savanni D'Gerinel 2024-12-09 13:41:03 -05:00
parent 4c453b192a
commit 8f47885d0a
1 changed files with 35 additions and 15 deletions

View File

@ -1,6 +1,7 @@
use std::collections::HashSet;
use std::{collections::HashSet, sync::{Arc, RwLock}};
use crate::grid::{Direction, Grid};
use rayon::prelude::*;
const INPUT: &'static str = include_str!("../data/day6.txt");
@ -23,31 +24,42 @@ struct Guard {
fn distinct_locations(grid: &Grid) -> usize {
let guard = find_guard(grid);
let (_, path) = simulate_path(grid, guard.clone());
path.into_iter().map(|guard| guard.location).collect::<HashSet<(usize, usize)>>().len()
path.into_iter()
.map(|guard| guard.location)
.collect::<HashSet<(usize, usize)>>()
.len()
}
fn looping_obstructions(mut grid: Grid) -> HashSet<(usize, usize)> {
fn looping_obstructions(grid: Grid) -> HashSet<(usize, usize)> {
let guard = find_guard(&grid);
let (_, path) = simulate_path(&grid, guard.clone());
let mut obstructions = HashSet::new();
let obstructions = Arc::new(RwLock::new(HashSet::new()));
let start = path.first().unwrap().clone();
let mut path = path.into_iter().map(|g| g.location).collect::<HashSet<(usize, usize)>>();
let mut path = path
.into_iter()
.map(|g| g.location)
.collect::<HashSet<(usize, usize)>>();
path.remove(&start.location);
// Now that we know the guard's original path, we can traverse all of the locations she would
// step through and consider that location as a potential new obstacle. Place and obstacle
// there and re-run the simulation.
for location in path.into_iter() {
path.into_par_iter().for_each({
let obstructions = obstructions.clone();
move |location| {
let mut grid = grid.clone();
*grid.elem_mut(location.0, location.1) = '#';
let (looping, _) = simulate_path(&grid, guard.clone());
*grid.elem_mut(location.0, location.1) = '.';
if looping {
obstructions.insert(location);
obstructions.write().unwrap().insert(location);
}
}
});
obstructions
let x = obstructions.read().unwrap().clone();
x
}
fn find_guard(grid: &Grid) -> Guard {
@ -129,7 +141,13 @@ mod test {
#[test]
fn it_finds_the_guard() {
let grid = Grid::from(TEST_INPUT);
assert_eq!(find_guard(&grid), Guard{ location: (4, 6), orientation: Direction::North });
assert_eq!(
find_guard(&grid),
Guard {
location: (4, 6),
orientation: Direction::North
}
);
}
#[test]
@ -156,7 +174,9 @@ mod test {
assert!(obs.contains(&(3, 8)));
assert!(obs.contains(&(7, 9)));
/* Even with par_iter, this is still too slow to run on every test
let grid = Grid::from(INPUT);
assert_eq!(looping_obstructions(grid).len(), 1703);
*/
}
}