check if 2d array contains value on second spot - c#

I have a 2D array for a lottery I am creating. Basically it's a set of 2 integers:
int[,] coupon = new int[rowAmount, numAmount];
Where rowAmount is the amount of rows, and numAmount is the amount of numbers in that row.
Now I need to select the numbers for each row, however there may not be duplicates of a number within a specific row.
for (int r = 0; r < rowAmount; ++r)
{
for (int n = 0; n < numAmount; ++n)
{
userNum = lotRng.Next(1, numAmount * rngMult);
while (COUPON CONTAINS DUPLICATE NUMBER ON SECOND SPOT )
{
userNum = lotRng.Next(1, numAmount * rngMult);
}
coupon[r, n] = userNum;
}
}
My issue is the while part, I cannot figure out how to check if coupon contains the userNum on the second slot(The numAmount slot). For lists and stuff I used to just do list.Contains() but that doesn't seem to work on here.

Depending on the size of your array is wether it makes sense to optimize performance.
Depending on that one possibility would be to sort the array and use Array.BinarySearch .
You have to sort your array for that.
https://msdn.microsoft.com/en-us/library/2cy9f6wb(v=vs.110).aspx
So you have a number of possibilities to optimize data structure.

Solution with an array of lists is one of my favourites for this. It's very similar to my other with jagged arrays but faster- because List search is most efficient and Linq searches are not.
const int rowAmount = 1000;
const int numAmount=1000;
const int rngMult = 10;
Random lotRng = new Random();
var coupon = new List<int>[rowAmount];
int userNum;
for (int r = 0; r < rowAmount; r++)
{
coupon[r]= new List<int>();
for (int n = 0; n < numAmount; ++n)
{
do userNum = lotRng.Next(1, numAmount * rngMult);
while (coupon[r].Contains(userNum));
coupon[r].Add(userNum);
}
}
Of course it would be also possible to use a list of lists (kind of 2D lists), if necessary.
var couponLoL = new List<List<int>>();
The following quick and dirty way show a possible way of copying a 2D array to a list, but not to recommend here for several reasons (loop, boxing for value types):
var coupon= new int[rowAmount,numAmount];
[..]
do userNum = lotRng.Next(1, numAmount * rngMult);
while (coupon.Cast<int>().ToList().Contains(userNum));
In this special case it makes even less sense, because this would look in the whole 2D array for the double value. But it is worth knowing how to convert from 2D to 1D array (and then in a list).

Solution with 2D jagged arrays: If you want to access rows and columns in C#, a jagged array is very convenient and unless you care very much how effient the array ist stored internally, jagged array are to recommend strongly for that.
Jagged arrays are simply arrays of arrays.
const int rowAmount = 1000;
const int numAmount=1000;
const int rngMult = 10;
int userNum;
Random lotRng = new Random();
var coupon = new int[rowAmount][];
for (int r = 0; r < rowAmount; r++)
{
coupon[r] = new int[numAmount];
for (int n = 0; n < numAmount; ++n)
{
do userNum = lotRng.Next(1, numAmount * rngMult);
while (Array.Exists(coupon[r], x => x == userNum));
coupon[r, n] = userNum;
}
}
The above function Array.Exists works only for 1 dimension what is enough here, and needs no Linq. The same as above with Linq method .Any :
while (coupon[r].Any(x => x == userNum));
If you would have to search in two dimensions for a double value, you would need a loop more again, but still on nested loop level less than without this.
Linq is elegant, but normally not the fastest method (but you would have to handle with very big arrays of multi-million sizes for that to matter).
For other possibilities of using Linq, look for example here:
How to use LINQ with a 2 dimensional array
Another idea would be to make one-dimensional array of size rowAmount*numAmount.
It needs a little bit of thinking, but allows most simple and fastest access of searching.

Solution with loops in an array. Not elegant, but you could refactor the search loops in an own method to look better. But as a second point, in this case a linear search like shown is not a really fast solution either.
Only inner part of the 2 for-loops, not full code (as in other answers by me here):
bool foundDup;
do
{
userNum = lotRng.Next(1, numAmount * rngMult);
foundDup = false;
for (var x = 0; x < coupon.GetLength(1); x++) //Iterate over second dimension only
if (coupon[r, x] == userNum)
{ foundDup = true;
break;
}
} while (foundDup);
coupon[r, n] = userNum;
In the special context of this question, you can optimize the loop:
for (var x = 0; x < n; x++)

