Iteratively divide 2D array - c#

int numberOfThreads=4;
int division = (size * size) / numberOfThreads;
int startI = 0, startJ = 0;
int endI = division/size,endJ=division%size;
for (int i = 0; i < 4; i++)
{
Console.WriteLine("Start I: {0} Start J:{1} && End I: {2} End J: {3}",startI,startJ,endI,endJ);
startI = endI;
startJ = endJ;
//endI += (division/size); <-- how to find next ending index?
//endJ += (division % size); <-- how to find next ending index?
}
I want to divide my 2D array into numberOfThreads parts. I know how to get the starting and ending index of first part, but I need help to find endI and endJ for rest of the array. For example if I had a 4x4 array which I want to divide in to 4 partsI would want
0,0 to 0,3 -> 1,0 to 1,3 -> 2,0 to 2,3 -> 3,0 to 3,4
If I want to divide it ino 8 parts:
0,0 to 0,0 -> 0,1 to 0,1 -> 0,2 to 0,2 -> 0,3 to 0,3 etc

So assuming I've understood correctly, I think you want to end up with something like this:
[
[[0,0],[0,1][0,2][0,3]],
[[1,0],[1,1][1,2][1,3]],
[[2,0],[2,1][2,2][2,3]],
[[3,0],[3,1][3,2][3,3]]
]
Or perhaps like this:
[
[0,0],
[0,1],
[0,2],
[0,3],
[1,0],
[1,1],
[1,2],
[1,3],
[2,0],
[2,1],
[2,2],
[2,3],
[3,0],
[3,1],
[3,2],
[3,3]
}
I'm still a little unclear what your original array looks like, but I'm guessing you're doing it from array dimensions rather than an actual filled array.
If this is all still the case I would do something like this for the 1st version:
public int[][][] GetArrayCoordinates(int xAxisSize, int yAxisSize)
{
var coordinatesArray = new int[xAxisSize][][];
for (int x = 0; x < xAxisSize; x++)
{
coordinatesArray[x] = new int[yAxisSize][];
for (int y = 0; y < yAxisSize; y++)
{
coordinatesArray[x][y] = new int[] { x , y};
}
}
return coordinatesArray;
}
This should give a multidimensional array (an array of arrays of arrays) with the x co-ordinate coming first in each set.
2nd version:
public int[][] GetArrayCoordinates(int xAxisSize, int yAxisSize)
{
var index = 0;
var coordinatesArray = new int[xAxisSize * yAxisSize][];
for (int x = 0; x < xAxisSize; x++)
{
for (int y = 0; y < yAxisSize; y++)
{
coordinatesArray[index] = new int[] { x, y };
index++;
}
}
return coordinatesArray;
}
This should give you a jagged array (array of arrays) with the x co-ordinate coming first in each set.

Related

How to put matrix into array in one for-loop?

