2 dimensional array with multiple values for each x and y - c#

I am looking to create a 2-dimensional array that remaps a texture. So for each pixel it will store a hsv value so that it can be recreated programmatically. (In C# preferrably)
My question is is there an algorithm/code (Linq/ArrayList etc) that would enlarge the resulting array and therefore image - ie: by a factor of ten for example.
Current code for recreating 1 to 1 (this is the loop):
imageHueArray = new float[width,height];
for (int i = 0; i < img.width; i++)
{
for (int j = 0; j < img.height; j++)
{
imageHueArray[i,j] = pixelH;
}
}
New edit:
I have attempted new code based on some suggestions and links I looked at - I think it is getting closer, but not there yet (any better suggestions appreciated).
I replaced j with z in the array when loops through i in outer loop (as outside j loop).
This code increases size of image, but the increase portion is only blank (or at least using a fixed pixel, 0,0 perhaps) - I think it is in issue with the i/x plane as this does not seem to loop correctly, although the code looks okay (to me).
for (var i = 0; i < newRows; i++) {
for (var j = 0; j < newCols; j++) {
for (var k = 0; k < resizeScale; k++) {
imageHueArray[i,j] = pixelHSV;
}
z=j;
}
for (var k = 0; k < resizeScale; k++) {
imageHueArray[i,z] = pixelHSV;
}
}

Related

Is there any way to speed up array initialization?

I have a function that stores values inside some arrays. Every time the function is called, the arrays have to be cleared before putting items in them.
public static void UpdateAttackedPieces()
{
attackedSquares = new List<int>[2][];
for (int color = 0; color < 2; color++) attackedSquares[color] = new List<int>[64];
for (int color = 0; color < 2; color++) for (int i = 0; i < 64; i++) attackedSquares[color][i] = new List<int>();
checkAttackersRays = new List<int>[2][];
for (int color = 0; color < 2; color++) checkAttackersRays[color] = new List<int>[64];
for (int color = 0; color < 2; color++) for (int i = 0; i < 64; i++) checkAttackersRays[color][i] = new List<int>();
// Update arrays
}
(It is a chess program and the function is for updating pieces under attack).
attackedSquares is an array (one per color) of the 64 squares on the board which holds information about its attackers (so attackedSquares[0][4][2] is the third attacker on the fifth square for white, for example)
I've done some testing and about 35% of the time it takes to run the function is spent initializing the jagged arrays. Is there a faster way to do this?
Thanks to #Matthey Watson's comment, I was able to bring the time down from 6.5 seconds to less than 1 second with this change in the code:
public static void UpdateAttackedPieces()
{
for (int color = 0; color < 2; color++) for (int i = 0; i < 64; i++) attackedSquares[color][i].Clear();
for (int color = 0; color < 2; color++) for (int i = 0; i < 64; i++) checkAttackersRays[color][i].Clear();
// Update arrays
}

How to eliminate duplicates in 2D arrays in C#

just started to learn programming and I need 2D array without duplicates. This code (well edited for 1D) worked just fine for 1D but doesn't for 2D and have no clue why.
Would be very happy if someone helped me. Thanks.
Random r = new Random();
int[,] array = new int[10, 8];
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
array[i, j] = r.Next(10, 100);
for (int k = 0; k < i; k++)
{
for (int l = 0; l < j; l++)
{
if (array[i,j] == array[k,l])
{
i--;
j--;
break;
}
}
}
}
}
With the nested j loop you are filling the entire second dimension for each i, but in the k and l loops you are only checking the grid to the upper and left of current cell. You could place a number twice because you are not checking every previously filled location.
If we change the code to this:
for (int k = 0; k < array.GetLength(0); k++)
{
for (int l = 0; l < array.GetLength(1); l++)
{
if (i != k && j != l && array[i, j] == array[k, l])
{
i--;
j--;
break;
}
}
}
Then you eliminate that problem, but you very quickly find that you get a IndexOutOfRangeException because you're decrementing both i & j at the same time. That's not moving you to the previous value - it's jumping back a whole row and left one cell - and that's ultimately sending i or j to -1 and that's not good.
If you want to do it like you're attempting then you need to have a way to simply move back to the previously filled cell, regardless of the row or column you're on.
Try this:
for (int x = 0; x < array.GetLength(0) * array.GetLength(1); x++)
{
array[x % array.GetLength(0), x / array.GetLength(0)] = r.Next(10, 100);
for (int y = 0; y < x; y++)
{
if (array[x % array.GetLength(0), x / array.GetLength(0)] == array[y % array.GetLength(0), y / array.GetLength(0)])
{
x--;
break;
};
}
}
However, that's not very efficient. Try this instead:
var values = Enumerable.Range(10, 90).OrderBy(_ => r.Next()).ToArray();
for (int x = 0; x < array.GetLength(0) * array.GetLength(1); x++)
{
array[x % array.GetLength(0), x / array.GetLength(0)] = values[x];
}
So, first of all, that just seems inefficient. Not sure why you want to do it this way, but then again, don't know the reason. Looks like a programming assignment.
My guess, you need a sort of double break going on. When you break finding a match, you don't break out to the "k" for loop, so you continue looking for a match even though you found one. Try setting a boolean value to say it's found, then use that in the criteria for the for loop for k. That'll break it out and let you start over on the outside loops for i and j.
Even then, it won't work because you indescriminately subtracted i and j. So if you're on position 1,2 you will jump back to 0,1 rather than 1,2. So you need to subtract j, if it drops below 0, then subtract from i and add "array.GetLength(1)" to j.
This solution depends on HashSet's property of containing unique elements. It has an Add method that returns false when we try to add existing elements.
Random r = new Random();
int[,] array = new int[10, 8];
var usedValues = new HashSet<int>();
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
int uniqueValue;
while (true)
{
uniqueValue = r.Next(10, 100);
if (usedValues.Add(uniqueValue)) break; // It is unique indeed
// It is not unique, try again.
}
array[i, j] = uniqueValue;
}
}
The above solution is more suitable when the range of the acceptable unique values is large. In this specific case the range is very small (10-99), and the solution offered by #Enigmativity is preferable.

