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