-1

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);
        }
  • Just curious why you have to use for-loop and if-statement here? They are not necessary in the solution IMO. – Cheng Chen Jan 22 '19 at 02:42
  • `r.Next(9)` will only returns numbers in the range 0-8 (one less than the parameter). You need to change your `Next` call to `r.Next(10)` to return numbers from 0-9. – Simply Ged Jan 22 '19 at 04:16
  • To be honest i'm following one of the online coursebook. So I'm practicing working with these specific operators. – Rezi Dzidziguri Jan 22 '19 at 04:42

4 Answers4

0

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]);
    }
FFF
  • 274
  • 1
  • 5
0

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

JohnG
  • 9,259
  • 2
  • 20
  • 29
-1

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));  
} 
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
-1

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;
}
Gauravsa
  • 6,330
  • 2
  • 21
  • 30
  • The OP didn't want a more complex solution, which this is for a beginner :-) – Simply Ged Jan 22 '19 at 02:31
  • It still doesn't work. The first version in the answer will simply not fill the entire array if the rng rolls duplicate numbers, and the 2nd option doesn't check to be sure items are unique at all, and could also leave unassigned elements. – Joel Coehoorn Jan 22 '19 at 15:51