How to make this code work without repeating the numbers? [duplicate] - c#

This question already has answers here:
Randomize a List<T>
(28 answers)
Closed 9 years ago.
I need to print numbers from 1 to 50 in random order without repeating
it .
static void Main(string[] args)
{
ArrayList r = new ArrayList();
Random ran = new Random();
for (int i = 0; i < 50; i++)
{
r.Add(ran.Next(1,51));
}
for (int i = 0; i < 50; i++)
Console.WriteLine(r[i]);
Console.ReadKey();
}

What you want here is the Fisher Yates Shuffle
Here is the algorithm as implemented by Jeff Atwood
cards = Enumerable.Range(1, 50).ToList();
for (int i = cards.Count - 1; i > 0; i--)
{
int n = ran.Next(i + 1);
int temp = cards[i];
cards[i] = cards[n];
cards[n] = temp;
}

If you don't want to repeat the numbers between 1 and 50, your best bet is to populate a list with the numbers 1 to 50 and then shuffle the contents. There's a good post on shuffling here:
Randomize a List<T>

All you need to do is this check if the number already exists in the list and if so get another one:
static void Main(string[] args)
{
ArrayList r = new ArrayList();
Random ran = new Random();
int num = 0;
for (int i = 0; i < 50; i++)
{
do { num = ran.Next(1, 51); } while (r.Contains(num));
r.Add(num);
}
for (int i = 0; i < 50; i++)
Console.WriteLine(r[i]);
Console.ReadKey();
}
Edit: This will greatly increase the effeciency, preventing long pauses waiting for a non-collision number:
static void Main(string[] args)
{
List<int> numbers = new List<int>();
Random ran = new Random();
int number = 0;
int min = 1;
int max = 51;
for (int i = 0; i < 50; i++)
{
do
{
number = ran.Next(min, max);
}
while (numbers.Contains(number));
numbers.Add(number);
if (number == min) min++;
if (number == max - 1) max--;
}
for (int i = 0; i < 50; i++)
Console.WriteLine(numbers[i]);
Console.ReadKey();
}

Related

Generate and store 7 random numbers in a array

I made a program to generate 7 random numbers for a lottery using a array. I have generated a random number between 1, 50 but every number shows in order and not on the same line. I would also like to store the auto generated numbers in a array to use. I am not sure how to fix this any help would be appreciated
static void AutoGenrateNumbers()
{
int temp;
int number = 0;
int[] lotto = new int[7];
Random rand = new Random();
for (int i = 0; i <= 50; i++)
{
number = 0;
temp = rand.Next(1, 50);
while (number <= i)
{
if (temp == number)
{
number = 0;
temp = rand.Next(1, 50);
}
else
{
number++;
}
}
temp = number;
Console.WriteLine($"the new lotto winning numbers are:{number}Bonus:{number}");
}
}
Is this what you need?
static void AutoGenrateNumbers()
{
int temp;
int[] lotto = new int[7];
Random rand = new Random();
for (int i = 0; i < 7; i++)
{
temp = rand.Next(1, 50);
lotto[i]= temp;
}
Console.Write($"the new lotto winning numbers are: ");
for (int i = 0; i < 6; i++)
{
Console.Write(lotto[i]+" ");
}
Console.Write($"Bonus:{lotto[6]}");
}
edit: if you want the numbers to be unique:
static void AutoGenrateNumbers()
{
int temp;
int[] lotto = new int[7];
Random rand = new Random();
for (int i = 0; i < 7; i++)
{
do
{
temp = rand.Next(1, 50);
}
while (lotto.Contains(temp));
lotto[i]= temp;
}
Console.Write($"the new lotto winning numbers are: ");
for (int i = 0; i < 6; i++)
{
Console.Write(lotto[i]+" ");
}
Console.Write($"Bonus:{lotto[6]}");
}
A better way to do this is just to generate all the numbers 1-50, shuffle them and then just take 7. Using Jon Skeet's Shuffle extension method found here:
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
T[] elements = source.ToArray();
for (int i = elements.Length - 1; i >= 0; i--)
{
int swapIndex = rng.Next(i + 1);
yield return elements[swapIndex];
elements[swapIndex] = elements[i];
}
}
Now your code is very simple:
static void AutoGenrateNumbers()
{
var lotto = Enumerable.Range(0, 50).Shuffle(new Random()).Take(7);
Console.WriteLine("the new lotto winning numbers are: {0}", string.Join(",", lotto));
}
Fiddle here
Just to add to the existing answers tried to do that in one LINQ statement:
static void Main(string[] args)
{
var rand = new Random();
Enumerable
.Range(1, 7)
.Aggregate(new List<int>(), (x, y) =>
{
var num = rand.Next(1, 51);
while (x.Contains(num))
{
num = rand.Next(1, 51);
}
x.Add(num);
return x;
})
.ForEach(x => Console.Write($"{x} "));
}
The result is something like:
34 24 46 27 11 17 2

How can I fill array with unique random numbers with for-loop&if-statement?

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

Create number for random and non repeat

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

Generating random numbers without repeating.C# [duplicate]