I am trying to put the values of a matrix into an array in a specific order. The matrix is 2*length, where the length is the length of the message chosen by the user divided by two. The array is the entire length.
I have attempted using a for-loop where the first two values of the matrix ([0, 0] and [1, 0]) are put in the array.
Int[,] result = new int[2, length/2];
String[] resultArray = new string[length];
tracker = 0;
while (tracker < length)
{
for (int i = 0; i < length/2; i++)
{
resultArray[2*i] = Convert.ToString(result[0, i]);
resultArray[(2*i)+1] = Convert.ToString(result[1, i]);
}
tracker++;
}
When I run this code, I get the System.IndexOutOfRangeException: 'Index was outside the bounds of the array.' error message. The second expression in the for-loop is highlited.
I can't seem to realize what I've done wrong. (2*i)+1 when i=(length/2-1) should equal length-1, right?
Not a explicit answer, but way more fault proof than your aproach: to iterate trough a square matrix you can use
var y = i / d
var x = i % d
where d is the dimension of the array
int d = 2;
int length = d * d; // square matrix;
for (int i = 0; i < length; i++)
{
// iterate trough the array via column -> row by row (or horizontal)
int y = i / d;
int x = i % d; // => i mod 2 (remnant of division by 2)
resultArray[i] = Convert.ToString(result[x, y]);
}
for (int i = 0; i < length; i++)
{
// iterate trough the array via row -> column by column (or vertical)
int x = i / d;
int y = i % d;
resultArray[i] = Convert.ToString(result[x, y]);
}
You can actually iterate over a matrix using LINQ. You just need to use Cast<T>() to get the right IEnumerable interface then use a simple Select. It'll iterate over the first dimension first and within that iterate over the second dimension.
If I set up test data like this:
int[,] result = new int[2, 5];
result[0,0] = 00;
result[0,1] = 01;
result[0,2] = 02;
result[0,3] = 03;
result[0,4] = 04;
result[1,0] = 10;
result[1,1] = 11;
result[1,2] = 12;
result[1,3] = 13;
result[1,4] = 14;
Then this statement:
var resultArray1 = result.Cast<int>().Select( n => n.ToString("00")).ToArray();
Will yield these results:
00
01
02
03
04
10
11
12
13
14
If you wish to iterate over the second dimension first, you can write a short extension method:
public static IEnumerable<T> ToSingleDimension<T>(this T[,] source)
{
for (int i=0; i<=source.GetUpperBound(1); i++)
{
for (int j=0; j<=source.GetUpperBound(0); j++)
{
yield return source[j,i];
}
}
}
And call it like this:
var resultArray2 = result.ToSingleDimension().Select( n => n.ToString("00")).ToArray();
Which will yield these results:
00
10
01
11
02
12
03
13
04
14
See the example on DotNetFiddle.
You can use MathNet.Numerics library with some LINQ to achieve what you want:
PM > Install-Package MathNet.Numerics
var result = new double[2,4]
{
{ 1,2,3,4 },
{ 5,6,7,8 },
};
var resultArray = Matrix
.Build
.DenseOfArray(result)
.ToRowArrays()
.SelectMany(q => q.ToArray().Select(w => w.ToString()))
.ToArray();
You can use ToColumnArrays() if your initial array has shape [4,2] rather than [2,4]

How to build a large 2d array out of many smaller 2d arrays

I am trying to work towards a
512 x 512 (262144 elements)
I currently have a
List<double[,]> data;
Dimensions are:
4096 x [8 , 8] (262144 elements)
The 2d array I am working towards is square.
List<List<float>> newList = new List<List<float>(); //working towards
I have tried something along the lines of:
for (int i = 0; i < Math.Sqrt(data.Count); i++ ) {
List<float> row = new List<float>();
foreach (double[,] block in data) {
for (int j = 0; j < 8; j++) {
row.Add(block[i,j]); //i clearly out of range
}
}
newList.Add(row);
}
What I was trying to do there was to brute force my way and add up every row (which is 8 in length) and then add the large rows to the newList.
I believe you can do that in the following way
var newList = new List<List<float>>();
for (int i = 0; i < 512; i++)
{
var innerList = new List<float>();
for (int j = 0; j < 512; j++)
{
int x =(i/8)*64 + (j/8);
int y = i % 8;
int z = j % 8;
innerList.Add(data[x][y,z]);
}
newList.Add(innerList);
}
Basically you have 64x64 of your 8x8 blocks. So the (i,j) coordinate of the larger 512x512 structure translate in the following ways. First to determine the 8x8 block you have to figure out the row and column of the 64x64 structure of blocks by dividing the i and j by the size of the block (8) then you multiply the row (i/8) by the number of block in a row (64) and add the column (j/8). For the y and z it's simpler because you know that its just a matter of the remainder of i and j when divided by 8 (i%8) and (j%8).

Maximum Submatrix Sum of nxn matrices

