Improve tick performance in game_of_life

This commit is contained in:
Héctor Ramón Jiménez 2020-05-01 01:24:31 +02:00
parent a6db1e1fb3
commit 377ead93d6

View File

@ -353,17 +353,19 @@ mod grid {
} }
fn tick(&mut self) { fn tick(&mut self) {
use itertools::Itertools; let mut adjacent_life = HashMap::new();
let populated_neighbors: HashMap<Cell, usize> = self for cell in &self.cells {
.cells let _ = adjacent_life.entry(*cell).or_insert(0);
.iter()
.flat_map(Cell::cluster)
.unique()
.map(|cell| (cell, self.count_adjacent(cell)))
.collect();
for (cell, amount) in populated_neighbors.iter() { for neighbor in Cell::neighbors(*cell) {
let amount = adjacent_life.entry(neighbor).or_insert(0);
*amount += 1;
}
}
for (cell, amount) in adjacent_life.iter() {
match amount { match amount {
2 => {} 2 => {}
3 => { 3 => {
@ -375,17 +377,6 @@ mod grid {
} }
} }
} }
fn count_adjacent(&self, cell: Cell) -> usize {
let cluster = Cell::cluster(&cell);
let is_neighbor = |candidate| candidate != cell;
let is_populated = |cell| self.cells.contains(&cell);
cluster
.filter(|&cell| is_neighbor(cell) && is_populated(cell))
.count()
}
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -407,7 +398,7 @@ mod grid {
} }
} }
fn cluster(cell: &Cell) -> impl Iterator<Item = Cell> { fn cluster(cell: Cell) -> impl Iterator<Item = Cell> {
use itertools::Itertools; use itertools::Itertools;
let rows = cell.i.saturating_sub(1)..=cell.i.saturating_add(1); let rows = cell.i.saturating_sub(1)..=cell.i.saturating_add(1);
@ -416,6 +407,10 @@ mod grid {
rows.cartesian_product(columns).map(|(i, j)| Cell { i, j }) rows.cartesian_product(columns).map(|(i, j)| Cell { i, j })
} }
fn neighbors(cell: Cell) -> impl Iterator<Item = Cell> {
Cell::cluster(cell).filter(move |candidate| *candidate != cell)
}
fn all_visible_in(region: Rectangle) -> impl Iterator<Item = Cell> { fn all_visible_in(region: Rectangle) -> impl Iterator<Item = Cell> {
use itertools::Itertools; use itertools::Itertools;