Splitting a 2D array into 4 smaller 2D arrays - c#

I need to loop through a 2D array of ints that is 4x4, but I also have to create 4 2x2 arrays out of it. Then I have to loop through each of those 4 2x2 arrays to pick out the average of the numbers in each 2x2 array.
public int[,] Reduced(Sampler sampler)
{
int[,] a = new int[SampleSize,SampleSize];
for (int r = 0; r < Math.Sqrt(image.Length); r+=SampleSize)
{
for (int c = 0; c < Math.Sqrt(image.Length); c+=SampleSize)
{
InsideLoop(a, r, c);
}
}
return a;
}
private void InsideLoop(int[,] a, int r, int c)
{
for (r = 0; r < SampleSize; r++)
{
for (c = 0; c < SampleSize; c++)
{
a[r, c] = image[r, c];
Console.WriteLine("Value: {0}", a[r, c]);
}
}
}
This is essentially what I've got so far, but it's working how it's written instead of how I'd like it to work. For this example, SampleSize is a variable that is set to 2. What this does currently is print out the numbers that create the first 2x2 array four times. My laptop battery is about to die, so I can't elborate more, but if anyone has any tips while I'm driving home. I had to finish posting this on my phone.

Does this work?
int sampleSize = 2;
int[,] data = {
{1, 2, 3, 4 },
{5, 6, 7, 8 },
{9, 10, 11, 12 },
{13, 14, 15, 16 }
};
//assume input data is a perfect square as per your example
int max = (int)Math.Sqrt(data.Length);
List<int[,]> samples = new List<int[,]>();
int startX = 0;
while (startX + sampleSize <= max)
{
int startY = 0;
while (startY + sampleSize <= max)
{
int[,] sample = new int[sampleSize, sampleSize];
for (int x = 0; x < sampleSize;x++)
{
for (int y = 0; y < sampleSize; y++)
{
sample[x, y] = data[x + startX, y + startY];
}
}
samples.Add(sample);
startY += sampleSize;
}
startX += sampleSize;
}
//for output testing
foreach (int[,] sample in samples)
{
Console.WriteLine(sample[0, 0].ToString().PadLeft(2) + " | " + sample[0, 1]);
Console.WriteLine(" ----- ");
Console.WriteLine(sample[1, 0].ToString().PadLeft(2) + " | " + sample[1, 1]);
Console.WriteLine();
Console.WriteLine();
}
Console.ReadLine();
and here's the output
1 | 2
-----
5 | 6
3 | 4
-----
7 | 8
9 | 10
-----
13 | 14
11 | 12
-----
15 | 16

Generalized version:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
int[,] original = new int[,] { { 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
int[,] harder = new int[,] { { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 10, 11, 12, 13, 14, 15, 16, 17, 18 },
{ 19, 20, 21, 22, 23, 24, 25, 26, 27 },
{ 28, 29, 30, 31, 32, 33, 34, 35, 36 },
{ 37, 38, 39, 40, 41, 42, 43, 44, 45 },
{ 46, 47, 48, 49, 50, 51, 52, 53, 54 },
{ 55, 56, 57, 58, 59, 60, 61, 62, 63 },
{ 64, 65, 66, 67, 68, 69, 70, 71, 72 },
{ 73, 74, 75, 76, 77, 78, 79, 80, 81 } };
IterateArray(original);
Console.ReadLine();
}
static void IterateArray(int[,] array)
{
double tDim = Math.Sqrt(Math.Sqrt(array.Length));
int dim = (int)tDim;
if (dim != tDim) throw new ArgumentException("Not a valid array!");
for (int i = 0; i < dim; i++)
{
IterateRows(array, dim, i);
}
}
static void IterateRows(int[,] array, int dim, int pass)
{
int maxRow = dim * dim;
IList<int> list = new List<int>(maxRow);
for (int curRow = 0; curRow < maxRow; curRow++)
{
IterateColumns(array, dim, curRow, pass, list);
if (list.Count == maxRow)
{
PrintNewArray(list, dim);
list.Clear();
}
}
}
static void IterateColumns(int[,] array, int dim, int row, int pass, IList<int> list)
{
int maxCol = dim + (dim * pass);
for (int curCol = pass * dim; curCol < maxCol; curCol++)
{
list.Add(array[row, curCol]);
}
}
static void PrintNewArray(IList<int> list, int dim)
{
for(int i = 0; i < list.Count; i++)
{
if (i % dim == 0)
{
Console.WriteLine();
}
Console.Write($"{list[i]} ");
}
Console.WriteLine($"\nAverage {list.Average()}");
}
}

