HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Quickly Iterate through 2D array manipulating contained structs

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
quicklymanipulatingarraystructsiteratecontainedthrough

Problem

I am hoping to streamline this bit of code better. This snippet does not cause my any slow downs in relation to other parts of the algorithm(?). I would just like guidance on making it better.

Some variables not given by code:

regionDimensions = whatever you want. (256)
hexagonArray[,] = new Hexagon[regionDimensions, regionDimensions];


The Struct:

public struct Hexagon
{
    private float height;
    private bool[] hasSides;

    public Hexagon(float height)
    {
        this.height = height;
        hasSides = new bool[] { true, true, true, true, true, true };
    }

    public float Height
    {
        get { return height; }
    }

    public bool[] HasSides
    {
        get { return hasSides; }
        set { hasSides = value; }
    }

    public bool this[int i]
    {
        get { return hasSides[i]; }
        set { hasSides[i] = value; }
    }
}


The Iterator:

```
// Evaluate heights of hexagons and cull sides
for (var x = 0; x ();

// If it's not in bounds it doesn't need its side no matter what.
if (y % 2 == 0)
{
if (CheckBounds(x, y + 1)) // 0
neighborHexes.Add(hexagonArray[x, y + 1], 0);
else
hexagonArray[x, y].HasSides[0] = false;

if (CheckBounds(x + 1, y)) // 1
neighborHexes.Add(hexagonArray[x + 1, y], 1);
else
hexagonArray[x, y].HasSides[1] = false;

if (CheckBounds(x, y - 1)) // 2
neighborHexes.Add(hexagonArray[x, y - 1], 2);
else
hexagonArray[x, y].HasSides[2] = false;

if (CheckBounds(x - 1, y - 1)) // 3
neighborHexes.Add(hexagonArray[x - 1, y - 1], 3);
else
hexagonArray[x, y].HasSides[3] = false;

Solution

You will see a big improvement in performance if you swap the key/value types of your neighborHexes dictionary around..

var neighbourHexes = new Dictionary();

neighborHexes.Add(0, hexagonArray[x, y + 1]); // etc...

private void EvaluateNeighbors(Dictionary neighbors, ref Hexagon currentHexagon)
{
    foreach (var neighbor in neighbors)
    {
        if (currentHexagon.Height < neighbor.Value.Height)
            currentHexagon[neighbor.Key] = false;
        else if (NearlyEqual(currentHexagon.Height, neighbor.Value.Height))
            currentHexagon[neighbor.Key] = false;
    }
}


I also moved the dictionary construction var neighborHexes = new Dictionary(); outside of the loop, and replaced it with neighbourHexes.Clear() inside the loop (we don't need 65536 individual dictionaries, we can just create one and re-use it).

In my tests that small change resulted in about a 72% improvement.

Here are my test results (regionDimensions = 256, 100 iterations)

Unoptimized Average 
0.091637207 

Optimized Average 
0.025620268


And here is the code in Linqpad

Code Snippets

var neighbourHexes = new Dictionary<int, Hexagon>();

neighborHexes.Add(0, hexagonArray[x, y + 1]); // etc...

private void EvaluateNeighbors(Dictionary<int, Hexagon> neighbors, ref Hexagon currentHexagon)
{
    foreach (var neighbor in neighbors)
    {
        if (currentHexagon.Height < neighbor.Value.Height)
            currentHexagon[neighbor.Key] = false;
        else if (NearlyEqual(currentHexagon.Height, neighbor.Value.Height))
            currentHexagon[neighbor.Key] = false;
    }
}
Unoptimized Average 
0.091637207 

Optimized Average 
0.025620268

Context

StackExchange Code Review Q#24839, answer score: 2

Revisions (0)

No revisions yet.