i'm code:
Random rand = new Random();
int[] arr = new int[4];
for (int i = 0; i < 4; i++)
{
for (int k = 0; k < 4; k++)
{
int rad = rand.Next(1, 5);
if (arr[k] != rad)
arr[i] = rad;
}
}
for (int i = 0; i < 4; i++)
MessageBox.Show(arr[i].ToString());
I wanna production numbers from 1 to 4 am and unequal with each other.
tnx.
Think it the other way round:
instead of:
generating a number and then check it if it is not duplicate
you make it such that:
you already have a set of non-duplicate numbers, then you take it
one-by-one - removing the possibilities of duplicates.
Something like this will do:
List<int> list = Enumerable.Range(1, 4).ToList();
List<int> rndList = new List<int>();
Random rnd = new Random();
int no = 0;
for (int i = 0; i < 4; ++i) {
no = rnd.Next(0, list.Count);
rndList.Add(list[no]);
list.Remove(list[no]);
}
The result is in your rndList.
This way, no duplicate will occur.
Create an array with unique elements and then shuffle it, like in the code below, it will shuffle an array in uniformly random order it uses Fisher-Yates shuffle algorithm:
int N = 20;
var theArray = new int[N];
for (int i = 0; i < N; i++)
theArray[i] = i;
Shuffle(theArray);
public static void Shuffle(int[] a) {
if (a == null) throw new ArgumentNullException("Array is null");
int n = a.Length;
var theRandom = new Random();
for (int i = 0; i < n; i++) {
int r = i + theRandom.Next(n-i); // between i and n-1
int temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
Explanation and template version of algorithm could be found in this post with nice answer from Jon Skeet.
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
T[] elements = source.ToArray();
// Note i > 0 to avoid final pointless iteration
for (int i = elements.Length-1; i > 0; i--)
{
// Swap element "i" with a random earlier element it (or itself)
int swapIndex = rng.Next(i + 1);
T tmp = elements[i];
elements[i] = elements[swapIndex];
elements[swapIndex] = tmp;
}
// Lazily yield (avoiding aliasing issues etc)
foreach (T element in elements)
{
yield return element;
}
}
Create a list containing the numbers you want, then shuffle them:
var rnd = new Random();
List<int> rndList = Enumerable.Range(1, 4).OrderBy(r => rnd.Next()).ToList();
If you want an array instead of a list:
var rnd = new Random();
int[] rndArray = Enumerable.Range(1, 4).OrderBy(r => rnd.Next()).ToArray();
int[] arr = new int[5];
int i = 0;
while (i < 5)
{
Random rand = new Random();
int a = rand.Next(1,6);
bool alreadyexist = false;
for (int j = 0; j < 5; j++)
{
if (a == arr[j])
{
alreadyexist = true;
}
}
if (alreadyexist == false)
{
arr[i] = a;
i++;
}
}
for (int k = 0; k < 5; k++)
{
MessageBox.Show(arr[k].ToString());
}
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;
}
In my code i have static int method that should return an array of random integers. The problem is when i print an array, only the last number is random int, and other ints are all zeros.
static void Main(string[] args)
{
int a = int.Parse(Console.ReadLine());
int[] array = mtd(a);
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine(array[i]);
}
}
public static int[] mtd(int b)
{
int[] arr = new int[b];
Array.Resize<int>(ref arr, b);
Random rand = new Random();
for (int i = 0; i < arr.Length; i++)
{
arr.SetValue(rand.Next(1, 5), arr.Length - 1);
}
return arr;
}
In the for loop in your method mtd you are always setting the last value of your array arr by using arr.Length - 1. Use i instead:
for (int i = 0; i < arr.Length; i++)
{
arr[i] = rand.Next(1, 5);
}
Or with arr.SetValue:
for (int i = 0; i < arr.Length; i++)
{
arr.SetValue(rand.Next(1, 5), i);
}
Working one :
public static int[] mtd(int b)
{
int[] arr = new int[b];
Random rand = new Random();
for (int i = 0; i < arr.Length; i++)
{
arr.SetValue(rand.Next(1, 5), i);
}
return arr;
}
EDIT : Btw the Array.resize is useless here, you already define the length of your array. ( new int[b] set the length of the array to b )
Your problem was that you never used i, so you just set the value of the last value of your array.
I modified and simplified your code:
public static int[] mtd(int b)
{
int[] arr = new int[b];
Random rand = new Random();
for (int i = 0; i < arr.Length; i++)
arr[i] = rand.Next(1, 5);
return arr;
}
Why this code is throw an exception?
int n = 10;
int[] arr = null;
for (int i = 0; i < n; i++)
{
arr[i] = i * 2;
}
Any one can help?
You have to init your array first int[] arr = new int[n];
int n = 10;
int[] arr = new int[n];
for (int i = 0; i < n; i++)
{
arr[i] = i * 2;
}
You have to initialize an array. This also has to be a fixed size, you cannot expand the lend of an array like you can with a List
you could do:
int n = 10;
int[] arr = new int[n];
for (int i = 0; i < n; i++)
{
arr[i] = i * 2;
}
This will initialise an array of length 10 then populate numbers.
Or with a list:
int n = 10;
List<int> arr = new List<int>();
for (int i = 0; i < n; i++)
{
arr.Add(i * 2);
}
Notice we do not define the length of the list like we do for the array. We then go on and add elements as we want rather than a maximum of n.
You have to declare a new array with defined values instead of null. Like the code below. :).
int n = 10;
int[] arr = new int[n];
for (int i = 0; i < n; i++)
{
arr[i] = i * 2;
}
I have list and I want a short and fast way to make one of its element as the first.
I have in mind to use the code below to select the 10th element and make it first. But looking for a better soln
tempList.Insert(0, tempList[10]);
tempList.RemoveAt(11);
if you don't mind the ordering of the rest, you actually could swap the two items at position 0 and 10, believe it's better than doing insertion and deletion:
var other = tempList[0];
tempList[0]=tempList[10];
tempList[10] = other;
and you can even make this an extension of List for ease of use, something like:
public static void Swap<T>(this List<T> list, int oldIndex, int newIndex)
{
// place the swap code here
}
There are some special cases when you could get better performance (for the sake of simplicity, I'm assuming that the value is always inserted before the position where it was taken from):
class Program
{
const int Loops = 10000;
const int TakeLoops = 10;
const int ItemsCount = 100000;
const int Multiplier = 500;
const int InsertAt = 0;
static void Main(string[] args)
{
var tempList = new List<int>();
var tempDict = new Dictionary<int, int>();
for (int i = 0; i < ItemsCount; i++)
{
tempList.Add(i);
tempDict.Add(i, i);
}
var limit = 0;
Stopwatch
sG = new Stopwatch(),
s1 = new Stopwatch(),
s2 = new Stopwatch();
TimeSpan
t1 = new TimeSpan(),
t2 = new TimeSpan();
for (int k = 0; k < TakeLoops; k++)
{
var takeFrom = k * Multiplier + InsertAt;
s1.Restart();
for (int i = 0; i < Loops; i++)
{
tempList.Insert(InsertAt, tempList[takeFrom]);
tempList.RemoveAt(takeFrom + 1);
}
s1.Stop();
t1 += s1.Elapsed;
s2.Restart();
for (int i = 0; i < Loops; i++)
{
var e = tempDict[takeFrom];
for (int j = takeFrom - InsertAt; j > InsertAt; j--)
{
tempDict[InsertAt + j] = tempDict[InsertAt + j - 1];
}
tempDict[InsertAt] = e;
}
s2.Stop();
t2 += s2.Elapsed;
if (s2.Elapsed > s1.Elapsed || limit == 0)
limit = takeFrom;
}
sG.Start();
for (int k = 0; k < TakeLoops; k++)
{
var takeFrom = k * Multiplier + InsertAt;
if (takeFrom >= limit)
{
for (int i = 0; i < Loops; i++)
{
tempList.Insert(InsertAt, tempList[takeFrom]);
tempList.RemoveAt(takeFrom + 1);
}
}
else
{
for (int i = 0; i < Loops; i++)
{
var e = tempDict[takeFrom];
for (int j = takeFrom - InsertAt; j > InsertAt; j--)
{
tempDict[InsertAt + j] = tempDict[InsertAt + j - 1];
}
tempDict[InsertAt] = e;
}
}
}
sG.Stop();
Console.WriteLine("List: {0}", t1);
Console.WriteLine("Dictionary: {0}", t2);
Console.WriteLine("Optimized: {0}", sG.Elapsed);
/***************************
List: 00:00:11.9061505
Dictionary: 00:00:08.9502043
Optimized: 00:00:08.2504321
****************************/
}
}
In the example above, a Dictionary<int,int> is being used to store the index of each element. You will get better results if the gap between insertAt and takeFrom is smaller. As this interval increases, the performance will degrade. I guess you might want to evaluate this gap and take the optimal branch based on it's value.