Related

Get the maximum Count of a range of values in an Array in C#

I have this array. If the minimum Value is defined as 22, I want the get the maximum number of integers that are next to each other that are higher than 22. For example, here 22 and 23 and higher or equal to 22. The loop breaks at 21. The counter is 2 integers. Then the loop goes to 22,23,23,24,22 and the counter is now 5 integers.At the end I need to get the range that delivers the maximum number of integers that is 5 in this case.
How will I write this code please? I am working for 2 days on this now.
Array:
int[] tempList = { 20, 22, 23, 21, 19, 18, 20, 22, 23, 23, 24, 22, 21 };
Min Value: 22
int[] tempList = { 20, 22, 23, 21, 19, 18, 20, 22, 23, 23, 24, 22, 21 };
var g = tempList.ToArray();
int lastStartIndex = -1;
int lastEndIndex = -1;
int min = 20;
int lastSum = 0;
int i = 0;
while ( i < g.Length)
{
if (g[i] > min)
{
lastStartIndex = i;
int lastSumTemp = 0;
int j = lastStartIndex ;
while (j<g.Length)
{
if (g[j] > min)
{
lastSumTemp += g[j];
j++;
}
else
{
if (lastSumTemp> lastSum)
{
lastSum = lastSumTemp;
lastEndIndex = j;
}
break;
}
}
if (j==g.Length && g[j-1] > min)
{
if (lastSumTemp > lastSum)
{
lastSum = lastSumTemp;
lastEndIndex = j-1;
}
break;
}
i = j + 1;
}
else
{
i++;
}
}
Console.WriteLine(lastStartIndex);
Console.WriteLine(lastEndIndex);
Console.WriteLine(lastSum);
Console.ReadLine();

How can sort by odd,even row?

I hava jagged Array
I want sort first,third row ascending order and second,fourth row descending order
public class JaggedArrayTest {
public static void Main() {
int[][] arr = new int[4][] {
new int[] {
11,
78,
56,
21
},
new int[] {
2,
7,
5,
6
},
new int[] {
8,
3,
9,
12
},
new int[] {
1,
10,
19,
17
}
};
// Traverse array elements
for (int i = 0; i < arr.Length; i++) {
for (int j = 0; j < arr[i].Length; j++) {
System.Console.Write(arr[i][j] + " ");
}
System.Console.WriteLine();
}
}
}
I want output like this
11, 21, 56, 78 
7, 6, 5,2
3, 8,9,12
19,17,10,1
Algo:-
Loop through each row.
Use Array.Sort() to sort each row
for(int row = 0; row < arr.Length; row++)
{
Array.Sort(arr[row]);
}
Although a little "allocatey", this can be done with linq and the remainder operator (to test for odd or even) fairly easily
The remainder operator ``% computes the remainder after dividing its
left-hand operand by its right-hand operand.
var results = arr.Select((values, i)
=> (i % 2 == 0 ? values.OrderBy(x => x) : values.OrderByDescending(x => x)).ToArray())
.ToArray();
foreach (var values in results)
Console.WriteLine(string.Join(", ",values));
Or an in situ, less "allocatey", and more idiomatic approach
for (var i = 0; i < arr.Length; i++)
{
Array.Sort(arr[i]);
if(i % 2 != 0)
Array.Reverse(arr[i]);
}
Output
11, 21, 56, 78
7, 6, 5, 2
3, 8, 9, 12
19, 17, 10, 1

How to implement a multidimensional array shuffling in CSharp?

