I want to generate 25 unique random numbers and list them in a console. The numbers should be atleast 10 characters long. Any easy way to do that?
Try building the numbers up as strings, and use a HashSet to ensure they are unique:
Random random = new Random();
HashSet<string> ids = new HashSet<string>();
while (ids.Count < 25)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; ++i)
{
sb.Append(random.Next(10));
}
ids.Add(sb.ToString());
}
Example output:
7895499338
2643703497
0126762624
8623017810
...etc...
The class HashSet is present in .NET 3.5 and newer.
The problem lies a little in "25 unique random". Displaying 25 random numbers is as easy as
Random r = new Random();
for(int i=0; i<25; i++)
Console.WriteLine(r.Next(1,100).ToString());
These are not necessarily unique, though. If you do not want to allow duplicates, you need to store previously generated numbers somehow, and roll again if you hit an old one.
Be aware that you change the probability distribution of your generated numbers this way.
Edit: I've just noticed that these numbers should be ten characters long. Since 9,999,999,999 exceeds Int32.MaxValue, I'd suggest using Math.Floor(r.NextDouble() * 10000000000 + 1000000000) instead of r.Next(1,100).
Since your numbers are that long, you should not need to worry about duplicates. They are very very unlikely.
There is a big different between Randomness and Uniqueness.
So if you need really unique numbers you have to make sure that you save somewhere all already created numbers and check if your newly created one isn't within this list or you have to provide some algorithm that ensures that a given number can't created twice.
To get the second part to work you mostly take the date/time of the creation moment, cause the current date/time pair is unique forever. The only problem is how many creations per (milli)second do you have and how many digits are available to store your unique number.
A sample about using 12 digits is made here. Hope this helps.
One simple way is this:
class Test
{
private static void Main()
{
Random rand = new Random();
for (int i = 0; i < 25; ++i)
{
Console.WriteLine(rand.Next(1000000000, int.MaxValue));
}
}
}
This will ensure that the numbers are always 10 characters (digits) long. They will not necessarily be unique however. If you want them to definitely be unique, you'll have to do something like this:
class Test
{
private static void Main()
{
Random rand = new Random();
var generatedSoFar = new HashSet<int>();
for (int i = 0; i < 25; ++i)
{
int newRand;
do
{
newRand = rand.Next(1000000000, int.MaxValue);
} while (generatedSoFar.Contains(newRand)); // generate a new random number until we get to one we haven't generated before
generatedSoFar.Add(newRand);
Console.WriteLine(newRand);
}
}
}
If you want to be able to have more than ten digits, you generate the number of digits randomly between 10 and your max number of digits. Then generate each digit (or group of digits) randomly in a StringBuilder or List. You can use the same HashSet method I used above to ensure uniqueness.
Random rnd = new Random(table);
for(int i = 0; i < 25; ++i) {
Console.WriteLine("{0}", rnd.Next(50, 50+i)
}
Related
I need some help to do my homework. I should write non-duplicate random numbers. I'm able to show random numbers but I don't know about non-duplicate.
Here's my code:
Random r = new Random();
for (int i = 0; i < 40; i++)
{
int temp = r.Next(0, 100);
Console.WriteLine(temp);
}
What do I need to do to generate non-duplicate number?
Note that this answer only deals with (relatively) small, pre-determined sets.
The reason the other (simple) solution is inefficient is this: you want to generate 100 random numbers between 0 and 99. You get to the point where you have generated 90 random numbers, and just need 10 more.
The problem is that you're still generating numbers between 0 and 99 every time, except now your chance of finding a number that hasn't already been generated is 1 in 10. So 9 of every 10 numbers you generate has already been added to the list.
Once you get down to just needing 1 number, your chance of generating the remaining 1 that hasn't already been generated is 1 in 100. So for every 100 numbers you generate, only 1 of them will be the last possible number.
I'm sure this is simplifying things given that the Random class is pseudo-random (i.e. it's an algorithm that appears random), but this does explain your situation and why the other answer will be slower.
An improved solution would be this:
// Add all of the numbers 0 to 100 to a list
var availableNumbers = new List<int>();
for (int i = 0; i < 100; ++i)
{
availableNumbers.Add(i);
}
Random random = new Random();
for (int i = 0; i < 40; ++i)
{
// Choose a random position in the available numbers list
var idx = random.Next(0, availableNumbers.Count);
// Print the number from this position in the list
Console.WriteLine(availableNumbers[idx]);
// Remove the item at this position
availableNumbers.RemoveAt(idx);
}
Because we start with a list of all available numbers, we are able to choose numbers from it at random. Removing items from the available numbers list means that they are not available to be chosen a second time. We no longer have to try many times to find an unused number, as removing them when we select them ensures that all of the numbers in the available numbers list are always only unused numbers.
You may use a HashSet to store the numbers and make sure there are no duplicates. Here's an example:
HashSet<int> numbers = new HashSet<int>();
Random r = new Random();
for (int i = 0; i < 40; i++)
{
int temp;
do
{
temp = r.Next(0, 100);
} while (numbers.Add(temp) == false); // If the `.Add()` method returns false,
// that means the number already exists.
// So, we try to generate another number.
Console.WriteLine(temp);
}
i am developing a mine sweeper game in c# of dimension (8 x 8).The difficulty levels increase/decrease the number of mines on the grid.
I use a random class (with min,max set;) to generate a random cell number.The problem i am facing is ,the random object keeps repeating the same number.I tried to resolve this issue by maintaining a local list where i store the generated unique random numbers.The next time i call Next(), i would check it against the local list ,to see if its already present.If the number is already present i would keep calling Next() until i get a new number which is unique and not present in the list.But this doesnt look in itself a good solution as sometimes it takes painful amount of time to generate a new list.
Any suggestions on this please
Even if you use the same random number generator, repeating values are possible.
One way to avoid this would be to generate a list of possible values and using the random number generated to access a value in this list (using as indice) and reducing this list, as you find places to put mines to.
For 8 X 8 example, you have 64 possible places
List<int> possibleValues = new List<int>();
for (int i = 0; i < 64; i++)
{
possibleValues[i] = i;
}
List<int> result = new List<int>();
Random r = new Random();
int numberOfMines = 50; //say you want to put 50 mines there
for (int i = 0; i < numberOfMines; i++)
{
int indice = r.Next(possibleValues.Count);
int value = possibleValues[indice];
possibleValues.Remove(value);
result.Add(value);
}
It looks like you want a shuffle based on a fixed number of cells (8,8), e.g. a Fisher-Yates shuffle. This would guarantee that any coordinate only appears exactly once (as opposed to repeatedly using Random.Next() where you can draw the same number many times), and the order of appearance of coordinates is randomized.
Initialize an array that contains all the coordinates of your cells, shuffle the array and maintain an index of the next "random" cell, return the cell at the offset of the index and increase the index.
First calculate the number of mines, and empty fields.
Random rand=new Random();
int mines=GetMinesFromDifficulty(...);
int empty=TotalFields-mines;
Then for each field:
for(int y=0;y<height;y++)
for(int x=0;y<height;y++)
{
if(random.Next(mines+empty) < mines))
{
field[x,y]=Mine;
mines--;
}
else
{
field[x,y]=Empty;
empty--;
}
}
Instead of picking slots where the mines should be, loop through the slots and calculate the probability that there should be a mine there. The implementation for this becomes very simple, as you just need a single loop:
bool[] mines = new bool[64];
int cnt = 12;
Random rnd = new Random();
for (int i = 0; i < mines.Length; i++) {
if (rnd.Next(mines.Length - i) < cnt) {
mines[i] = true;
cnt--;
}
}
(Room for improvement: You can exit out of the loop when cnt reaches zero, if you don't need to initialise all slots.)
If your grid is 8x8, and you want to randomly choose an unused cell instead of pulling random numbers until you hit an unused one, then keep track of the number of unused cells. Say 8 have been used, leaving 55 unused. Then generate a random number between 0 and 54. You would then have to count through, and find the nth empty cell.
It would probably be easier to think of the problem in a more linear way. Instead of say a 2D array... Squares[8][8] think of it as a single dimension array Squares[64].
At this point you generate a number between 0-63 for your random mine placement. If say the value is 10 you could store for later to offset subsequent numbers. You can reduce your range now from 0-62, if you pulled out the value 16 you would want to add +1 for each value you'd already pulled out underneath it (so actually use 17 in this case, but square 10 has been excluded from our set).
Without seeing any code it's kind of hard to get the gist of things, but from what I can tell you have the following:
A multi-dimensional array [8][8] for the grid layout of the game, you're now trying to randomly place mines?
You'll need to keep one instance of Random for generating the numbers, else you will get the same number over and over again. Something like this
private readonly Random randomNumber = new Random();
for(int i = 0; i < 10; i++)
{
Console.WriteLine(this.randomNumber.Next(1, 10));
}
This will then generate 10 random numbers, each one different.
This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 8 years ago.
I am using Random to generate a sequence of random number. I am constructing the random object just once and then inside the loop generating the random values (300 of them). The problem is that once I get all the values and do a sort on them I realize that some of them are equal and/or sequential: I am generating numbers from 0 to 50000.
This is my script:
Random rnd = new Random();
for (int n=0; n < 300; n++)
{
int RndNumber = rnd.Next(0, 50000);
System.Threading.Thread.Sleep(3);
}
Can someone have a clue on why this is happening, and how can I improve this to make it more random?
So this is the birthday paradox*. When you draw 300 numbers from 50000 the approximate probability that at least two of them are equal is
p(300) = 1 - exp(-300 * 300 / (2 * 50000))
= 0.59
(I could work out the exact probability but I'm lazy!.)
So, chances are more likely than not that you'll have a collision. Sequential is even more likely (now you don't need a collision, you just need n - 1 and n or n and n + 1 to be hit for some n).
Random is fickle.
*: In case you're not familiar with it, it says that if you have twenty-three people in a room, it is more likely than not that at least two people in the room share the same birthday.
!: Okay, I worked it out. It's 0.5953830515549951746819986449....
Research:
If you use the constructor without parameters new Random() the seed is depending on the current servertime.
Random(): "Initializes a new instance of the Random class, using a time-dependent"
http://msdn.microsoft.com/en-us/library/system.random.aspx
So, if I try it like this:
for(int i = 0; i < 1000; i++)
{
Random ran = new Random();
Console.WriteLine(ran.Next(50001));
}
I only get 3 different numbers about 300 times within a thousand calls! Not that random...
Setting the seed in the constructor new Random(0) returns a fix serie of numbers.
e.g. new Random(0).Next(50) always! returns 36. Try it yourself, if you don't trust me;
What we need for "real" random numbers is a changing seed, that's independent of time.
I'm using Hashcode of changing values:
e.g. Guid.NewGuid().GetHashCode() or DateTime.Now.GetHashCode()
Result:
Random ran = new Random(Guid.NewGuid().GetHashCode());
for(int i = 0; i < 1000; i++)
{
Console.WriteLine(ran.Next(50001));
}
or (for better performance):
for(int i = 0; i < 1000; i++)
{
int val = Guid.NewGuid().GetHashCode() % 50001;
val = val > 0 ? val : -val;
Console.WriteLine(val);
}
PS: The maximum of the Next(max)-method is always max - 1;
-> ran.Next(11) can return 0,1,2,...,8,9,10. Not 11!
As an explanation of why you're seeing the occasional duplicate, Jason's answer is right on.
If what you want is 300 distinct random numbers, what about something like this?
static IEnumerable<int> GetRandoms(int min, int max)
{
var rand = new Random();
while (true)
{
yield return rand.Next(min, max);
}
}
var distinctRandoms = GetRandoms(0, 50000).Distinct().Take(300);
I had a lot of issues with randomizing lists. I am talking about a list of 200 elements, where I want to shuffle the list. Don't get me wrong, I read a lot of examples, and on first glance there are pretty nice things, like this:
Randomize a List<T>
But in my experience, at least on a fast machine, this is basically worthless. The shuffling works so fast that there is NOT a MS delay between two calls to Random.NEXT() which results in not nearly random behaviour.
I am NOT talking about super secure stuff, just a basic game random. I know I can add a delay of 1 MS, but this means "wasting" 200 MS just to randomize a list.
Now I found this approach: http://www.codinghorror.com/blog/2007/12/shuffling.html
It looks nice, using GUIDs to sort. BUT aren't they created the same way? Lets step it up a notch, lets assume I want to create 1000 numbers, between 0 - 5. This code is basically useless:
var resultA = new List<int>();
for (int i = 0; i < 1000; i++)
{
resultA.Add(new Random().Next(5));
}
var resultB = new List<int>();
for (int i = 0; i < 1000; i++)
{
resultB.Add(new Random().Next(5));
Thread.Sleep(1);
}
A does not work at all, at least not im my environment in Windows Phone 7. B is fine, but it takes a second, which is also stupid. Any comments or thoughts, it can't be that hard to create a random list of integers :-)
Don't keep initializing a new instance of Random; make just one and continually reference it.
var random = new Random();
var resultA = new List<int>();
for (int i = 0; i < 1000; i++)
{
resultA.Add(random.Next(5));
}
You are correct that repeatedly creating new instances of Random within the same "timestamp" will result in the same seed; but calling .Next on an instance of Random "advances" the seed so that the next number you retrieve is (most likely) different.
This is also covered in the documentation on Random:
... because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers.
...
This problem can be avoided by creating a single Random object rather than multiple ones.
You need to keep hold of the same instance of Random.
var random = new Random();
var resultA = new List<int>();
for (int i = 0; i < 1000; i++)
{
resultA.Add(random.Next(5));
}
var resultB = new List<int>();
for (int i = 0; i < 1000; i++)
{
resultB.Add(random.Next(5));
Thread.Sleep(1);
}
This is because when Random initializes it uses the system clock to get a point in time. When you call next it can use the difference in time to get the next number. If you keep initializing a Random object you will keep getting the same number most of the time.
The shuffling works so fast that there is NOT a MS delay between two calls to Random.NEXT() which results in not nearly random behaviour.
What makes you think that there needs to be a ms delay between two calls to Random.Next?
Your bog standard random number generator is going to take some initial seed (say the system clock) and then repeatedly some algorithm to that seed to produce a sequence of numbers that appears to be random. Most of these algorithms don't take the clock as an input other than for the seed and so it doesn't matter how quickly two consecutive calls are executed.
The reason your code fails is because you keep instantiating a new random number generator on each iteration. This is where the clock can kill you because you end up with the same seed twice. You are not calling Random.Next consecutively on the same random number generator. You are calling Random.Next on a new random number generator on every iteration and sometimes these random number generators are seeded with the same value because you are seeding them by the system clock.
Move the instantiation of the random number generator outside of your loop.
var resultA = new List<int>();
Random rg = new Random();
for (int i = 0; i < 1000; i++) {
resultA.Add(rg.Next(5));
}
Ok so I have a dice throw app...
When I step through the code it functions normally and 'results' contains the correct number of throw results and they appear to be random, when I leave the code to run and do exactly the same thing it produces a set of identical numbers.
I'm sure this is a logical error I cannot see but fiddling with it for hours hasnt improved the situation, so any help is much appriciated. :)
class Dice
{
public int[] Roll(int _throws, int _sides, int _count)
{
Random rnd = new Random();
int[] results = new int[_throws];
// for each set of dice to throw pass data to calculate method
for (int i = 0; i < _throws; i++)
{
int thisThrow = Calculate(_sides, _count);
//add each throw to a new index of array... repeat for every throw
results[i] = thisThrow;
}
return results;
}
private int Calculate(int _sides, int _count)
{
Random rnd = new Random();
int[] result = new int[_count];
int total = 0;
//for each dice to throw put data into result
for (int i = 0; i < _count; i++)
{
result[i] = rnd.Next(1, _sides);
}
//count the values in result
for (int x = 0; x < _count; x++)
{
total = total + result[x];
}
//return total of all dice to Roll method
return total;
}
}
First mistake: Never use multiple instances of Random, use a single instance, and pass that along with the other parameters.
When you create "Random rnd = new Random();" it is seeded by the current time. When you debug your code (which takes time) it will be seeded differently each time.
Create 1 instance of Random, and reference that everywhere.
You're creating a random class every time you need to create a number. Doing this will give you the nutty results.
See here: FROM MSDN
This problem can be avoided by creating a single Random object rather than multiple ones.
To improve performance, create one Random object to generate many random numbers over time, instead of repeatedly creating a new Random objects to generate one random number.
E.g. create a private instance of Random...
In addition to what has been mentioned before...
Use Random for things like dice, card games, choosing random images and so forth. If you ever need to create a random number for security sake, use System.Security.Cryptography.RandomNumberGenerator. This simple example shows creating a random integer.
RandomNumberGenerator gen = RandomNumberGenerator.Create();
byte[] myBytes = new byte[4];
gen.GetBytes(myBytes);
int myValue = (BitConverter.ToInt32(myBytes, 0));
DO NOT use this unless you have a security need. The performance is less than that of the Random class. I suppose you could use this to seed Random but that might be overkill.
EDIT: It occurred to me that I had never tested this. A quick performance test showed the following:
1,000,000 random numbers:
RandomNumberGenerator: 2.6 seconds
Random: .015 seconds.
So Random is about 150 times faster.
Give the constructor Random a seed. That's the problem.
http://msdn.microsoft.com/en-us/library/aa329890%28VS.71%29.aspx
Random r = new Random(DateTime.Now.Millisecond);