How can I fill a 2d array recursively?

I have a string filled with 9 numbers. I want to fill a 3x3 array with the numbers. I've managed to do it using a foreach and 2 for loops, but I feel this is quite messy. How can I modify my code to recursively enter the values into the array? This is my code currently:
int[,] matrix = new int[3, 3];
if(key.Length < 9 || key.Length > 9)
{
keyfield.GetComponent<InputField>().text = " Key Not Valid";
}
else
{
foreach(char c in key)
{
for (int k = 0; k < 3; k++)
{
for (int j = 0; j < 3; j++)
{
matrix[j, k] = c - 0;
}
}
}
}
Note, I'm working with Unity.
Well, just iterate over the chars in your key and assign them to the array, one field at a time. It's just a matter of calculating the correct columns and rows:
for (int i = 0; i < 9; ++i)
{
int row = i / 3;
int col = i % 3;
matrix[row, col] = (int)key[i];
}
Also note that neither the code in your question nor the code in my answer solves the problem in a recursive way. Recursion is given when a method calls itself directly or indirectly, which is not required to solve this particular problem.

Problems with displaying information from an array

I am trying to make a simple program in C# code (Console Application), which prompts the user to enter 10 names and then the 10 names displayed at the end in a random order (not the order the names were entered in)
This is how far I have gotten:-
static void Main(string[] args)
{
string[] names = new string [10];
int i;
for ( i = 0; i < 10 ; i++)
{
Console.WriteLine("Give me name " + (i+1) );
names[i] = Console.ReadLine();
}
for (int j = 0; j <= 10; j++)
{
Console.WriteLine(names[j]);
}
Console.ReadLine();
}
So far I have been able to prompt the user for 10 names, and store those 10 names, and display them at the end, however, once they are displayed I get the error :- "IndexOutOfRangeException was unhandled" and the Console.WriteLine(names[j]); gets highlighted.
Lastly, once these problems are sorted, how do I display the names entered back in random order?
Thanks for reading.
You get from 0 to 9 from input, but try to print from 0 to 10.
The 10th item does not exist in the array.
Correct it like below:
for (int j = 0; j < 10; j++)
{
Console.WriteLine(names[j]);
}
Hope this helps.
The first loop runs from 0 to 9, but the second runs from 0 to 10, so you try to display an item that doesn't exist in the array. Change j <= 10 to j < 10 in the loop (just like in the first loop) to loop to 9 instead of 10.
Better yet, you can use i < names.Length and j < names.Length in the loops. That way you can change the size of the array and the loops will still work without any change.
To display the items in random order you would want to shuffle the array. The best method for that is a Fisher-Yates shuffle. Shuffle the items in the array like this:
Random rnd = new Random();
for (int i = 0; i < names.Length − 1; i++) {
int j = rnd.Next(i, names.Length);
string tmp = names[i];
names[i] = names[j];
names[j] = tmp;
}
Then you can just show the items from the array the way that you do now (with the correction in the loop).
To resolve error, only check for less than 10 (<10) instead of less than or equal to 10 (<=10)
and to get random order use Random class. Make sure only one random instance is created and you call Next so that new random number is generated in tight loop
Random random = new Random();
for (int j = 0; j < 10; j++)
{
int randomNumber = random.Next(1,10);
Console.WriteLine(names[randomNumber-1]);
}
The problem is that your index is 0 based, and contains 10 entries, but the last one is Array[9] not Array[10]
{Frank,Paul,John}
So Array[0] is Frank,
and Array[3] is... out of range.
Your loop uses
for (int j = 0; j <= 10; j++)
{
Console.WriteLine(names[j]);
}
The first time through, j = 0, names[j] would be Frank for us. Your problem is since 10 <= 10 is indeed true, it is looking for j[10], which doesn't exist.
The solution is to change j < 10
for (int j = 0; j < 10; j++)
{
Console.WriteLine(names[j]);
}

