Using Rayon gets 6b runtime down to only five seconds
This commit is contained in:
parent
4c453b192a
commit
8f47885d0a
|
@ -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() {
|
||||
*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);
|
||||
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.write().unwrap().insert(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
obstructions
|
||||
let x = obstructions.read().unwrap().clone();
|
||||
x
|
||||
}
|
||||
|
||||
fn find_guard(grid: &Grid) -> Guard {
|
||||
|
@ -62,7 +74,7 @@ fn find_guard(grid: &Grid) -> Guard {
|
|||
};
|
||||
|
||||
if let Some(orientation) = orientation {
|
||||
return Guard{
|
||||
return Guard {
|
||||
location: (x, y),
|
||||
orientation,
|
||||
};
|
||||
|
@ -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);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue