Files
game-of-life/GameOfLife/LifeHashSet.cs
T
2026-05-07 03:23:56 +00:00

83 lines
2.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GameOfLife.Entities;
namespace GameOfLife
{
public class LifeHashSet : LifeBase
{
protected HashSet<Cell> World;
public LifeHashSet()
{
World = new HashSet<Cell>();
}
public LifeHashSet(IEnumerable<Cell> cells) : this()
{
foreach (var cell in cells)
World.Add(cell);
}
public override bool IsCellAlive(Cell cell) => World.Contains(cell);
protected override bool ToggleCell_Internal(Cell cell)
{
if (IsCellAlive(cell))
{
World.Remove(cell);
return false;
}
World.Add(cell);
return true;
}
protected override int IncrementGeneration_Internal()
{
World = GetNextGeneration_Parallel(NeighborhoodField);
return World.Count;
}
private HashSet<Cell> GetNextGeneration_Serial(IEnumerable<Tuple<Cell, short>> field)
{
return
new HashSet<Cell>(
field.Where(
cellNeighborCount =>
LifeRule(World.Contains(cellNeighborCount.Item1), cellNeighborCount.Item2))
.Select(c => c.Item1));
}
private HashSet<Cell> GetNextGeneration_Parallel(IEnumerable<Tuple<Cell, short>> field)
{
var nextGeneration = new HashSet<Cell>();
Parallel.ForEach(
field,
() => new HashSet<Cell>(),
(cellNeighborCount, loop, localNextGen) =>
{
var cell = cellNeighborCount.Item1;
var neighborCount = cellNeighborCount.Item2;
if (LifeRule(World.Contains(cell), neighborCount))
localNextGen.Add(cell);
return localNextGen;
},
globalNextGen =>
{
lock (nextGeneration)
foreach (var cell in globalNextGen)
nextGeneration.Add(cell);
}
);
return nextGeneration;
}
public override IEnumerable<Cell> LivingCells => World;
}
}