7

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
SwissCodeMen
  • 4,222
  • 8
  • 24
  • 34
Reginwaldt Led
  • 369
  • 3
  • 9
  • 19
  • 2
    Uniqueness isn't a property of randomness. "Random" means that the number isn't deterministic. What you're asking is that the number is determined by preceding state. – David May 03 '15 at 14:26
  • Put the numbers 1 to 49 in a list Then pick one randomly and remove it after you do, repeat until you ahve enough.. Or shufffle them and pick the first six. As soon as you say random and unique, random is in the bin... – Tony Hopkinson May 03 '15 at 14:27

11 Answers11

25

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);
}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 2
    Why the downvote? If you don't explain what it is that you think is wrong, it can't improve the answer. – Guffa May 03 '15 at 14:33
  • I didn't downvote your answer, but your first solution seems to be a bit of a mess. While it will work, I think it's better to change the for loop to the while loop like in [my answer.](http://stackoverflow.com/a/30014963/3094533) – Zohar Peled May 03 '15 at 14:37
  • @ZoharPeled: That is just two different approaches. Neither is better than the other. – Guffa May 03 '15 at 14:40
  • @Guffa I disagree. I see no good reason of nesting the while loop in the for loop. In this case I think that performance-wise both our suggestions will probably be equivalent, But I think having just the while loop is more readable. – Zohar Peled May 03 '15 at 14:43
  • @ZoharPeled: Then you should consider separation of concerns. In my approach there is one loop that keeps track of the number of items to create, and one that makes sure that there are no duplicates. In your code you have mixed these two concerns together. – Guffa May 03 '15 at 14:49
  • @Guffa, having an if to take care of uniqueness, and the loop to take care of the count is still pretty much separated to my opinion. Also, my approach condenses the same meaning into a smaller code. – Zohar Peled May 03 '15 at 14:58
  • @ZoharPeled: They are not really separated, as the if statement relies on the loop for making another attempt to create a number. – Guffa May 03 '15 at 15:10
  • @Guffa: I guess we can just agree to disagree on that one. – Zohar Peled May 03 '15 at 15:14
  • 1
    @ZoharPeled: Try to refactor out the part of the code that creates a number that's not used yet into a function, and you should see what I mean. – Guffa May 03 '15 at 15:19
  • @Guffa I see what you mean, but I still disagree. this is not some complicated data manipulation that deserves it's own function, it's just a simple random sequence generator. Sometimes sticking to principles just for the sake of the principle makes for a less readable code. This is my opinion, I understand and respect the fact that yours is different. – Zohar Peled May 03 '15 at 15:39
  • @ZoharPeled: I didn't say that it should have it's own function, that was just a way to demonstrate how separation of concerns work. I was just trying to explain why the code looks the way that it does, so that you could see that it's not "a bit of a mess". – Guffa May 03 '15 at 15:43
  • @Guffa I give a vote for your answer but here need to some changes on code and the 1st example is throwing an exception on some cases so I add my comment on the answer please allow it – Adnan Ahmed Ansari Mar 18 '19 at 16:48
10
listNumbers.AddRange(Enumerable.Range(1, 48)
                               .OrderBy(i => rand.Next())
                               .Take(6))
  • Shuffling by ordering on a random number is not a very good method, you should use a Fisher-Yates shuffle instead. It happens to work in this case, as LINQ caches the values that it gets from the predicate, but for other implementations of sorting it won't work properly. – Guffa May 03 '15 at 14:32
4

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();
}
Sathish
  • 2,029
  • 15
  • 13
1

Make it a while loop and add the integers to a hashset. Stop the loop when you have six integers.

idstam
  • 2,848
  • 1
  • 21
  • 30
  • That's an interesting idea, but there is no good way to get the values out of the hash set. The order of the items in the hash set is not defined, so you might get them in an order that depends on the value, not on the order that they were added. – Guffa May 03 '15 at 14:36
  • Add every number to the return list as they are added to the hash if the generated order is important. – idstam May 03 '15 at 17:25
  • The order is definitely important. If the items are rearranged based on the value, then the list is not random any more. Just adding the numbers to the list would mean that the list could contain duplicates. You would need to check if the number exists in the hash set to determine if it should be added to the list or not. – Guffa May 03 '15 at 17:39
  • Yes, when you add them to the hash you get a true/false to indicate if the add succeeded. No need to look in the hash. – idstam May 03 '15 at 17:52
  • Right, you could check it that way, I didn't think of that. :) – Guffa May 03 '15 at 20:08
  • Thinking in terms of time complexicity, HashSet is far better than using 2 nested loops. Checking for previous numbers in a list in do-while loop is O(n) which is wrapped in for loop that results in O(n^2) where with HashSet its O(n). Yes it doesnt keeps the order but is the order a critical characteristic? – Yawar Murtaza Jan 01 '19 at 18:39
1

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)
Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
1

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;
}
BSG
  • 2,084
  • 14
  • 19
0

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--;
}
mephisto123
  • 1,400
  • 13
  • 38
0

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

Anton Belev
  • 11,963
  • 22
  • 70
  • 111
-1

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**);
Liam
  • 27,717
  • 28
  • 128
  • 190
Kumar K
  • 1
  • 1
-1
   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());
        }
    }
}
mr.mdo
  • 26
  • 5