I'm trying to get the maximum Submatrix Sum from given nxn matrices. From what I read around the algorithm have a complexity of n^3 (kadane). I tried to implement it in java using a code I found here on stackoverflow (written by Anders Gustafsson in C# in these post) but it seems to not always work.
my code is this:
public static void maxSubMatrix(int matrix[][]) {
// O(n^3) Max Sum Submatrix
int row = matrix.length;
int col = matrix[0].length; // Get the col-length by taking the length of
// row 0 (in programm the matrices will be n x n)
// Initialise maxSum
int maxSum = 0;
// Set left column
for (int left=0; left<col; left++) {
// Initialise array
int tempArray[] = new int[row];
// Set right column by left column (outer loop)
for (int right=left; right<col; right++){
// Calculate sum between current left-right for every row 'i'
for (int i=0; i<row; i++)
tempArray[i] = matrix[i][right];
// ----
// Find maximum sum in tempArray[]
int sum = maxSubArray(tempArray);
// Compare sum with maxSum so far, and update it if necessary
if (sum > maxSum) maxSum = sum;
}
}
System.out.println(maxSum);
}
// ==========================
public static int maxSubArray(int array[]){
// Kadane O(n) Max Sum Subarray
int maxSum = 0;
int tempSum = 0;
for (int i=0; i<array.length; i++){
int b = array[i];
if (tempSum + b > 0) tempSum += b;
else tempSum = 0;
maxSum = Math.max(maxSum, tempSum);
}
return maxSum;
}
I have three examples:
Matrix 1
-2 -3
-1 -4
Output is 0 (Also the empty 0x0 Matrix is a solution)
Matrix 2
2 -1
-2 -1
Output is 2
Matrix 3
-1 3
3 -1
Output is 3, but should be 4
Maybe someone can see the error. I'm also open to completely new idea to implement it.
You have just forgotten to add the next rigth element to the temp-array:
(int i=0; i<row; i++)
tempArray[i] += matrix[i][right];
Now everything's fine! ;)
Greetz

How to Save a Multidimensional Array Index?

Basically my first task was to save the position of the '0' in an integer. Real simple with a standard array. This code loops through an array (Size: 8) until it locates the 0, then save that as the position. See code below:
p.s: n is a reference to an array saved somewhere else.
int position = 0;
this.nodesExpanded++;
// Loop through the array to get the position of where '0' is
for (int i = 0; i < n.getPuzzle().length; i++){
if (n.getPuzzle()[i] == 0){
position = i;
break;
}
}
My ultimate task was to make this possible for a multidimensional array (Size: [3, 3]). So here's what I've created thus far:
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
if (n.getPuzzle()[x,y] == 0)
{
**position = ;**
break;
}
}//end y loop
}//end x loop
So how do I go about saving an array reference to a location to a value?
'position' will need to be something other than int I'm guessing..
If you need more clarification be sure to comment, sorry in advance & thank you!
You can use a Tuple to store that position. Or you can create your own data structure.
Example: at the end you can see how to access tuple items.
var positions = new List<Tuple<int, int>>();
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
if (n.getPuzzle()[x,y] == 0)
{
positions.Add(new Tuple<int, int>(x,y));
break;
}
}//end y loop
}//end x loop
if(positions.Any())
{
var xpos = positions[0].Item1;
var ypos = positions[0].Item2;
}
I find a natural way to store a multidimensional array index is to use a single dimensional array whose size is the number of dimensions.
So if you have a object[,,] A and index int[] i you would index into A with the expression A[i[0],i[1],i[2]].
It works the same way as your one-dimensional array, but you have two position values to keep. I've used ints for the example, but you may want to use a custom structure or Tuple (as AD.Net) said.
int xpos = -1;
int ypos = -1;
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
if (n.getPuzzle()[x,y] == 0)
{
xpos = x;
ypos = y;
break;
}
}//end y loop
}//end x loop
if (!(xpos > -1 && ypos > -1)) ; // 0 was not found

Does Array.Copy work with multidimensional arrays?