IndexOutOfRangeException C#

My goal is to make a triple for loop to multiply matrix X matrix, i get in input the matrix and i have to get matrix^2.
I get the error "IndexOutOfRangeException" - index was outside the bounds of the array when i debug the following code:
for (int i = 1; i < nodeList.Count+1; i++)
{
for (int j = 1; j < nodeList.Count+1; j++)
{
result[i, j] = "0";
for (int k = 1; k < nodeList.Count+1; i++)
{
if ((matrix[i, k] != null) && (matrix[k, j] != null))
{
n1 = Convert.ToInt32(matrix[i, k]);
n2 = Convert.ToInt32(matrix[k, j]);
n3 = Convert.ToInt32(result[i, j]);
total = n3 + n1 * n2;
_total = total.ToString();
result[i, j] = _total;
}
}
}
}
where the variables are:
1. matrix that is type String[,] and the dimensions are (nodelist+1,nodelist+1)
2.result that is is the same type and dimension of the matrix, where i want to put the resultant matrix
3.nodelist is the array of the names of the nodes that i have in the diagram
4. n1,n2,n3 are int, I put in them the convert int from the matrix
5.total is the result of the operation for the multiplication
6._total convert total int in total string for the result matrix
So i set the right dimensions for every array and matrix but i get constantly the same error. I don't get it why. Can please someone help to notice the error, because i don't see it.
In the k loop, you are incrementing i.
for (int k = 1; k < nodeList.Count+1; i++) <-- you are incrementing i, it should be incrementing k.
like this:
for (int k = 1; k < nodeList.Count+1; k++)
Arrays are 0-based in C# -- the first element is at position 0 instead of position 1.
for (int i = 1; i < nodeList.Count+1; i++)
... should be ...
for (int i = 0; i < nodeList.Count; i++)
You also have what appears to be a copy-paste error for the k-loop.
for (int k = 1; k < nodeList.Count+1; i++) // should be k++?
The standard way to use a for loop with an array is to use
for(int x= 0; x < arry.count ;x++)
using 1 and +1 as the conditional will assure that you get an index out of rage as c# arrays are indexed by 0
As mentioned you are incrementing by i in the K loop.
Also you will be getting the out of bounds error every time you try to access an matrix on the last iteration of the loops. Either you need to go from 0 to Count in your loops or you need to put a -1 in all of your matrix operations. ex:
results[i-1, j-1] = _total;
The matrix indexes start at 0.

Categories

Resources