83 lines
2.4 KiB
C#
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;
|
|
}
|
|
} |