As you say in your comment you need to check all n fields vs. your new userNum. You can solve this with the following code:
for (int r = 0; r < rowAmount; ++r)
{
for (int n = 0; n < numAmount; ++n)
{
userNum = lotRng.Next(1, numAmount * rngMult);
for (int x = 0; x < coupon.GetLength(1); x++) //Iterate over your second dimension again
{
while (coupon[r,x] == userNum)
{
userNum = lotRng.Next(1, numAmount * rngMult);
}
}
coupon[r, n] = userNum;
}
}

Related

Getting a 1D array from a 3D array C#

I have a 8x8x3 array with some values. What I want to do is make a list of just the 1D arrays.
What I've got so far:
int[] packIt(int[,,] data, int factor) {
List<int[]> toReturn = new List<int[]>();
int[] test = data[0, 0];
So unless I'm missing something, I make a list of one dimensional arrays and try to fit in the one dimensional array at data[0, 0] (the test is just a placeholder so far). The error I'm getting is "Wrong number of indices", however if I follow the data[0,0,0] (which gives no error) I'll just get the 1 value at the location. I could do it manually, but am just wondering if there is an implementation for the functionality that I'm trying to do, as I will be using it a lot. Thanks a bunch.
You don't need to do anything specific to turn a 3D array into a 1D one; you can just enumerate it:
foreach(var x in multiDim)
...
This will print 1 to 8:
var x = new int[2,2,2];
x[0,0,0] = 1;
x[0,0,1] = 2;
x[0,1,0] = 3;
x[0,1,1] = 4;
x[1,0,0] = 5;
x[1,0,1] = 6;
x[1,1,0] = 7;
x[1,1,1] = 8;
foreach(int i in x)
Console.WriteLine(i);
To this end you can just straight enumerate your array in chunks of whatever:
var out = new List<int[]>();
var arr = new int[chunkSize];
out.Add(arr);
var idx = 0;
foreach(var x in miltiDimArray){
if(idx == chunkSize){
out.Add(arr = new int[chunkSize]);
idx = 0;
}
arr[idx++] = i;
}
Note that I don't try to make the ticks array smaller if the chunk size doesn't divide into the number of elements. idx will have a residual value you can use to work out what to resize the last array by if that is important

Using specific array count

My array max size is 20. If I were to enter data that would be less than 20,how do I get it where my program only counts the used arrays?
for (int i = 0; i < Score.Length; i++)
{
sum = sum + Score[i];
}
average = sum / Score.Length;
If I use this for loop above, it always divides by 20 for the average. I need it to only count the ones I entered, not 20. I would prefer solutions using arrays
If you insist in using arrays, then you must keep track of how many items you added to the array, like:
int[] Score = new int[20];
Random rdn = new Random();
int size=0;
for(int i=0;i<rdn.Next(0,20);i++)
{
Score[i] = rdn.Next();
size++;
}
int sum = 0;
for (int i = 0; i < size; i++)
{
sum = sum + Score[i];
}
double average = sum / size;
A better option is to use the List class that keep track for you of the number of items you add
List<int> Score = new List<int>();
Random rdn = new Random();
for(int i=0;i<rdn.Next(0,20);i++)
{
Score.Add(rdn.Next());
}
int sum = 0;
for (int i = 0; i < Score.Count; i++)
{
sum = sum + Score[i];
}
double average = sum / Score.Count;
And of course, as you didn't say the type of your data you could use other data types, like double, float, long, decimal for both solutions.
That is probably an overkill, but another approach would be to use a SparseVector class of the Math.Numerics package:
Sparse Vector uses two arrays which are usually much shorter than the vector. One array stores all values that are not zero, the other stores their indices.
PM > Install-Package MathNet.Numerics
var vector = SparseVector.Build.SparseOfArray(Score);
var sum = vector.Sum();
Sum() will only go through non-empty elements.
You need to keep track of the record that are != 0, so
int count = 0;
for(int i = 0; i < array.Length; i++)
{
if ( array[i] != 0 )
{
count++;
sum += array[i];
}
}
average = sum / count;
And beware of division by 0 ;)

Storing arrays withing arrays in C#