I wonder if it is possible to implement a general Julia\Matlab alike View function in C# that would work for arrays of any dimensions (eg [,,] and [,,,]) as they do it in array slicer\mover view. So I wonder if there is a library that provides similar functionality for CSharp multidimentional arrays or how to implement it in C#?
The solution is twofold:
Use a wrapper class that holds a reference to the master array
Use the Array base class to make it polymorphic
Wrapper
class View<T>
{
private readonly Array array;
private readonly int dim;
private readonly int slice;
public View(Array array, int dim, int slice)
{
this.array = array;
this.dim = dim;
this.slice = slice;
}
public T this[params int[] indexes]
{
get { return (T)array.GetValue(BaseIndexesFor(indexes)); }
set { array.SetValue(value, BaseIndexesFor(indexes)); }
}
private int[] BaseIndexesFor(int[] indexes)
{
if (indexes.Length != array.Rank - 1) throw new ArgumentException("indexes");
int i_index = 0;
int[] baseIndexes = new int[array.Rank];
for (int i = 0; i < baseIndexes.Length; i++)
{
baseIndexes[i] = (i == dim) ? slice : indexes[i_index++];
}
return baseIndexes;
}
}
2D example
var A = new int[,]
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
/* View(Array array, int dim, int slice)
*
* For 2 dimensional array:
* dim=0 -> rows
* dim=1 -> columns
*/
// From second dimension slice index 1
// Or simply, take column with index 1
var B = new View<int>(A, 1, 1);
B[2] = 0;
Console.WriteLine(A[2, 1]); // 0
3D examples
var C = new int[,,]
{
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
},
{
{ 11, 12, 13 },
{ 14, 15, 16 },
{ 17, 18, 19 }
},
{
{ 21, 22, 23 },
{ 24, 25, 26 },
{ 27, 28, 29 }
}
};
/* From first dimension slice index 2
* { 21, 22, 23 },
* { 24, 25, 26 },
* { 27, 28, 29 }
*/
var D = new View<int>(C, 0, 2);
D[1, 1] = 0;
Console.WriteLine(C[2, 1, 1]); // 0
/* From third dimension slice index 0
* { 1, 4, 7 },
* { 11, 14, 17 },
* { 21, 24, 27 }
*/
var E = new View<int>(C, 2, 0);
E[2, 0] = 0;
Console.WriteLine(C[2, 0, 0]); // 0

Finding largest sequence of bytes in two byte arrays

