I want write extension method for fill multidimensional rectangular array. I know how to do it for the array with a fixed number of measurements:
public static void Fill<T>(this T[] source, T value)
{
for (int i = 0; i < source.Length; i++)
source[i] = value;
}
public static void Fill<T>(this T[,] source, T value)
{
for (int i = 0; i < source.GetLength(0); i++)
for (int j = 0; j < source.GetLength(1); j++)
source[i, j] = value;
}
public static void Fill<T>(this T[,,] source, T value)
{
for (int i = 0; i < source.GetLength(0); i++)
for (int j = 0; j < source.GetLength(1); j++)
for (int k = 0; k < source.GetLength(2); k++)
source[i, j, k] = value;
}
Can I write one fill-method for all multidimensional rectangular array?
You can change the fixed dimension parameter to an Array parameter so you can put the extension on any Array. Then I used recursion to iterate through each position of the array.
public static void Fill<T>(this Array source, T value)
{
Fill(0, source, new long[source.Rank], value);
}
static void Fill<T>(int dimension, Array array, long[] indexes, T value)
{
var lowerBound = array.GetLowerBound(dimension);
var upperBound = array.GetUpperBound(dimension);
for (int i = lowerBound; i <= upperBound; i++)
{
indexes[dimension] = i;
if (dimension < array.Rank - 1)
{
Fill(dimension + 1, array, indexes, value);
}
else
{
array.SetValue(value, indexes);
}
}
}
Here's a solution that does not use recursion (and is less complex):
public static void FillFlex<T>(this Array source, T value)
{
bool complete = false;
int[] indices = new int[source.Rank];
int index = source.GetLowerBound(0);
int totalElements = 1;
for (int i = 0; i < source.Rank; i++)
{
indices[i] = source.GetLowerBound(i);
totalElements *= source.GetLength(i);
}
indices[indices.Length - 1]--;
complete = totalElements == 0;
while (!complete)
{
index++;
int rank = source.Rank;
indices[rank - 1]++;
for (int i = rank - 1; i >= 0; i--)
{
if (indices[i] > source.GetUpperBound(i))
{
if (i == 0)
{
complete = true;
return;
}
for (int j = i; j < rank; j++)
{
indices[j] = source.GetLowerBound(j);
}
indices[i - 1]++;
}
}
source.SetValue(value, indices);
}
}
This is modeled from the System.Array.ArrayEnumerator. This implementation should have a similar level of correctness as ArrayEnumerator and (based on a few spot checks) appears to function fine.
Related
public static void GenerateRandomd<T>(D_List<T> list, int size, Random rand)
{
if (list is D_List<int>)
{
for (int i = 0; i < size; i++)
list.Push_Back(rand.Next(0, 10000));
}
else if (list is D_List<string>)
{
for (int i = 0; i < size; i++)
list.Push_Back(Gen_rand_string(rand));
}
else
{
for (int i = 0; i < size; i++)
list.Push_Back(rand.NextDouble());
}
}
Hello! Is it possible to implement something like this? Thank you in advance.
You just need to cast list variable with pattern matching:
public static void GenerateRandomd<T>(D_List<T> list, int size, Random rand)
{
switch (list)
{
case D_List<int> il:
for (int i = 0; i < size; i++)
il.Push_Back(rand.Next(0, 10000));
break;
case D_List<string> sl:
for (int i = 0; i < size; i++)
sl.Push_Back(Gen_rand_string(rand));
break;
default:
for (int i = 0; i < size; i++)
(list as D_List<double>).Push_Back(rand.NextDouble());
}
}
Or you can cast it directly in your code:
public static void GenerateRandomd<T>(D_List<T> list, int size, Random rand)
{
if (list is D_List<int>)
{
for (int i = 0; i < size; i++)
(list as DList<int>).Push_Back(rand.Next(0, 10000)); // cast variable to the DList<int> at each step of the cyclecast
}
else if (list is D_List<string>)
{
for (int i = 0; i < size; i++)
(list is D_List<string>).Push_Back(Gen_rand_string(rand));
}
else
{
for (int i = 0; i < size; i++)
(list is D_List<double>).Push_Back(rand.NextDouble());
}
}
If default scenario implies a different type so you may implement non-generic Push_Back(double value) method for D_List.
i defined the array and the functions but i'm having trouble calling the function, should i call a function using class name or object
public static string PrintArray (int [,] arr)
{
string output = "";
for (int i = 0; i<arr.GetLength(0);i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
output += arr[i,j];
output = output.Substring(0, output.Length)+"/n";
}
return output;
}
public static void Fill(int[,] arr,int min, int max)
{
Random r = new Random();
for (int i = 0; i < arr.GetLength(0); i++)
{
arr[i] = r.Next(min, max);
for (int j = 0; j < arr.GetLength(1); j++)
{
arr[i,j] = r.Next(min, max);
}
}
}
If you have static methods, they must be called using the class name. You would only call from an object if it was an instance (non-static) method, it is not possible to call a static method from an instance of an object, or an instance method from a static class name.
In your case, as you have defined static methods, you must reference them in a static way. e.g., if your class was called ArrayHelper
public class ArrayHelper
{
public static string PrintArray (int [,] arr)
{
string output = "";
for (int i = 0; i<arr.GetLength(0);i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
output += arr[i,j];
output = output.Substring(0, output.Length)+"/n";
}
return output;
}
public static void Fill(int[,] arr,int min, int max)
{
Random r = new Random();
for (int i = 0; i < arr.GetLength(0); i++)
{
arr[i] = r.Next(min, max);
for (int j = 0; j < arr.GetLength(1); j++)
{
arr[i,j] = r.Next(min, max);
}
}
}
}
You could use it like so
var array = ...
ArrayHelper.Fill(array, 10, 20);
I don't know how to shuffle 2D array without duplicate elements. Can anyone help me to shuffle a 2D array?
Here is what I have so far:
public class Shuffle2DArray
{
public Shuffle2DArray ()
{
}
public static void Main(string[] args)
{
int[,] a = new int[3, 3] { { 1, 2, 3, }, { 6, 7, 8 }, { 11, 12, 13 } };
Shuffle2DArray shuffle = new Shuffle2DArray ();
shuffle.getshuffle2D (a);
}
void getshuffle2D(int[,] arr)
{
Random ran = new Random ();
for (int i = 0; i < arr.GetLength (0); i++) {
for (int j = 0; j < arr.GetLength (1); j++) {
int m = ran.Next(arr.GetLength (0)-1);
int n = ran.Next(arr.GetLength (1)-1);
int temp = arr[0,j];
arr[i,0] = arr[m,n+1];
arr[m,n] = temp;
Console.Write(arr[i,j]+ "\t");
}
Console.WriteLine();
}
}
}
Well, I would say shuffle the 2d array the same way as you shuffle the 1d array.
For instance, Fisher–Yates shuffle for 1d array is something like this
public static class Utils
{
public static void Swap<T>(ref T a, ref T b) { var temp = a; a = b; b = temp; }
public static void RandomShuffle<T>(this T[] target, Random random = null)
{
if (target.Length < 2) return;
if (random == null) random = new Random();
for (int i = target.Length - 1; i > 0; i--)
{
int j = random.Next(i + 1);
if (i != j) Swap(ref target[i], ref target[j]);
}
}
}
All you need is to realize that having a 2d array
T[,] array
and accessing the element of the array
array[row, column]
that
row = index / columnCount
column = index % columnCount
where
index = [0, array.Lenght - 1] corresponds to the index in 1d array
columnCount = array.GetLength(1)
adding the 2d version function to the class above is trivial
public static class Utils
{
// ...
public static void RandomShuffle<T>(this T[,] target, Random random = null)
{
if (target.Length < 2) return;
if (random == null) random = new Random();
int columnCount = target.GetLength(1);
for (int i = target.Length - 1; i > 0; i--)
{
int j = random.Next(i + 1);
if (i != j) Swap(ref target[i / columnCount, i % columnCount], ref target[j / columnCount, j % columnCount]);
}
}
}
Sample usage:
int[,] a = new int[3, 3] { { 1, 2, 3, }, { 6, 7, 8 }, { 11, 12, 13 } };
a.RandomShuffle();
You need to first order your array by random sequence of numbers. What you are doing now is just changing two random items of 2d array at each iterate thus it may result in duplicate items.
Look at this Sort algorithm for 1d array.
for (int i = 0; i < arr.Length - 1; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i] > arr[j]) // ran.Next(-1,1) == 0 // or any random condition
{
int temp = arr[i];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
As you can see we need 2 loops to sort 1d array. So in order to sort 2d array we need 4 loops.
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(0); j++)
{
for (int k = 0; k < arr.GetLength(1); k++)
{
for (int l = 0; l < arr.GetLength(1); l++)
{
if (arr[i, k] > arr[j, l]) // ran.Next(-1,1) == 0
{
int temp = arr[i, k];
arr[i, k] = arr[j, l];
arr[j, l] = temp;
}
}
}
}
}
Then write another algorithm to print items.
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
Console.Write(arr[i, j] + "\t");
}
Console.WriteLine();
}
This was Sort algorithm. Now if you just change this condition with random one you sort your array by random.
Change if (arr[i, k] > arr[j, l])
To if (ran.Next(-1,1) == 0). this is just randomly true or false.
I cannot get this method to work. It intends to multiply a matrix by a given one. Could someone help me to correct it please?
class Matriz
{
public double[,] structure;
//Other class methods
public void multiplyBy(Matrix m)
{
if (this.structure.GetLength(1) == m.structure.GetLength(0))
{
Matriz resultant = new Matriz(this.structure.GetLength(0), m.structure.GetLength(1));
for (int i = 0; i < this.structure.GetLength(0) - 1; i++)
{
for (int j = 0; j < m.structure.GetLength(1) - 1; j++)
{
resultant.structure[i, j] = 0;
for (int z = 0; z < this.structure.GetLength(1) - 1; z++)
{
resultant.structure[i, j] += this.structure[i, z] * m.structure[z, j];
}
}
}
this.structure= resultant.structure;
}
else
{
Console.WriteLine("Selected matrixs cannot be multiply");
}
}
}
Read this MSDN Magazine article by James McCaffrey and use the code below as an extension method. They use a jagged array which is more convenient and sometimes faster than a 2D array. Change any data[i][j] to data[i,j] to make the code work with a 2D array.
public static double[] MatrixProduct(this double[][] matrixA,
double[] vectorB)
{
int aRows=matrixA.Length; int aCols=matrixA[0].Length;
int bRows=vectorB.Length;
if (aCols!=bRows)
throw new Exception("Non-conformable matrices in MatrixProduct");
double[] result=new double[aRows];
for (int i=0; i<aRows; ++i) // each row of A
for (int k=0; k<aCols; ++k)
result[i]+=matrixA[i][k]*vectorB[k];
return result;
}
public static double[][] MatrixProduct(this double[][] matrixA,
double[][] matrixB)
{
int aRows=matrixA.Length; int aCols=matrixA[0].Length;
int bRows=matrixB.Length; int bCols=matrixB[0].Length;
if (aCols!=bRows)
throw new Exception("Non-conformable matrices in MatrixProduct");
double[][] result=MatrixCreate(aRows, bCols);
for (int i=0; i<aRows; ++i) // each row of A
for (int j=0; j<bCols; ++j) // each col of B
for (int k=0; k<aCols; ++k)
result[i][j]+=matrixA[i][k]*matrixB[k][j];
return result;
}
public static double[][] MatrixCreate(int rows, int cols)
{
// creates a matrix initialized to all 0.0s
// do error checking here?
double[][] result=new double[rows][];
for (int i=0; i<rows; ++i)
result[i]=new double[cols];
// auto init to 0.0
return result;
}
This is the modified version of my method, as far as I've been testing this approach works fine.
public void multiplicarPor(Matriz m)
{
if (this.estructura.GetLength(1) == m.estructura.GetLength(0))
{
Matriz resultante = new Matriz(this.estructura.GetLength(0), m.estructura.GetLength(1));
for (int i = 0; i < this.estructura.GetLength(0); i++)
{
for (int j = 0; j < m.estructura.GetLength(1); j++)
{
resultante.estructura[i, j] = 0;
for (int z = 0; z < this.estructura.GetLength(1); z++)
{
resultante.estructura[i, j] += this.estructura[i, z] * m.estructura[z, j];
}
}
}
this.estructura = resultante.estructura;
}
else
{
Console.WriteLine("No se pueden multiplicar estas matrices");
}
}
public static void Sort2DArray(int[,] matrix)
{
var numb = new int[matrix.GetLength(0) * matrix.GetLength(1)];
int i = 0;
foreach (var n in matrix)
{
numb[i] = n;
i++;
}
Array.Sort(numb);
int k = 0;
for (i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
matrix[i, j] = numb[k];
k++;
}
}
}
I'm curious how can I make this method generic. I wish that it could sort double matrices, string matrices and so on and so forth.
You can use IComparable interface as a generic type T specifier.
See those links
How to Sort 2D Array in C#
How do I sort a two-dimensional array in C#?
http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=151
I have solved it. the method looks like this:
public static void Sort2DArray<T>(T[,] matrix)
{
var numb = new T[matrix.GetLength(0) * matrix.GetLength(1)];
int i = 0;
foreach (var n in matrix)
{
numb[i] = n;
i++;
}
Array.Sort(numb);
int k = 0;
for (i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
matrix[i, j] = numb[k];
k++;
}
}
}