I'm working on a project right now that requires me to work with and store millions of different doubles. So I figure the most effective way to store all of these values would be in sets of arrays within arrays. but i have no idea how to do this. Plus i have to feed values into the lower level arrays and don't yet know an effective way of doing this.
The below is an attempt at explaining what I'm going for (This is not code, but the website thought it was):
L01 = [1,2,3]
L02 = [3,2,1]
L03 = [2,3,1]
L04 = [1,3,2]
L11 = [L01,L02]
L12 = [L03,L04]
L2 = [L11,L12]
So far I have only come up with this, and you should see why it doesn't work. I'm still pretty new to programming so please explain what I should be doing:
//Stores the weight values attached to an individual neuron
public double[] NeuronWeights = new double[321];
//Stores the NeuronWeights[] for an individual layer with incoming weights
public double[][] LayerWeight = new double[321][];
//Stores all of the LayerWeight[] in the network
public double[][][] TotalWeights = new double[11][][];
public void InitializWeights()
{
for (int i = 0; i < TotalWeights.Length; i++)
{
for(int j = 0; j < LayerWeight.Length; j++)
{
for(int k = 0; k < NeuronWeights.Length; k++)
{
Random r = new Random();
//Creating randome values to fill first level
if (r.Next(0, 2) > 0)
{
NeuronWeights[k] = r.NextDouble() * 2 - 1;
}
else NeuronWeights[k] = 0.0;
}
LayerWeight[j][] = NeuronWeights[];
}
TotalWeights[i][][] = LayerWeight[][];
}
}
}
To add more detail; I'm trying to generate and store 321 doubles ,within the range of (-1, 1), 321 time per "layer". Then do that for all 11 "layers". this information then needs to be called on to assign values for 321 other doubles, 11 times.
Multi-dimensional arrays are not the same as arrays of arrays. Try using List<> instead:
var L01 = new List<int> { 1,2,3 };
var L02 = new List<int> { 3,2,1 };
var L03 = new List<int> { 2,3,1 };
var L04 = new List<int> { 1,3,2 };
var L11 = new List<List<int>> { L01,L02 };
var L12 = new List<List<int>> { L03,L04 };
var L2 = new List<List<List<int>>> { L11,L12 };
But depending on what you are trying to accomplish, maybe you don't need to nest your Lists like that.
It looks like you are trying to create a structure where there are 11 layers, each with 321 neuron weights? That doesn't seem to make sense with your initial goal of storing and working with millions of doubles.
If you simply wanted to store a variable number of layers, each with a variable number of recorded weights, you'd set up something like this:
List<List<double>> weightData = new List<List<double>>();
You can think of a List as a variable-sized array that is expandable as you are going along in your process. So for each Layer, you'd
List<double> currentLayer = new List<double>();
weightData.add(currentLayer);
Then for each weight you wanted to add to the layer you'd do something like:
double neuronWeight = 17.0;
currentLayer.add(neuronWeight);
at the end of the day, weightData will have all your layers and weights within the layers. If you plan to manipulate the data after loading it, you will need to come up with a scheme to reference the various layers and weights, but I'm not sure what your use case for that is.
Good luck!
What about something like this, which uses one multi-dimensional array?
int totalWeightLength = 11;
int layerWeightLength = 321;
int neuronWeights = 321;
double[,,] TotalWeights = new double[totalWeightLength, layerWeightLength, neuronWeights];
void InitializWeights()
{
for (int i = 0; i < totalWeightLength; i++)
{
for (int j = 0; j < layerWeightLength; j++)
{
for (int k = 0; k < neuronWeights; k++)
{
Random r = new Random();
//Creating randome values to fill first level
if (r.Next(0, 2) > 0)
{
TotalWeights[i,j,k] = r.NextDouble() * 2 - 1;
}
else TotalWeights[i,j,k] = 0.0;
}
}
}
}
InitializWeights();
Console.WriteLine(TotalWeights[1,34,23]);
Console.WriteLine(TotalWeights[2,84,123]);
Console.WriteLine(TotalWeights[3,39,24]);
Console.WriteLine(TotalWeights[4,27,36]);

Char in random position