Example:
{ 54, 87, 23, 87, 45, 67, 7, 85, 65, 65, 3, 4, 55, 76, 65, 64, 5, 6, 4, 54, 45, 6, 4 };
{ 76, 57, 65, 3, 4, 55, 76, 65, 64, 5, 6, 4, 54, 45, 8, 65, 66, 57, 6, 7, 7, 56, 6, 7, 44, 57, 8, 76, 54, 67 };
Basically, I have two byte[], and need to find the largest identical sequence of bytes in both.
I have tried the obvious thing and wrote some code that bruteforces the result:
var bestIndex = 0;
var bestCount = 0;
for (var i1 = 0; i1 + bestCount < data1.Length; i1++)
{
var currentCount = 0;
for (var i2 = 0; i2 < data2.Length; i2++)
{
if (data1[i1 + currentCount] == data2[i2])
{
currentCount++;
if (i1 + currentCount == data1.Length)
{
bestCount = currentCount;
bestIndex = i1;
break;
}
}
else
{
if (currentCount > bestCount)
{
bestCount = currentCount;
bestIndex = i1;
}
currentCount = 0;
}
}
if (currentCount > bestCount)
{
bestCount = currentCount;
bestIndex = i1;
}
}
However, in my application the byte arrays will be much larger, up to a GB even. So basically I need a hint / code on how to be more efficient than that.
I had a couple thoughts on this. I'm not sure if this helps or hurts, but have you considered working backwards through the largest possibilities first, so you can terminate as soon as you've found a match.
byte[] b1 = { 54, 87, 23, 87, 45, 67, 7, 85, 65, 65, 3, 4, 55, 76, 65, 64, 5, 6, 4, 54, 45, 6, 4 };
byte[] b2 = { 76, 57, 65, 3, 4, 55, 76, 65, 64, 5, 6, 4, 54, 45, 8, 65, 66, 57, 6, 7, 7, 56, 6, 7, 44, 57, 8, 76, 54, 67 };
//figure out which one is smaller, since that one will limit the range options
byte[] smaller;
byte[] bigger;
if (b1.Count() > b2.Count())
{
bigger = b1;
smaller = b2;
}
else
{
bigger = b2;
smaller = b1;
}
// doesn't matter what order we put these in, since they will be ordered later by length
List<Tuple<int, int>> ranges = new List<Tuple<int, int>>();
Parallel.For(0, smaller.Count(), (i1) => {
Parallel.For(i1 + 1, smaller.Count(), (i2) =>
{
ranges.Add(new Tuple<int, int>(i1, i2));
});
});
// order by length of slice produced by range in descending order
// this way, once we get an answer, we know nothing else can be longer
ranges = ranges.OrderByDescending(x => x.Item2 - x.Item1).ToList();
Tuple<int, int> largestMatchingRange = new Tuple<int, int>(0, 0);
foreach (Tuple<int, int> range in ranges)
{
bool match = true; // set in outer loop to allow for break
for (int i1 = 0; i1 < bigger.Count(); i1++)
{
if (bigger.Count() <= i1 + (range.Item2 - range.Item1))
{
//short cut if the available slice from the bigger array is shorter than the range length
match = false;
continue;
}
match = true; // reset to true to allow for new attempt for each larger array slice
for (int i2 = range.Item1, i1Temp = i1; i2 < range.Item2; i2++, i1Temp++)
{
if (bigger[i1Temp] != smaller[i2])
{
match = false;
break;
}
}
if (match)
{
largestMatchingRange = range;
break;
}
}
if (match)
{
break;
}
}
byte[] largestMatchingBytes = smaller.Skip(largestMatchingRange.Item1).Take(largestMatchingRange.Item2 - largestMatchingRange.Item1).ToArray();
Instead of checking the bytes one by one, you can save the index locations for each byte value in a dictionary of lists. In your case arrays of 256 lists might be better.
List<int>[] index(byte[] a) { // List<long> if the array can be more than 2GB
var lists = new List<int>[256];
for(int i = 0; i < a.Length; i++) {
var b = a[i];
if (lists[b] == null) lists[b] = new List<int>();
lists[b].Add(i);
}
return lists;
}
then you can loop over the 256 possible byte values
byte[] data1 = { 54, 87, 23, 87, 45, 67, 7, 85, 65, 65, 3, 4, 55, 76, 65, 64, 5, 6, 4, 54, 45, 6, 4 };
byte[] data2 = { 76, 57, 65, 3, 4, 55, 76, 65, 64, 5, 6, 4, 54, 45, 8, 65, 66, 57, 6, 7, 7, 56, 6, 7, 44, 57, 8, 76, 54, 67 };
var indexes1 = index(data1);
var indexes2 = index(data2);
var bestIndex = 0;
var bestCount = 0;
for (var b = 0; b < 256; b++)
{
var list1 = indexes1[b]; if (list1 == null) continue;
var list2 = indexes1[b]; if (list2 == null) continue;
foreach(var index1 in list1)
{
foreach (var index2 in list2)
{
// your code here
for (var i1 = index1; i1 < data1.Length - bestCount; i1++)
{
var currentCount = 0;
for (var i2 = index2; i2 < data2.Length; i2++)
{
if (data1[i1 + currentCount] == data2[i2])
{
currentCount++;
if (i1 + currentCount == data1.Length)
{
bestCount = currentCount;
bestIndex = i1;
break;
}
}
else
{
if (currentCount > bestCount)
{
bestCount = currentCount;
bestIndex = i1;
}
currentCount = 0;
}
}
if (currentCount > bestCount)
{
bestCount = currentCount;
bestIndex = i1;
}
}
}
}
}
var best = data1.Skip(bestIndex).Take(bestCount);
Debug.Print(bestIndex + ", " + bestCount + ": " + string.Join(", ", best));
In theory this feels like it will take less comparisons for bigger arrays, but in practice it will have more memory cache misses, so I am not sure if it will be faster than a more linear parallel version like in the other answer. I did not think into this too much but hopefully it can give you some ideas in case I got it wrong.
Update
I just realized how bad this idea is for a regular machine with less than 32 GB of memory as the list of indexes will take more than 4 times the memory of the byte array.
I figured out the loops, this one should be faster.
byte[] data1 = { 54, 87, 23, 87, 45, 67, 7, 85, 65, 65, 3, 4, 55, 76, 65, 64, 5, 6, 4, 54, 45, 6, 4 };
byte[] data2 = { 76, 57, 65, 3, 4, 55, 76, 65, 64, 5, 6, 4, 54, 45, 8, 65, 66, 57, 6, 7, 7, 56, 6, 7, 44, 57, 8, 76, 54, 67 };
//figure out which one is smaller, since that one will limit the range options
byte[] smaller;
byte[] bigger;
if (data1.Count() > data2.Count())
{
bigger = data1;
smaller = data2;
}
else
{
bigger = data2;
smaller = data1;
}
Tuple<int, int> largestMatchingRange = new Tuple<int, int>(0, 0);
//iterate over slices in reverse length order
for (int length = smaller.Count() - 1; length > 0; length--)
{
int numberOfSlicesForLength = smaller.Count() - length;
bool match = true; // set in outer loop to allow for break
for (int start = 0; start < numberOfSlicesForLength; start++)
{
//within a collection of similarly sized slices, we start with the slice found first within the array
Tuple<int, int> range = new Tuple<int, int>(start, start + length);
for (int i1 = 0; i1 < bigger.Count(); i1++)
{
if (bigger.Count() <= i1 + (range.Item2 - range.Item1))
{
//short cut if the available slice from the bigger array is shorter than the range length
match = false;
continue;
}
match = true; // reset to true to allow for new attempt for each larger array slice
for (int i2 = range.Item1, i1Temp = i1; i2 < range.Item2; i2++, i1Temp++)
{
if (bigger[i1Temp] != smaller[i2])
{
match = false;
break;
}
}
if (match)
{
largestMatchingRange = range;
break;
}
}
if (match)
{
break;
}
}
if (match)
{
break;
}
}
byte[] largestMatchingBytes = smaller.Skip(largestMatchingRange.Item1).Take(largestMatchingRange.Item2 - largestMatchingRange.Item1).ToArray();