This code works fine:
var newArray = new Rectangle[newHeight, newWidth];
for (int x = 0; x < newWidth; x++)
for (int y = 0; y < newHeight; y++)
newArray[y, x] = (x >= width) || (y >= height) ? Rectangle.Empty : tiles[y, x];
But I am not having much luck replacing it with Array.Copy. Basically, if the resized array is larger it just adds blank rectangles to the edges. If it is smaller then it should just cut off the edges.
When doing this:
Array.Copy(tiles, newArray, newWidth * newHeight);
It messes up the array and all of its contents become disordered and do not retain their original index. Maybe I'm just having a brainfart or something?
Yes. However, it doesn't work the way you are thinking it works. Rather, it thinks of each mutlidimensional array as a single-dimensional array (which is actually what they are in memory, it's just a trick that lets us place some structure on top of them to think of them as multidimensional) and then copies the single-dimensional structures. So if you have
1 2 3
4 5 6
and want to copy it into
x x x x
x x x x
then it will think of the first array as
1 2 3 4 5 6
and the second as
x x x x x x x x
and the result will be
1 2 3 4 5 6 x x
which will appear to you as
1 2 3 4
5 6 x x
Got it?
I use this code:
public static void ResizeBidimArrayWithElements<T>(ref T[,] original, int rows, int cols)
{
T[,] newArray = new T[rows, cols];
int minX = Math.Min(original.GetLength(0), newArray.GetLength(0));
int minY = Math.Min(original.GetLength(1), newArray.GetLength(1));
for (int i = 0; i < minX; ++i)
Array.Copy(original, i * original.GetLength(1), newArray, i * newArray.GetLength(1), minY);
original = newArray;
}
calling like this for array of strings
ResizeBidimArrayWithElements<string>(ref arrayOrigin, vNumRows, vNumCols);
Simple use the "Clone()" function like the following:
This is your array list
object newArray = new object [row, column];
When you are creating another Array just use this code:
object[,] clonedArray = (object[,]) newArray.Clone();
Simple! Have fun!
I had a need to consume data from a buffer and copy off to a large holding array before the next interrupt hit. Copying in a loop wasn't an option; far too slow. I didn't need the multidimensional structure of the combined data until all of the copying was done, this meant I could Buffer.BlockCopy() to a single dimension array, then copy again onto a multidimensional array to obtain the required structure. Here's some code (run it in a console) that will demonstrate the technique as well as the performance.
static class Program
{
[STAThread]
static void Main()
{
Stopwatch watch = new Stopwatch();
const int width = 2;
const int depth = 10 * 1000000;
// Create a large array of data
Random r = new Random(100);
int[,] data = new int[width, depth];
for(int i = 0; i < width; i++)
{
for(int j = 0; j < depth; j++)
{
data[i, j] = r.Next();
}
}
// Block copy to a single dimension array
watch.Start();
int[] buffer = new int[width * depth];
Buffer.BlockCopy(data, 0, buffer, 0, data.Length * sizeof(int));
watch.Stop();
Console.WriteLine("BlockCopy to flat array took {0}", watch.ElapsedMilliseconds);
// Block copy to multidimensional array
int[,] data2 = new int[width, depth];
watch.Start();
Buffer.BlockCopy(buffer, 0, data2, 0,buffer.Length * sizeof(int));
watch.Stop();
Console.WriteLine("BlockCopy to 2 dimensional array took {0}", watch.ElapsedMilliseconds);
// Now try a loop based copy - eck!
data2 = new int[width, depth];
watch.Start();
for (int i = 0; i < width; i++)
{
for (int j = 0; j < depth; j++)
{
data2[i, j] = data[i, j];
}
}
watch.Stop();
Console.WriteLine("Loop-copy to 2 dimensional array took {0} ms", watch.ElapsedMilliseconds);
}
}
Output:
BlockCopy to flat array took 14 ms
BlockCopy to 2 dimensional array took 28 ms
Loop-copy to 2 dimensional array took 149 ms

Categories