I`m facing with the problem of putting char in random position.
I have a table full of dots and I have to replace 30% of these dots with *
Size: 10x5
I used function Random.
Random rnd = new Random();
if (rnd.Next() % 10 > 3)
Console.Write(". ");
else
Console.Write("* ");
Everything is in 2 loops which hold Length and Height of table (10x5).
But it only makes PROBABILITY of 30% to make * instead of .
It takes good position but every time I start a program there is different amount of *.
It should just have 16 of * (17 - if rounded) every time I start the program
How should I suppose to make 30% always instead of probability?
You have 50 dots. calculate 50*30/100, it becomes 15.
Then generate 15 unique random numbers within range of 0 to 50. those numbers are indexes you have to replace . with *
var indexes = Enumerable.Range(0,50).OrderBy(x => rng.Next()).Take(50*30/100).ToList();
If you are working with 2d index, its fairly easy to convert 1d index into 2d index.
var i = index % 5;
var j = index / 5;
According to what #KonradRudolph said if you don't want to use OrderBy you can check out other ways to shuffle array (or create randomized set) posted here Best way to randomize an array with .NET
Here is more efficient way using Fisher-Yates algorithm that I suggest you to use instead of using OrderBy
var indexes = Enumerable.Range(0, 50).ToArray();
RandomExtensions.Shuffle(rng, indexes);
Write code that does the following:
Declare an array with x * y elements
Populate the entire array with .
Declare a loop with 0.30 * x * y iterations
For each iteration, change a randomly selected element from . to * (you must keep looking until you find one that isn't already a *)
Output the array, x elements per line
Imagine your array to be just 50 elements and forget about the rectangular shape for now. How would you approach that? Declare X dots and 50-X stars, then randomly order them. Like you would randomly order a 1->50 list of numbers.
Now how to randomly order a list of 1->50 numbers? One simple and intuitive way is imagining shuffling cards. Go through the loop and for each position obtain a random number in 1->50. Swap elements chosen (say for i=1 we got random number 7 => swap elements 1 and 7).
Here, you simply need to map this rectangle to those 50 points, which is trivial enough for 2D.
I would randomly select 30% of the possible positions
// create char array
int arrayRows = 5;
int arrayCols = 10;
char[,] arr= new char[arrayRows ,arrayCols];
// populate array with dots
for (int i = 0; i < arrayRows; i++)
{
for (int j = 0; j < arrayCols; j++)
{
arr[i,j] = '.';
}
}
Random rnd = new Random();
int numberOfPossiblePositions = arrayRows * arrayCols;
int k = 0;
while (k < numberOfPossiblePositions * 0.3) {
int position = rnd.Next(numberOfPossiblePositions);
int colIndex = position / 10;
int rowIndex = position % 10;
// if the cell already has * try again
if (arr[rowIndex,colIndex] == '*') {
continue;
}
arr[rowIndex,colIndex] = '*';
k++;
}
Create an array that holds x*y/3 starts and the rest are dots. order by random and iterate through it.
This is the array:
Enumerable.Range(0, count).Select(i => new {Text = "*", Order = rnd.Next() })
.Concat(Enumerable.Range(0, x*y - count)
.Select(i=>new { Text = ".", Order = rnd.Next() }))
.OrderBy(i => i.Order).Select(i=>i.Text).ToList();
And this is the code for iteration:
Random rnd = new Random();
int x = 10;
int y = 5;
int count = x*y/3;
var allPlaces =
Enumerable.Range(0, count).Select(i => new {Text = "*", Order = rnd.Next() })
.Concat(Enumerable.Range(0, x*y - count)
.Select(i=>new { Text = ".", Order = rnd.Next() }))
.OrderBy(i => i.Order).Select(i=>i.Text).ToList();
for (var i = 0; i < x; x++)
{
for (var j = 0; j < y; j++) { Console.Write(allPlaces[i*j + j]); }
Console.WriteLine();
}

finding maximum in a 3d matrix

I have matrix with 3 dimension (n*m*k). I am trying to fined the maximum number for each n and m by searching in k dimension.((I try to find the maximum number in k dimension for each n and m)) and at last i have a 2d matrix (n*m). i have the following code but it is so slow. Is there any new code or any changes to the current code that do this more quickly.
thanks.
my c# code: note: li is the 3 dimension matrix and they are grater or equal to zero.
int[,] array2 = new int[n, m];
int[,] array = new int[n, m];
List<Array> li = new List<Array>();
for(int k = 0; k <'not a specific value, change each time' ; k++)
{
li.Add(array);
%% changing array
} %% so li will became a (n*m*k) matrix
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{
int ma = -2;
int d = 0;
while (d <= k)
{
ma = Math.Max(ma, Convert.ToInt32(li[d].GetValue(i, j)));
d++;
}
array2[i, j] = ma;
}
The biggest performance issue is that you use Array objects as elements of your list. This makes it so that every element access using GetValue boxes the value, i.e. allocates a new tiny object to hold the element value.
Your code will run a lot faster if you replace
List<Array> li = new List<Array>();
with
List<int[,]> li = new List<int[,]>();
and
ma = Math.Max(ma, Convert.ToInt32(li[d].GetValue(i, j)));
with
ma = Math.Max(ma, li[d][i, j];
Since you don't know the 3rd dimension in advance, it is harder to use 3D arrays.
An entirely different approach would be to compute the maximum as you're building the list li. This will help in two ways: 1. You avoid indexing into the list of arrays and 2. as long as m and n aren't too large, you improve locality. That is: the values you're working with are closer together in memory, and more likely to be in the processor cache.
This should do the trick (even though it could be kinda slower than your approach):
// put this at the top of your source file
using System.Linq;
// put this where you calculate the maxima
for(int i = 0; i < array2.GetLength(0); ++i)
for(int j = 0; j < array2.GetLength(1); ++j)
{
array2[i, j] = Convert.ToInt32(li.Max(x => x.GetValue(i, j)));
}
You could use a three-dimensional array like this:
int xRange = 10;
int yRange = 10;
int zRange = 10;
int[, ,] matrix = new int[xRange, yRange, zRange];
// set up some dummy values
for (int x = 0; x < xRange; x++)
for (int y = 0; y < yRange; y++)
for (int z = 0; z < zRange; z++)
matrix[x, y, z] = x * y * z;
// calculate maximum values
int[,] maxValues = new int[xRange, yRange];
/* LINQ version of maximum calculation
for (int x = 0; x < xRange; x++)
for (int y = 0; y < yRange; y++)
maxValues[x, y] = Enumerable.Range(0, zRange).Select(z => matrix[x, y, z]).Max();
*/
// longhand version of maximum calculation
for (int x = 0; x < xRange; x++)
for (int y = 0; y < yRange; y++)
for (int z = 0; z < zRange; z++)
maxValues[x, y] = Math.Max(maxValues[x, y], matrix[x, y, z]);
// display results
for (int x = 0; x < xRange; x++)
{
for (int y = 0; y < yRange; y++)
Console.Write("{0}\t", maxValues[x, y]);
Console.WriteLine();
}
From an algorithm perspective, there's no more efficient way to evaluate the maximum value for fixed n,m for all k. It will take O(n*m*k) operations.
Now, the only way to improve performance is to find improvements in your implementation, particularly in your storage of the 3D matrix.
Using List<Array> is a major area for improvement. You are prone to boxing issues (conversion of primitive types to objects) and making more function calls than are necessary.
Reduce your 3D matrix to an array of primitives:
int[] my3DArray = new int[n * m * l]; // Note I'm using l where you use k
Now index into your array at [i, j, k] using the following offset:
int elementAtIJK = my3DArray[i + (n * j) + (m * n * k)];
If you just use arrays of primitives you should see a definite improvement.
Edit:
In fact, in C# (and several other languages) it's very easy to implement 3D arrays directly, e.g.:
int[,,] my3DArray = new int[n,m,l];
int elementAtIJK = my3DArray[i,j,k];
Which is much simpler than I first described (but at the end of the day is internally translated in the 1D form).
What to do if the 3rd dimension varies in size...
Now, it gets more interesting if the size of the 3rd dimension varies significantly. If it has a known maximum and isn't too big, you can simply set it to the maximum and fill the empty values with zeroes. This is simple and may meet your needs.
However, if the 3rd dimension can be very big, all these extra stored zeroes could waste a lot of valuable space and what you need is a Sparse Matrix representation.
There are different storage mechanisms for sparse matrices. For your purposes, you could consider your 3D array to be a 2D matrix, with (n*m) rows and max(k) columns. As the 3rd dimension varies in length, there are lots of empty spaces in your columns. This is called a sparse row and the standard data storage for this is "Compressed Sparse Row". Again, for performance this can be represented just by three primitive arrays, a data array, a row index array and a column pointer array. There are resources elsewhere on the web that describe the CSR implementation better than I can, but hopefully this will point you in the right direction.

Categories

Resources