Template list creation C# - c#

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.

Related

Code should not nest more than 3 control flow statements

I have to implement a bingo game and check for line, bingo or nothing for a given input where I get a 3x3 bingo card and next 15 numbers extracted.
I wrote the following function:
static int[,] ReadBingoCard(int rowsNumber, int columnNumber)
{
int[,] card = new int[rowsNumber, columnNumber];
for (int i = 0; i < rowsNumber; i++)
{
string[] array = Console.ReadLine().Split(' ');
for (int j = 0; j < columnNumber; j++)
{
card[i, j] = Convert.ToInt32(array[j]);
}
}
return card;
}
static int[] ReadNumbersExtracted(int numbersExtracted)
{
int[] numbers = new int[numbersExtracted];
for (int i = 0; i < numbersExtracted; i++)
{
numbers[i] = Convert.ToInt32(Console.ReadLine());
}
return numbers;
}
static bool CheckForBingo(int[,] bingoCard, int[] numbers)
{
int numMatchesFound = 0;
for (int row = 0; row < bingoCard.GetLength(0); row++)
{
for (int col = 0; col < bingoCard.GetLength(1); col++)
{
for (int numIndex = 0; numIndex < numbers.Length; numIndex++)
{
if (bingoCard[row, col] == numbers[numIndex])
{
numMatchesFound++;
break;
}
}
}
}
return numMatchesFound == bingoCard.Length;
}
static bool CheckForLine(int[,] bingoCard, int[] numbers)
{
for (int row = 0; row < bingoCard.GetLength(0); row++)
{
int colMatchesInRow = 0;
for (int col = 0; col < bingoCard.GetLength(1); col++)
{
for(int numIndex = 0; numIndex < numbers.Length; numIndex++)
{
if (bingoCard[row, col] != numbers[numIndex])
{
continue;
}
colMatchesInRow++;
break;
}
}
Due to some limitations of sonar analyzer I get the error:
S134 (Error) : Refactor this code to not nest more than 3 control flow statements for CheckForBingo function.
Is there a way to split this function to get rid of this error?
Just use for-each to iterate through your 2d array:
static bool CheckForBingo(int[,] bingoCard, int[] numbers)
{
int numMatchesFound = 0;
foreach (var number in bingoCard)
{
for (int numIndex = 0; numIndex < numbers.Length; numIndex++)
{
if (number == numbers[numIndex])
{
numMatchesFound++;
break;
}
}
}
return numMatchesFound == bingoCard.Length;
}
EDIT:
This is a refactored CheckForLine using a helper method to search for a values in an array
static bool CheckForLine(int[,] bingoCard, int[] numbers)
{
for (int row = 0; row < bingoCard.GetLength(0); row++)
{
int colMatchesInRow = 0;
for (int col = 0; col < bingoCard.GetLength(1); col++)
{
if (IsNumberContainedInArray(bingoCard[row, col],numbers))
{
colMatchesInRow++;
break;
}
}
}
}
}
static bool IsNumberContainedInArray(int numberToCheck, int[] numbers)
{
for (int numIndex = 0; numIndex < numbers.Length; numIndex++)
{
if (numberToCheck == numbers[numIndex])
{
return true;
}
}
return false;
}

How to call static methods in a class

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

How to multiply a matrix in C#?

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

Method for Sorting 2D Matricies, How can i make the method generic?

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++;
}
}
}

Extension method for fill rectangular array in C#

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.

Categories