message: Improve tick performance in `game_of_life`
diff: @@ -353,17 +353,19 @@ mod grid {
  }
  fn tick(&mut self) {
  - use itertools::Itertools;
  + let mut adjacent_life = HashMap::new();
  +
  + for cell in &self.cells {
  + let _ = adjacent_life.entry(*cell).or_insert(0);
  +
  + for neighbor in Cell::neighbors(*cell) {
  + let amount = adjacent_life.entry(neighbor).or_insert(0);
  - let populated_neighbors: HashMap<Cell, usize> = self
  - .cells
  - .iter()
  - .flat_map(Cell::cluster)
  - .unique()
  - .map(|cell| (cell, self.count_adjacent(cell)))
  - .collect();
  + *amount += 1;
  + }
  + }
  - for (cell, amount) in populated_neighbors.iter() {
  + for (cell, amount) in adjacent_life.iter() {
  match amount {
  2 => {}
  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)]
  @@ -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;
  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 })
  }
  + 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> {
  use itertools::Itertools;
  