C# 2D Array - how to print the largest element in each row

I'm raeding MTA 98-361 and there is a task: You are writing a program that uses a two-dimensional array. The array has four rows and five columns. You need to print the largest element in each row of the array.
My code:
static void Main(string[] args)
{
//[x, y] row, col
int[,] grid = new int[4,5] { { 1, 2, 4, 5, 6 }, //how to get largest number of each row
{ 3, 4, 7, 8, 9 },
{ 5, 6, 56, 12, 45 },
{ 7, 8, 45, 12, 78 }};
for (int row = 0; row < grid.GetLength(0); row++)
{
for (int col = 0; col < grid.GetLength(1); col++)
{
Console.Write(grid[row, col] + "\t ");
}
Console.WriteLine();
}
Console.WriteLine("Row1: {0} {1} {2} {3} {4} ", grid[0, 0], grid[0, 1], grid[0, 2], grid[0, 3], grid[0, 4]);
Console.ReadLine();
}
I know that this is my task, and should solve it, but I'm stuck.
Can you give me advice how to accomplish it?
Thanks!
Here's how you do it without spawning threads:
public static void Main()
{
int[,] grid = new int[4,5] { { 1, 2, 4, 5, 6 }, //how to get largest number of each row
{ 3, 4, 7, 8, 9 },
{ 5, 6, 56, 12, 45 },
{ 7, 8, 45, 12, 78 }};
int w=grid.GetLength(0), h=grid.GetLength(1);
Console.WriteLine(string.Join(",",
Enumerable.Range(0,w).Select(i=>Enumerable.Range(0,h).Select(j=>grid[i,j]).Max())));
}
You can see it in action here: https://dotnetfiddle.net/8u08i3

Categories

Resources