I have a code which does the following:
For each value v in a 2D array, look at neighboring positions - how far to look is specified by distThreshold. If the count of values identical to v in the neighborhood is lower or equal to countThreshold, change v to a value which is most prevalent in the neighborhood.
For example: input:
[5, 2, 1, 0, 5]
[1, 5, 5, 0, 4]
[0, 2, 0, 0, 5]
[1, 3, 2, 4, 0]
[3, 3, 4, 3, 0]
output for distThreshold = 1, countThreshold = 0:
[5, 5, 5, 0, 0]
[2, 5, 5, 0, 0]
[1, 2, 0, 0, 0]
[3, 3, 2, 4, 0]
[3, 3, 4, 0, 0]
Functions that are important:
public static int[][] correctedArray(int distThreshold, int countThreshold, int[][] arr)
{
int[][] newArray = arrCopy(arr);
for (int j = 0; j < arr.Length; j++)
{
for (int i = 0; i < arr[0].Length; i++)
{
int[] dcfac = dupeCountForAutoCorrect(i, j, distThreshold, countThreshold, arr);
int dupeCount = dcfac[0];
int replacementIndex = dcfac[1];
if (dupeCount <= countThreshold)
{
newArray[j][i] = replacementIndex;
}
}
}
return newArray;
}
private static int[] dupeCountForAutoCorrect(int x, int y, int distThreshold, int countThreshold, int[][] arr)
{
int testedIndex = arr[y][x];
int[] result = new int[2];
Dictionary < int, int > colorCounts = new Dictionary < int, int > ();
for (int j = y - distThreshold; j <= y + distThreshold; j++)
{
for (int i = x - distThreshold; i <= x + distThreshold; i++)
{
if (!(i == x && j == y))
{
try
{
int currentIndex = arr[j][i];
if (currentIndex == testedIndex) result[0]++;
if (result[0] > countThreshold) return result;
if (colorCounts.TryGetValue(currentIndex, out int value))
{
value++;
colorCounts[currentIndex] = value;
}
else
{
colorCounts.Add(currentIndex, 1);
}
}
catch (IndexOutOfRangeException)
{
//do nothing and continue
}
}
}
}
//returns the index with highest count. I don't understand this at all, ripped from Stack Overflow
result[1] = colorCounts.Aggregate((xx, yy) => xx.Value > yy.Value ? xx : yy).Key;
return result;
}
Helper functions and testing:
public static void testArr()
{
int maxIndex = 5;
int arrWidth = 5;
int arrHeight = 5;
int distThreshold = 1;
int countThreshold = 0;
int[][] originalArray = new int[arrHeight][];
Random rnd = new Random();
for (int j = 0; j < arrHeight; j++)
{
int[] r = new int[arrWidth];
for (int i = 0; i < arrWidth; i++)
{
int rndn = rnd.Next(maxIndex + 1);;
r[i] = rndn;
}
originalArray[j] = r;
}
DateTime nao = DateTime.Now;
int[][] newArr = correctedArray(distThreshold, countThreshold, originalArray);
Console.WriteLine((DateTime.Now - nao).TotalSeconds.ToString() + "seconds");
string origArrString = arrToString(originalArray);
string newArrString = arrToString(newArr);
Console.Write(origArrString + System.Environment.NewLine + newArrString);
}
public static string arrToString(int[][] arr)
{
string result = "";
for (int j = 0; j < arr.Length; j++)
{
result += "[";
for (int i = 0; i < arr[0].Length; i++)
{
int val = arr[j][i];
result += val + (i == arr[0].Length - 1 ? "]" + System.Environment.NewLine : ", ");
}
}
return result;
}
public static int[][] arrCopy(int[][] arr)
{
int[][] result = new int[arr.Length][];
for (int j = 0; j < arr.Length; j++)
{
result[j] = new int[arr[0].Length];
for (int i = 0; i < arr[0].Length; i++)
{
result[j][i] = arr[j][i];
}
}
return result;
}
100*100 array is processed in a little over 3 seconds on my machine which seems a little slow to me. I am very new to C#, so pardon my naming and other convention violations :X
arrCopycould be replaced witharr.Select(inner => inner.ToArray()).ToArray(). But of course you should measure your baseline and then perform any modification to be able to determine whether it introduced a performance improvement or degradation. \$\endgroup\$