I am wanting to create multiple arrays of ints(in C#). However they all must have a unique number in the index, which no other array has that number in that index. So let me try show you what I mean:
int[] ints_array = new int[30];
for (int i = 0; i < ints_array.Count(); i++)
ints_array[i] = i;
//create a int array with 30 elems with each value increment by 1
List<int[]> arrayList = new List<int[]>();
for(int i = 0; i < ints_array.Count(); i++)
arrayList.Add(ints_array[i]. //somehow sort the array here randomly so it will be unique
So I am trying to get the arrayList have 30 int[] arrays and each is sorted so no array has the same int in the same index as another.
Example:
arrayList[0] = {5,2,3,4,1,6,7,8,20,21... etc }
arrayList[1] = {1,0,5,2,9,10,29,15,29... etc }
arrayList[2] = {0,28,4,7,29,23,22,17... etc }
So would this possible to sort the array in this unique kind of way? If you need anymore information just ask and ill fill you in :)
Wouldn't it be easier to create the arrays iteratively using an offset pattern?
What I mean is that if you created the first array using 1-30 where 1 is at index 0, the next array could repeat this using 2-30 where 2 is at index 0 and then wrap back to 1 and start counting forward again as soon as you go past 30. It would be an easy and repeatable way to make sure no array shared the same value/index pair.
You can do it like that:
List<int[]> arrayList = new List<int[]>();
Random rnd = new Random();
for (int i = 0; i < ints_array.Length; i++)
{
ints_array = ints_array.OrderBy(x => rnd.Next()).ToArray();
var isDuplicate = arrayList.Any(x => x.SequenceEqual(ints_array));
if (isDuplicate)
{
while (arrayList.Any(x => x.SequenceEqual(ints_array)))
{
ints_array = ints_array.OrderBy(x => rnd.Next()).ToArray();
}
}
arrayList.Add(ints_array);
}
I think, this wouldn't be so efficient for bigger numbers than 30.But in this case it shouldn't be a problem, in my machine it takes 7 milliseconds.
Jesse's idea would be best unless you needed a pure random pattern. In that case I would recommend generating a random number, checking all your previous arrays, and then placing it in an array if it did not match any other arrays current index. Otherwise, generate a new random number until you find a fresh one. Put that into a loop until all your arrays are filled.
Use a matrix (2D-array). It is easier to handle than a list of arrays. Create a random number generator. Make sure to initialize it only once, otherwise random number generator may create bad random numbers, if created in too short time intervals, since the slow PC-clock might not have ticked in between. (The actual time is used as seed value).
private static Random random = new Random();
Create two helper arrays with shuffeled indexes for rows and columns:
const int N = 30;
int[] col = CreateUniqueShuffledValues(N);
int[] row = CreateUniqueShuffledValues(N);
Then create and initialize the matrix by using the shuffeled row and column indexes:
// Create matrix
int[,] matrix = new int[N, N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
matrix[row[i], col[j]] = (i + j) % N;
}
}
The code uses these two helper methods:
private static int[] CreateUniqueShuffledValues(int n)
{
// Create and initialize array with indexes.
int[] array = new int[n];
for (int i = 0; i < n; i++) {
array[i] = i;
}
// Shuffel array using one variant of Fisher–Yates shuffle
// http://en.wikipedia.org/wiki/Fisher-Yates_shuffle#The_modern_algorithm
for (int i = 0; i < n; i++) {
int j = random.Next(i, n);
Swap(array, i, j);
}
return array;
}
private static void Swap(int[] array, int i, int j)
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
int size = 10;
// generate table (no duplicates in rows, no duplicates in columns)
// 0 1 2
// 1 2 0
// 2 0 1
int[,] table = new int[size, size];
for (int y = 0; y < size; y++)
for (int x = 0; x < size; x++)
table[y, x] = (y + x) % size;
// shuffle rows
Random rnd = new Random();
for (int i = 0; i < size; i++)
{
int y1 = rnd.Next(0, size);
int y2 = rnd.Next(0, size);
for (int x = 0; x < size; x++)
{
int tmp = table[y1, x];
table[y1, x] = table[y2, x];
table[y2, x] = tmp;
}
}
// shuffle columns
for (int i = 0; i < size; i++)
{
int x1 = rnd.Next(0, size);
int x2 = rnd.Next(0, size);
for (int y = 0; y < size; y++)
{
int tmp = table[y, x1];
table[y, x1] = table[y, x2];
table[y, x2] = tmp;
}
}
// sample output
for (int y = 0; y < size; y++)
{
for (int x = 0; x < size; x++)
Console.Write("{0} ", table[y, x]);
Console.WriteLine();
}
Related
I can't fill it with numbers to 0 - 15 then shuffle the array, so that's not the solution
I used this code in C but now in c# it doesn't work, for some reason this code let some numbers pass the do while.
Random r = new Random();
bool unique;
int rand_num;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
do
{
unique = true;
rand_num = r.Next(16);
for (int k = 0; k < 4; k++)
{
for (int l = 0; l < 4; l++)
{
if (numbers[k, j] == rand_num)
{
unique = false;
}
}
}
} while (!unique);
numbers[i, j] = rand_num;
}
}
}
If the list of possible numbers is small, as in this case, just create the full list and randomise it first, then take the items in the order they appear. In your case, you can put the randomised numbers into a queue, then dequeue as required.
var r = new Random();
var numberQueue = new Queue<int>(Enumerable.Range(0, 16).OrderBy(n => r.NextDouble()));
var numbers = new int[4, 4];
for (var i = 0; i <= numbers.GetUpperBound(0); i++)
{
for (var j = 0; j <= numbers.GetUpperBound(1); j++)
{
numbers[i, j] = numberQueue.Dequeue();
}
}
I suggest you to use the Fisher-Yates algorithm to generate your non-repeatable sequence of random numbers.
It would be very straight-forward to implement a code to fill in a 2d array with those numbers, then.
List<int> seq = Enumerable.Range(0,16).ToList();
int[,] numbers = new int[4,4];
Random r = new();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int n = r.Next(0, seq.Count);
numbers[i,j] = seq[n];
seq.RemoveAt(n);
}
}
The approach you have taken may end up in continuous looping and take lot of time to complete.
Also checking for value in 2D using nested for loop is not efficient.
You can use HashSet to keep track of unique value. Searching in HashSet is fast.
following is the code approach I suggest.
var hashSet = new HashSet<int>();
var r = new Random();
var arr = new int[4, 4];
for(var i = 0;i<4;i++)
{
for(var j = 0;j<4;j++)
{
// Generate random value between 0 and 16.
var v = r.Next(0, 16);
// Check if the hashSet has the newly generated random value.
while(hashSet.Contains(v))
{
// generate new random value if the hashSet has the earlier generated value.
v = r.Next(0, 16);
}
//Add value to the hashSet.
hashSet.Add(v);
// add value to the 2D array.
arr[i, j] = v;
}
}
I hope this will help solving your issue.
The problem with your current approach is that as you get closer to the end of the array, you have to work harder and harder to get the next random value.
Imagine you roll a die, and each time you want to get a unique value. The first time you roll, any result will be unique. The next time, you have a 1/6 chance of getting a number that has already been obtained. And then a 2/6 chance, etc. and in the end most of your rolls will be non-unique.
In your example, you have 16 places that you want to fill with numbers 0 to 15. This is not a case of randomly generating numbers, but randomly placing them. How do we do this with a deck of cards? We shufle them!
My proposal is that you fill the array with unique sequential values and then shuffle them:
Random random = new Random();
int dim1 = array.GetLength(0);
int dim2 = array.GetLength(1);
int length = dim1 * dim2;
for (int i = 0; i < length; ++i)
{
int x = i / dim1;
int y = i % dim1;
array[x, y] = i; // set the initial values for each cell
}
// shuffle the values randomly
for (int i = 0; i < length; ++i)
{
int x1 = i / dim1;
int y1 = i % dim1;
int randPos = random.Next(i, length);
int x2 = randPos / dim1;
int y2 = randPos % dim1;
int tmp = array[x1, y1];
array[x1, y1] = array[x2, y2];
array[x2, y2] = tmp;
}
The shuffle in this code is based on the shuffle found here
int[,] numbers = new int[4, 4];
Random r = new Random();
bool unique;
int rand_num;
List<int> listRandom = new List<int> { };
for ( int i = 0; i < 4; i++ )
{
for ( int j = 0; j < 4; j++ )
{
do
{
unique = false;
if (!listRandom.Contains( rand_num = r.Next( 0, 16 )))
{
listRandom.Add( rand_num );
numbers[i, j] = rand_num;
unique = true;
}
} while ( !unique );
}
}
I'm trying to fill one dimensional array with random BUT unique numbers (No single number should be same). As I guess I have a logical error in second for loop, but can't get it right.
P.S I'm not looking for a more "complex" solution - all I know at is this time is while,for,if.
P.P.S I know that it's a really beginner's problem and feel sorry for this kind of question.
int[] x = new int[10];
for (int i = 0; i < x.Length; i++)
{
x[i] = r.Next(9);
for (int j = 0; j <i; j++)
{
if (x[i] == x[j]) break;
}
}
for (int i = 0; i < x.Length; i++)
{
Console.WriteLine(x[i);
}
Here is a solution with your code.
int[] x = new int[10];
for (int i = 0; i < x.Length;)
{
bool stop = false;
x[i] = r.Next(9);
for (int j = 0; j <i; j++)
{
if (x[i] == x[j]) {
stop = true;
break;
}
}
if (!stop)
i++;
}
for (int i = 0; i < x.Length; i++)
{
Console.WriteLine(x[i]);
}
A simple trace of the posted code reveals some of the issues. To be specific, on the line…
if (x[i] == x[j]) break;
if the random number is “already” in the array, then simply breaking out of the j loop is going to SKIP the current i value into the x array. This means that whenever a duplicate is found, x[i] is going to be 0 (zero) the default value, then skipped.
The outer i loop is obviously looping through the x int array, this is pretty clear and looks ok. However, the second inner loop can’t really be a for loop… and here’s why… basically you need to find a random int, then loop through the existing ints to see if it already exists. Given this, in theory you could grab the same random number “many” times over before getting a unique one. Therefore, in this scenario… you really have NO idea how many times you will loop around before you find this unique number.
With that said, it may help to “break” your problem down. I am guessing a “method” that returns a “unique” int compared to the existing ints in the x array, may come in handy. Create an endless while loop, inside this loop, we would grab a random number, then loop through the “existing” ints. If the random number is not a duplicate, then we can simply return this value. This is all this method does and it may look something like below.
private static int GetNextInt(Random r, int[] x, int numberOfRandsFound) {
int currentRand;
bool itemAlreadyExist = false;
while (true) {
currentRand = r.Next(RandomNumberSize);
itemAlreadyExist = false;
for (int i = 0; i < numberOfRandsFound; i++) {
if (x[i] == currentRand) {
itemAlreadyExist = true;
break;
}
}
if (!itemAlreadyExist) {
return currentRand;
}
}
}
NOTE: Here would be a good time to describe a possible endless loop in this code…
Currently, the random numbers and the size of the array are the same, however, if the array size is “larger” than the random number spread, then the code above will NEVER exit. Example, if the current x array is set to size 11 and the random numbers is left at 10, then you will never be able to set the x[10] item since ALL possible random numbers are already used. I hope that makes sense.
Once we have the method above… the rest should be fairly straight forward.
static int DataSize;
static int RandomNumberSize;
static void Main(string[] args) {
Random random = new Random();
DataSize = 10;
RandomNumberSize = 10;
int numberOfRandsFound = 0;
int[] ArrayOfInts = new int[DataSize];
int currentRand;
for (int i = 0; i < ArrayOfInts.Length; i++) {
currentRand = GetNextInt(random, ArrayOfInts, numberOfRandsFound);
ArrayOfInts[i] = currentRand;
numberOfRandsFound++;
}
for (int i = 0; i < ArrayOfInts.Length; i++) {
Console.WriteLine(ArrayOfInts[i]);
}
Console.ReadKey();
}
Lastly as other have mentioned, this is much easier with a List<int>…
static int DataSize;
static int RandomNumberSize;
static void Main(string[] args) {
Random random = new Random();
DataSize = 10;
RandomNumberSize = 10;
List<int> listOfInts = new List<int>();
bool stillWorking = true;
int currentRand;
while (stillWorking) {
currentRand = random.Next(RandomNumberSize);
if (!listOfInts.Contains(currentRand)) {
listOfInts.Add(currentRand);
if (listOfInts.Count == DataSize)
stillWorking = false;
}
}
for (int i = 0; i < listOfInts.Count; i++) {
Console.WriteLine(i + " - " + listOfInts[i]);
}
Console.ReadKey();
}
Hope this helps ;-)
The typical solution is to generate the entire potential set in sequence (in this case an array with values from 0 to 9). Then shuffle the sequence.
private static Random rng = new Random();
public static void Shuffle(int[] items)
{
int n = list.Length;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
int temp = items[k];
items[k] = items[n];
items[n] = temp;
}
}
static void Main(string[] args)
{
int[] x = new int[10];
for(int i = 0; i<x.Length; i++)
{
x[i] = i;
}
Shuffle(x);
for(int i = 0; i < x.Length; i++)
{
Console.WritLine(x[i]);
}
}
//alternate version of Main()
static void Main(string[] args)
{
var x = Enumerable.Range(0,10).ToArray();
Shuffle(x);
Console.WriteLine(String.Join("\n", x));
}
You can simply do this:
private void AddUniqueNumber()
{
Random r = new Random();
List<int> uniqueList = new List<int>();
int num = 0, count = 10;
for (int i = 0; i < count; i++)
{
num = r.Next(count);
if (!uniqueList.Contains(num))
uniqueList.Add(num);
}
}
Or:
int[] x = new int[10];
Random r1 = new Random();
int num = 0;
for (int i = 0; i < x.Length; i++)
{
num = r1.Next(10);
x[num] = num;
}
I am practicing with 2D arrays and am making a program that separates a 2D array with random integer values into two separate arrays based on if the values are even or odd.
However, the program seems to be adding additional zeroes to each row in the even and odd arrays. What am I doing wrong?
I think the problem is in the sort() function where I determine the size of the even and odd arrays but I am not sure.
class Program
{
static void Main(string[] args)
{
int[,] arr = new int[10, 10];
// Fills 2D array with random values and prints them out
Random r = new Random();
for (int y = 0; y < arr.GetLength(0); y++)
{
for (int x = 0; x < arr.GetLength(1); x++)
{
arr[y, x] = r.Next(1, 99);
Console.Write(arr[y,x] + " ");
}
Console.WriteLine();
}
Console.WriteLine();
// Function that separates original array into 2 separate ones (even and odd)
sort(arr);
Console.ReadLine();
}
public static void sort(int[,] array)
{
int j1 = 0;
int i1 = 0;
int j2 = 0;
int i2 = 0;
// Increases the size of the even/odd arrays whenever the value of the original array is even/odd respectively
// I think this is where the problem is
for (int y = 0; y < array.GetLength(0); y++)
{
for (int x = 0; x < array.GetLength(1); x++)
{
if (array[y,x] % 2 == 0)
{
i1 += 1;
}
else
{
i2 += 1;
}
}
j1 += 1;
j2 += 1;
}
int[,] evenArr = new int[j1, i1];
int[,] oddArr = new int[j2, i2];
// Sets the values for the even/odd arrays
for (int y = 0; y < array.GetLength(0); y++)
{
for (int x = 0; x < array.GetLength(1); x++)
{
if (array[y, x] % 2 == 0)
{
evenArr[y, x] = array[y, x];
}
else
{
oddArr[y, x] = array[y, x];
}
}
}
// Prints the values for the even array
for (int y = 0; y < evenArr.GetLength(0); y++)
{
for (int x = 0; x < evenArr.GetLength(1); x++)
{
Console.Write(evenArr[y, x] + " ");
}
Console.WriteLine();
}
Console.WriteLine();
// Prints the values for the odd array
for (int y = 0; y < oddArr.GetLength(0); y++)
{
for (int x = 0; x < oddArr.GetLength(1); x++)
{
Console.Write(oddArr[y, x] + " ");
}
Console.WriteLine();
}
}
}
When you initialize your arrays (evenArr = new int[j1, i1], oddArr = new int[j2, i2];) the default values are zero. Since there's an extra zero it means you should check the length and probably reduce it by one.
I have an array with 89395 rows and 100 columns.
float[][] a = Enumerable.Range(0, 89395).Select(i => new float[100]).ToArray();
I wanna get the index of last row from this array and add one row(lastindex+1) to array and insert 100 floats to the new row which are random. Also save the new index (number of new row) into the userid variable.
I wrote the below code in C#.
public float random(int newitemid)
{
a.Length = a.Length+1;
int userid = a.Length;
Random randomvalues = new Random();
float randomnum;
for (int counter = 0; counter < 100; counter++)
{
randomnum = randomvalues.Next(0, 1);
a[counter] = randomnum;
}
return a;
}
You could do this:
public float random(int newitemid)
{
// Create a new array with a bigger length and give it the old arrays values
float[][] b = new float[a.Length + 1][];
for (int i = 0; i < a.Length; i++)
b[i] = a[i];
a = b;
// Add random values to the last entry
int userid = a.Length - 1;
Random randomvalues = new Random();
float randomnum;
a[userid] = new float[100];
for (int counter = 0; counter < 100; counter++)
{
randomnum = (float)randomvalues.NextDouble(); // This creates a random value between 0 and 1
a[userid][counter] = randomnum;
}
return a;
}
However, if you use this method more than once or twice, you really should consider using a list, that's alot more efficient.
So use List<float[]> a instead.
P.S. If you don't use the parameter newitemid, then it's better to remove it from the function I guess.
Edit: I updated the randomnum to actually generate random numbers instead of 0's
I'm trying to write a code that will fill array with unique numbers.
I could write the code separately for 1, 2 and 3 dimensional arrays but number of for cycles grow to "infinity".
this is the code for 2D array:
static void fillArray(int[,] array)
{
Random rand = new Random();
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
array[i, j] = rand.Next(1, 100);
for (int k = 0; k < j; k++)
if (array[i, k] == array[i, j])
j--;
}
}
print_info(array);
}
Is it possible to do something like this for n-dimensional arrays?
My approach is to start with a 1-d array of unique numbers, which you can shuffle, and then slot into appropriate places in your real array.
Here is the main function:
private static void Initialize(Array array)
{
var rank = array.Rank;
var dimensionLengths = new List<int>();
var totalSize = 1;
int[] arrayIndices = new int[rank];
for (var dimension = 0; dimension < rank; dimension++)
{
var upperBound = array.GetLength(dimension);
dimensionLengths.Add(upperBound);
totalSize *= upperBound;
}
var singleArray = new int[totalSize];
for (int i = 0; i < totalSize; i++) singleArray[i] = i;
singleArray = Shuffle(singleArray);
for (var i = 0; i < singleArray.Length; i++)
{
var remainingIndex = i;
for (var dimension = array.Rank - 1; dimension >= 0; dimension--)
{
arrayIndices[dimension] = remainingIndex%dimensionLengths[dimension];
remainingIndex /= dimensionLengths[dimension];
}
// Now, set the appropriate cell in your real array:
array.SetValue(singleArray[i], arrayIndices);
}
}
The key in this example is the array.SetValue(value, params int[] indices) function. By building up the correct list of indices, you can use this function to set an arbitrary cell in your array.
Here is the Shuffle function:
private static int[] Shuffle(int[] singleArray)
{
var random = new Random();
for (int i = singleArray.Length; i > 1; i--)
{
// Pick random element to swap.
int j = random.Next(i); // 0 <= j <= i-1
// Swap.
int tmp = singleArray[j];
singleArray[j] = singleArray[i - 1];
singleArray[i - 1] = tmp;
}
return singleArray;
}
And finally a demonstration of it in use:
var array1 = new int[2,3,5];
Initialize(array1);
var array2 = new int[2,2,3,4];
Initialize(array2);
My strategy assigns sequential numbers to the original 1-d array to ensure uniqueness, but you can adopt a different strategy for this as you see fit.
You can use Rank property to get the total number of dimentions in your array
To insert use SetValue method
In the first two for loops you are analysing the array properly (i and j go from the start to the end of the corresponding dimension). The problem comes in the most internal part where you introduce a "correction" which actually provokes an endless loop for j.
First iteration:
- First loop: i = 0;
- Second loop: j = 0;
- Third loop: j = -1
Second iteration
- First loop: i = 0;
- Second loop: j = 0;
- Third loop: j = -1
. etc., etc.
(I start my analysis in the moment when the internal loop is used for the first time. Also bear in mind that the exact behaviour cannot be predicted as far as random numbers are involved. But the idea is that you are making the j counter back over and over by following an arbitrary rule).
What you want to accomplish exactly? What is this last correction (the one provoking the endless loop) meant to do?
If the only thing you intend to do is checking the previously stored values, you have to rely on a different variable (j2, for example) which will not affect any of the loops above:
int j2 = j;
for (int k = 0; k < j2; k++)
if (array[i, k] == array[i, j2])
j2--;