How to implement a multidimensional array shuffling in CSharp? - c#

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

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();

Splitting a 2D array into 4 smaller 2D arrays

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()}");
}
}

How to create single dimensional, two dimensional,three dimensional as well as multi dimensional array using C#?

I am trying to keep all the combinations (5C1, 5C2, 5C3, 5C4, 5C5) of 1,2,3,4,5 into individual array. So I need to create dynamic array using for loop in c#.
Say for example,
Here n = 5 and r = 1 to 5.
if r = 1 then
My array will be single dimensional array, when r = 2 then it will be two dimensional array, when r = 3 then three dimensional, when r = 4 then four dimensional array and it will e continued up to end of 5.
My code is given below
string[] ShipArrayObj;
public frmResult( string[] ShipArray )
{
InitializeComponent();
ShipArrayObj = ShipArray;
}
private void frmResult_Load(object sender, EventArgs e)
{
string[] arr = ShipArrayObj;
int n = ShipArrayObj.Count();
for (int r = 1; r <= n; r++)
{
StoreCombination(arr, n, r);
richTextBox1.Text = richTextBox1.Text + "/";
}
}
void StoreCombination(string[] arr, int n, int r)
{
string[] data = new string[r];
createCombination (arr, data, 0, n - 1, 0, r);
}
private void createCombination(string[] arr, string[] data, int start, int end, int index, int r)
{
if (index == r)
{
int j = 0;
for (j = 0; j < r; j++)
richTextBox1.Text = richTextBox1.Text + data[j].ToString();//Where I want to set array to keep combination values
return;
}
int i = 0;
for (i = start; i <= end && end - i + 1 >= r - index; i++)
{
data[index] = arr[i];
CreateCombination(arr, data, i + 1, end, index + 1, r);
}
}
I am storing all the combination into a Rich Text Box, but want to keep into array. If anybody help me then I will be grateful to you.
If you're used to something like Java then multidimensional arrays are a little different in syntax in C#.
Here's a page describing how to do them in C#. Here's a snippet from said page:
// Two-dimensional array.
int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// The same array with dimensions specified.
int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// A similar array with string elements.
string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" },
{ "five", "six" } };
// Three-dimensional array.
int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
// The same array with dimensions specified.
int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
If you're interested in different combinations of things with a fixed number of them, something like this should be all you need.
If you're interested in different combinations of things with a dynamic number of them, something like this should be all you need.
(Unless you're trying to optimize performance, it's better to be readable/expressive, generally speaking.)
You may need to consider whether or not order matters (un-ordered set vs. ordered list). I would assume it doesn't from your code (in which case sorting is good to eliminate "duplicates"), but I can't tell for sure.
Here's a good example that's easy to read and modify for variations and isn't so bad for small numbers:
// -1, 0, ..., 5
var choices = Enumerable.Range(-1, 6);
var possibleChoices =
from a in choices
from b in choices
from c in choices
from d in choices
from e in choices
select (IEnumerable<int>)new [] { a, b, c, d, e };
// Remove -1's because they represent not being in the choice.
possibleChoices =
possibleChoices.Select(c => c.Where(d => d >= 0));
// Remove choices that have non-unique digits.
possibleChoices =
possibleChoices.Where(c => c.Distinct().Count() == c.Count());
// Sort the choices to indicate order doesn't matter
possibleChoices =
possibleChoices.Select(c => c.OrderBy(d => d));
// Remove duplicates
possibleChoices =
possibleChoices.Select(c => new
{
Key = string.Join(",", c),
Choice = c
}).
GroupBy(c => c.Key).
Select(g => g.FirstOrDefault().Choice);
foreach (var choice in possibleChoices) {
Console.Out.WriteLine(string.Join(", ", choice));
}
Output:
0
1
2
3
4
0, 1
0, 2
0, 3
0, 4
1, 2
1, 3
1, 4
2, 3
2, 4
3, 4
0, 1, 2
0, 1, 3
0, 1, 4
0, 2, 3
0, 2, 4
0, 3, 4
1, 2, 3
1, 2, 4
1, 3, 4
2, 3, 4
0, 1, 2, 3
0, 1, 2, 4
0, 1, 3, 4
0, 2, 3, 4
1, 2, 3, 4
0, 1, 2, 3, 4
This is probably a little more dense to understand, hard-coded to this specific variation of combination and involves recursion but is a bit more generic/isn't hard-coded to 5 (and took 0.047s on dotnetfiddle.net instead of 0.094s). It's also completely lazy/IEnumerable.
public static void Main()
{
var possibleChoices = Choose(5);
foreach (var choice in possibleChoices) {
Console.Out.WriteLine(string.Join(", ", choice));
}
}
public static IEnumerable<IEnumerable<int>> Choose(int max)
{
var remaining = Enumerable.Range(0, max);
return ChooseRecursive(remaining, Enumerable.Empty<int>());
}
public static IEnumerable<IEnumerable<int>> ChooseRecursive(IEnumerable<int> remaining, IEnumerable<int> chosen)
{
yield return chosen;
foreach (var digit in remaining)
{
var choices = ChooseRecursive(
remaining.Where(d => d > digit),
chosen.Concat(new [] { digit })
);
foreach (var choice in choices)
{
yield return choice;
}
}
}
Output:
0
0, 1
0, 1, 2
0, 1, 2, 3
0, 1, 2, 3, 4
0, 1, 2, 4
0, 1, 3
0, 1, 3, 4
0, 1, 4
0, 2
0, 2, 3
0, 2, 3, 4
0, 2, 4
0, 3
0, 3, 4
0, 4
1
1, 2
1, 2, 3
1, 2, 3, 4
1, 2, 4
1, 3
1, 3, 4
1, 4
2
2, 3
2, 3, 4
2, 4
3
3, 4
4