This question already has answers here:
Random number generator with no duplicates
(12 answers)
Closed 2 years ago.
Hi everyone I am trying to generate 6 different numbers on the same line in c# but the problem that i face is some of the numbers are repeating on the same line.Here is my code to
var rand = new Random();
List<int> listNumbers = new List<int>();
int numbers = rand.Next(1,49);
for (int i= 0 ; i < 6 ;i++)
{
listNumbers.Add(numbers);
numbers = rand.Next(1,49);
}
somewhere my output is
17 23 23 31 33 48
Check each number that you generate against the previous numbers:
List<int> listNumbers = new List<int>();
int number;
for (int i = 0; i < 6; i++)
{
do {
number = rand.Next(1, 49);
} while (listNumbers.Contains(number));
listNumbers.Add(number);
}
Another approach is to create a list of possible numbers, and remove numbers that you pick from the list:
List<int> possible = Enumerable.Range(1, 48).ToList();
List<int> listNumbers = new List<int>();
for (int i = 0; i < 6; i++)
{
int index = rand.Next(0, possible.Count);
listNumbers.Add(possible[index]);
possible.RemoveAt(index);
}
listNumbers.AddRange(Enumerable.Range(1, 48)
.OrderBy(i => rand.Next())
.Take(6))
Create a HashSet and generate a unique random numbers
public List<int> GetRandomNumber(int from,int to,int numberOfElement)
{
var random = new Random();
HashSet<int> numbers = new HashSet<int>();
while (numbers.Count < numberOfElement)
{
numbers.Add(random.Next(from, to));
}
return numbers.ToList();
}
Make it a while loop and add the integers to a hashset. Stop the loop when you have six integers.
Instead of using a List, you should use an HashSet. The HashSet<> prohibites multiple identical values. And the Add method returns a bool that indicates if the element was added to the list, Please find the example code below.
public static IEnumerable<int> GetRandomNumbers(int count)
{
HashSet<int> randomNumbers = new HashSet<int>();
for (int i = 0; i < count; i++)
while (!randomNumbers.Add(random.Next()));
return randomNumbers;
}
I've switched your for loop with a do...while loop and set the stopping condition on the list count being smaller then 6.
This might not be the best solution but it's the closest to your original code.
List<int> listNumbers = new List<int>();
do
{
int numbers = rand.Next(1,49);
if(!listNumbers.Contains(number)) {
listNumbers.Add(numbers);
}
} while (listNumbers.Count < 6)
The best approach (CPU time-wise) for such tasks is creating an array of all possible numbers and taking 6 items from it while removing the item you just took from the array.
Example:
const int min = 1, max = 49;
List<int> listNumbers = new List<int>();
int[] numbers = new int[max - min + 1];
int i, len = max - min + 1, number;
for (i = min; i < max; i++) numbers[i - min] = i;
for (i = 0; i < 6; i++) {
number = rand.Next(0, len - 1);
listNumbers.Add(numbers[number]);
if (number != (len - 1)) numbers[number] = numbers[len - 1];
len--;
}
If you are not worried about the min, max, and range then you can use this.
var nexnumber = Guid.NewGuid().GetHashCode();
if (nexnumber < 0)
{
nexnumber *= -1;
}
What you do is to generate a random number each time in the loop. There is a chance of course that the next random number may be the same as the previous one. Just add one check that the current random number is not present in the sequence. You can use a while loop like: while (currentRandom not in listNumbers): generateNewRandomNumber
Paste the below in the class as a new method
public int randomNumber()
{
var random = new Random();
int randomNumber = random.Next(10000, 99999);
return randomNumber;
}
And use the below anywhere in the tests wherever required
var RandNum = randomNumber();
driver.FindElement(By.CssSelector("[class='test']")).SendKeys(**RandNum**);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int[] que = new int[6];
int x, y, z;
Random ran = new Random();
for ( x = 0; x < 6; x++)
{
que[x] = ran.Next(1,49);
for (y = x; y >= 0; y--)
{
if (x == y)
{
continue;
}
if (que[x] == que[y])
{
que[x] = ran.Next(1,49);
y = x;
}
}
}
listBox1.Items.Clear();
for (z = 0; z < 6; z++)
{
listBox1.Items.Add(que[z].ToString());
}
}
}

How to print 20 random numbers? [duplicate]

This question already has answers here:
Non-repetitive random number
(10 answers)
Closed 7 years ago.
I am looking to print 20 random numbers. Is it possible to do this with a for loop; and if it is, how can I do it?
Here is my current code:
int[] randomNum = new int[20];
Random RandomNumber = new Random();
for (int i = 0; i < 20; i++)
{
randomNum[i] = RandomNumber.Next(1, 80);
}
foreach (int j in randomNum)
{
Console.WriteLine("First Number:{0}", j);
Thread.Sleep(200);
}
Just loop the number generation until it generated a new number:
int[] randomNum = new int[20];
Random RandomNumber = new Random();
for (int i = 0; i < 20; i++)
{
int number;
do
{
number = RandomNumber.Next(1, 80);
} while(randomNum.Contains(number));
randomNum[i] = number;
}
foreach (int j in randomNum)
{
Console.WriteLine("First Number:{0}", j);
Thread.Sleep(200);
}
According to your last comment, I would say:
for (int i = 0; i < 20; i++)
{
int num;
do
{
num = RandomNumber.Next(1, 80);
} while (randomNum.Contains(num));
randomNum[i] = num;
}
Why you used array for this? If you want to print random numbers, you can write this.
Random RandomNumber = new Random();
for (int i = 0; i < 20; i++)
{
int randomNum = RandomNumber.Next(1, 80);
Console.WriteLine("Number:{0}", randomNum);
Thread.Sleep(200);
}
you don't need in randomNum. Just do it so:
for (int i = 0; i < 20; i++)
{
Console.WriteLine("First Number:{0}", RandomNumber.Next(1, 80));
}
If you wanna avoid dublication, do so:
List<int> intList = new List();
for (int i = 0; i < 20; i++)
{
int r = RandomNumber.Next(1, 80);
foreach(int s in intList) if(s!=r){
intList.Add(s);
Console.WriteLine("First Number:{0}", RandomNumber.Next(1, 80));
}else i--;
}

Categories