C# Method to Create an NxN Matrix

How do I go about writing a method to create a populated nxn matrix like so:
int[,] Matrix(int n) or int[][] Matrix(int n) for example for n = 5:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
One solution is this:
static int[,] Matrix(int n)
{
if (n < 0)
throw new ArgumentException("n must be a positive integer.", "n");
var result = new int[n, n];
int level = 0,
counter = 1;
while (level < (int)Math.Ceiling(n / 2f))
{
// Start at top left of this level.
int x = level,
y = level;
// Move from left to right.
for (; x < n - level; x++)
result[y, x] = counter++;
// Move from top to bottom.
for (y++, x--; y < n - level; y++)
result[y, x] = counter++;
// Move from right to left.
for (x--, y--; x >= level; x--)
result[y, x] = counter++;
// Move from bottom to top. Do not overwrite top left cell.
for (y--, x++; y >= level + 1; y--)
result[y, x] = counter++;
// Go to inner level.
level++;
}
return result;
}
Here are the resultant matrices (n between 1 and 6) printed to console:
This can be achieved in this MSDN Example.
Google Search Results
// Two-dimensional array.
int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// The same array with dimensions specified.
int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// A similar array with string elements.
string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" },
{ "five", "six" } };
// Three-dimensional array.
int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
// The same array with dimensions specified.
int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
// Accessing array elements.
System.Console.WriteLine(array2D[0, 0]);
System.Console.WriteLine(array2D[0, 1]);
System.Console.WriteLine(array2D[1, 0]);
System.Console.WriteLine(array2D[1, 1]);
System.Console.WriteLine(array2D[3, 0]);
System.Console.WriteLine(array2Db[1, 0]);
System.Console.WriteLine(array3Da[1, 0, 1]);
System.Console.WriteLine(array3D[1, 1, 2]);
// Getting the total count of elements or the length of a given dimension.
var allLength = array3D.Length;
var total = 1;
for (int i = 0; i < array3D.Rank; i++) {
total *= array3D.GetLength(i);
}
System.Console.WriteLine("{0} equals {1}", allLength, total);
// Output:
// 1
// 2
// 3
// 4
// 7
// three
// 8
// 12
// 12 equals 12

Take slice from 2D array (int[ , ]) using LINQ in C#

I am not C# expert, and total LINQ beginner, having searched a bit in SO and Google without discovering how to do the following:
If I have, say, int[10,10] array, how can I get a 2D slice from it?
For example, if the values in the said array were dependent on their position (a[2,3] = 23, a[4,8] = 48, etc.), I'd like to perform the following pseudocode:
int[3,3] a_slice = slicer_method(a, 3, 6, 2, 5) // or anything equivalent to this
> [[ 32, 33, 34],
[ 42, 43, 44],
[ 52, 53, 54]]
It doesn't have specifically to use LINQ, but I've seen LINQ used in every similar operation I've come across lately.
#JaredPar is correct, there is no intrinsic way to do slices - that said, you can craft up an extension method to do so:
public static class Ext
{
public static T[] Slice<T>(this T[] source, int fromIdx, int toIdx)
{
T[] ret = new T[toIdx - fromIdx + 1];
for(int srcIdx=fromIdx, dstIdx = 0; srcIdx <= toIdx; srcIdx++)
{
ret[dstIdx++] = source[srcIdx];
}
return ret;
}
public static T[,] Slice<T>(this T[,] source, int fromIdxRank0, int toIdxRank0, int fromIdxRank1, int toIdxRank1)
{
T[,] ret = new T[toIdxRank0 - fromIdxRank0 + 1, toIdxRank1 - fromIdxRank1 + 1];
for(int srcIdxRank0=fromIdxRank0, dstIdxRank0 = 0; srcIdxRank0 <= toIdxRank0; srcIdxRank0++, dstIdxRank0++)
{
for(int srcIdxRank1=fromIdxRank1, dstIdxRank1 = 0; srcIdxRank1 <= toIdxRank1; srcIdxRank1++, dstIdxRank1++)
{
ret[dstIdxRank0, dstIdxRank1] = source[srcIdxRank0, srcIdxRank1];
}
}
return ret;
}
}
And a test:
void Main()
{
var singleArr = new int[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
singleArr.Slice(2, 4).Dump();
var doubleArr = new int[,]
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
};
doubleArr.Slice(2, 4, 2, 4).Dump();
}
There is no way to do this on the CLR because it doesn't support the notion of array slices. They best you can do is create a wrapper type over arrays that simulates slices
You can try something like this:
public T[,] Slice<T>(T[,] a, int x1, int y1, int x2, int y2)
{
var result = new T[x2 - x1, y2 - y1];
for (var i = x1; i < x2; i++)
{
for (var j = y1; j < y2; j++)
{
result[i - x1, j - y1] = a[i,j];
}
}
return result;
}
sample
public class MyArraySlice<T> where T:struct {
public MyArraySlice(T[,] array, int xMin, int xMax, int yMin, int yMax) {
Array = array;
XMin = xMin; XMax = xMax;
YMin = yMin; YMax = yMax;
}
public T this[int i, int j] { get {
if (XMin <= i && i < XMax && YMin <= j && j < YMax)
return Array[i+XMin, j+YMin];
throw new ArgumentOutOfRangeException();
}
}
T[,] Array;
int XMin;
int XMax;
int YMin;
int YMax;
}

Categories

Resources