2

I would like to generate 6 numbers inside an array and at the same time, having it compared so it will not be the same or no repeating numbers. For example, I want to generate 1-2-3-4-5-6 in any order, and most importantly without repeating. So what I thought is to compare current array in generated array one by one and if the number repeats, it will re-run the method and randomize a number again so it will avoid repeating of numbers.

Here is my code:

import javax.swing.*;
public class NonRepeat
{
    public static void main(String args[])
    {
        int Array[] = new int [6];
        int login = Integer.parseInt(JOptionPane.showInputDialog("ASD"));
        while(login != 0)
        {
            String output="";

            for(int index = 0; index<6; index++)
            {
                Array[index] = numGen();

                for(int loop = 0; loop <6 ; loop++)
                {
                    if(Array[index] == Array[loop])
                    {
                        Array[index] = numGen();
                    }
                }


            }

            for(int index = 0; index<6; index++)
            {
                output += Array[index] + " ";
            }


            JOptionPane.showMessageDialog(null, output);

        }



    }

    public static int numGen()
    {
        int random = (int)(1+Math.random()*6);
        return random;
    }
}

I've been thinking it for 2 hours and still cant generate 6 numbers without repeating. Hope my question will be answered.

Btw, Im new in codes so please I just want to compare it using for loop or while loop and if else.

Darsh
  • 27
  • 8
lazygeniusLANZ
  • 21
  • 1
  • 2
  • 6
  • My first thought on this is that if you want real random numbers, you should allow for repetition. If you generate a random number and then check for clauses, discard it and, say, generate another random number, the resulting array will not contain completely random numbers. – Eric Tobias Jan 22 '14 at 12:40
  • 1
    You could add the generated numbers in a `Set` (which automatically removes duplicates), until the `size()` of the `Set` is `6`, and then convert the `Set` to an array using `toArray()`. – sp00m Jan 22 '14 at 12:41
  • @EricTobias what do you mean check for clauses? – lazygeniusLANZ Jan 22 '14 at 12:58
  • @sp00m I dont know what is that Set thing. Im sorry. – lazygeniusLANZ Jan 22 '14 at 12:58
  • A clause is a logical statement. So checking whether your data structure already contains the same random number would be a clause. – Eric Tobias Jan 22 '14 at 13:02
  • @lazygeniusLANZ It's a subtype of `Collection`, just like a `List`. Typical implementation is `HashSet`: `Set set = new HashSet();`. See the [javadoc](http://docs.oracle.com/javase/7/docs/api/java/util/Set.html). – sp00m Jan 22 '14 at 13:12
  • @EricTobias So Im checking the arrays one by one? – lazygeniusLANZ Jan 22 '14 at 13:17
  • possible duplicate of [Java generating non-repeating random numbers](http://stackoverflow.com/questions/16000196/java-generating-non-repeating-random-numbers) – mmmmmm Jan 22 '14 at 13:36
  • No you should not. To be as random as it gets, without fiddling with it, generate your random array, check if it contains random numbers. If so, discard, generate a completely new array. But this is flawed in regard to execution time. TacticalCoder's answer is your best bet. Understanding data structures such as `Collections` is one of the first steps towards better understanding OO programming. I'd suggest you give it a try! :) – Eric Tobias Jan 23 '14 at 07:02

7 Answers7

8

You can generate numbers from, say, 1 to 6 (see below for another solution) then do a Collections.shuffle to shuffle your numbers.

    final List<Integer> l = new ArrayList<Integer>();
    for (int j = 1; j < 7; j++ ) {
        l.add( j );
    }
    Collections.shuffle( l );

By doing this you'll end up with a randomized list of numbers from 1 to 6 without having twice the same number.

If we decompose the solution, first you have this, which really just create a list of six numbers:

    final List<Integer> l = new ArrayList<Integer>();
    for (int j = 1; j < 7; j++ ) {
        l.add( j );
    }

So at this point you have the list 1-2-3-4-5-6 you mentioned in your question. You're guaranteed that these numbers are non-repeating.

Then you simply shuffle / randomize that list by swapping each element at least once with another element. This is what the Collections.shuffle method does.

The solutions that you suggested isn't going to be very efficient: depending on how big your list of numbers is and on your range, you may have a very high probability of having duplicate numbers. In that case constantly re-trying to generate a new list will be slow. Moreover any other solution suggesting to check if the list already contains a number to prevent duplicate or to use a set is going to be slow if you have a long list of consecutive number (say a list of 100 000 numbers from 1 to 100 000): you'd constantly be trying to randomly generate numbers which haven't been generated yet and you'd have more and more collisions as your list of numbers grows.

If you do not want to use Collections.shuffle (for example for learning purpose), you may still want to use the same idea: first create your list of numbers by making sure there aren't any duplicates and then do a for loop which randomly swap two elements of your list. You may want to look at the source code of the Collections.shuffle method which does shuffle in a correct manner.

EDIT It's not very clear what the properties of your "random numbers" have to be. If you don't want them incremental from 1 to 6, you could do something like this:

final Random r = new Random();
final List<Integer> l = new ArrayList<Integer>();
for (int j = 0; j < 6; j++ ) {
    final int prev = j == 0 ? 0 : l.get(l.size() - 1);
    l.add( prev + 1 + r.nextInt(42) );
}
Collections.shuffle( l );

Note that by changing r.nextInt(42) to r.nextInt(1) you'll effectively get non-repeating numbers from 1 to 6.

TacticalCoder
  • 6,275
  • 3
  • 31
  • 39
  • i think he is asking for unique random number in your case you are giving him no from 1 to 7 – Indra Yadav Jan 22 '14 at 12:50
  • @IndraYadav: he clearly gave an example with numbers from 1 to 6 but I'll edit my answer to reflect both cases. – TacticalCoder Jan 22 '14 at 12:51
  • @IndraYadav: edited to allow generation of numbers either in sequence or not, using the same "one for loop, one shuffle" solution. – TacticalCoder Jan 22 '14 at 12:59
  • @TacticalCoder I dont know how this code works, but Im trying. Im sorry. But if it will be slow, what if I change 1-6 to 1-42? – lazygeniusLANZ Jan 22 '14 at 13:00
  • @lazygeniusLANZ: generating a list of 42 numbers? It's going to be very fast. Generating a list of 100 000 numbers using the second solution takes 25 milliseconds on my system... The solution I suggested are *O(n)* in complexity and on modern CPUs doing billions of operations per second, it's really fast. Hope it helps. – TacticalCoder Jan 22 '14 at 13:06
  • @TacticalCoder I dont really care if the sequence of numbers 1-6 is in order or not. I just need it to be free from repeated numbers. Btw, I just understand some of the code. Im sorry I only know basics. – lazygeniusLANZ Jan 22 '14 at 13:20
  • @lazygeniusLANZ: then the first solution is only three lines of code. The idea is really simple: first you generate non-repeating, incrementing (consecutive or not, apparently it doesn't matter), numbers. Then you simply shuffle or "randomize" your list of numbers. I'll edit the question a bit more. – TacticalCoder Jan 22 '14 at 13:30
1

You have to check if the number already exist, you could easily do that by putting your numbers in a List, so you have access to the method contains. If you insist on using an array then you could make a loop which checks if the number is already in the array.

Using ArrayList:

ArrayList numbers = new ArrayList();

while(numbers.size() < 6) {
    int random = numGen(); //this is your method to return a random int

    if(!numbers.contains(random))
        numbers.add(random);
}

Using array:

    int[] numbers = new int[6];

    for (int i = 0; i < numbers.length; i++) {
        int random = 0;

        /*
         * This line executes an empty while until numGen returns a number
         * that is not in the array numbers yet, and assigns it to random
         */
        while (contains(numbers, random = numGen()))
            ;


        numbers[i] = random;
    }

And add this method somewhere as its used in the snippet above

private static boolean contains(int[] numbers, int num) {
    for (int i = 0; i < numbers.length; i++) {
        if (numbers[i] == num) {
            return true;
        }
    }
    return false;
}
reveance
  • 126
  • 7
0

Use List instead of array and List#contains to check if number is repeated.

m0skit0
  • 25,268
  • 11
  • 79
  • 127
0

Here is the solution according to your code -

You just need to change the numGen method -

public static int numGen(int Array[])
{

    int random = (int)(1+Math.random()*6);

    for(int loop = 0; loop <Array.length ; loop++)
    {
        if(Array[loop] == random)
        {
            return numGen(Array);
        } 
    }


    return random;
}

Complete code is -

import javax.swing.*;
public class NonRepeat
{
    public static void main(String args[])
    {

        int login = Integer.parseInt(JOptionPane.showInputDialog("ASD"));
        while(login != 0)
        {
            int Array[] = new int [6];
            String output="";

            for(int index = 0; index<6; index++)
            {
                Array[index] = numGen(Array);


            }

            for(int index = 0; index<6; index++)
            {
                output += Array[index] + " ";
            }


            JOptionPane.showMessageDialog(null, output);

        }



    }

    public static int numGen(int Array[])
    {

        int random = (int)(1+Math.random()*6);

        for(int loop = 0; loop <Array.length ; loop++)
        {
            if(Array[loop] == random)
            {
                return numGen(Array);
            } 
        }


        return random;
    }
}
Indra Yadav
  • 600
  • 5
  • 22
  • I dont even know why this is down voted but this really solved and answered my question with the most easiest code which I understand. – lazygeniusLANZ Jan 22 '14 at 13:29
  • Recursion? Seriously? Why? There is no need for recursion. All you need to solve this is initialize an array with the numbers and randomly swapping the elements N times. – EpicPandaForce Jul 02 '14 at 12:35
0

you can use a boolean in a while loop to identify duplicates and regenerate

int[] array = new int[10]; // array of length 10

Random rand = new Random(); 

    for (int i = 0 ; i < array.length ; i ++ ) {

        array[i] = rand.nextInt(20)+1;  // random 1-20

        boolean found = true;

        while (found) { 

        found = false; 
  // if we do not find true throughout the loop it will break (no duplicates)

         int check = array[i]; // check for duplicate 

             for (int j = 0 ; j < i ; j ++) {

                 if ( array[j] == check ) {

                 found = true; // found duplicate                   
                 }
             }          

              if (found) {  
                    array[i] = rand.nextInt(20)+1 ;   // replace    
              }
        }
    }

System.out.println(Arrays.toString(array));
TheCures
  • 11
  • 1
-1

Use List and .contains(Object obj) method. So you can verify if list has the random number add before.

update - based on time you can lost stuck in random loop.

    List<Integer> list = new ArrayList<Integer>();
    int x = 1;
    while(x < 7){

                list.add(x);
                x++;
    }
    Collections.shuffle(list);

    for (Integer number : list) {
        System.out.println(number);
    }

http://docs.oracle.com/javase/7/docs/api/java/util/List.html#contains(java.lang.Object)

xild
  • 187
  • 8
  • 1
    The thing about randomness is that it is random! Your while might not terminate in your lifetime. While improbable, it is possible. I would avoid this practice and recommend writing code where the time complexity can be calculated with certainty. – Eric Tobias Jan 22 '14 at 13:04
  • You're right and this why shuffle is a cool thing to do. If you think in a big cenario this is bad. I just posted a different example for our mate ;) – xild Jan 22 '14 at 13:30
-1

You may use java.util.Random. And please specify if you want any random number or just the number 1,2,3,4,5,6. If you wish random numbers then , this is a basic code:

import java.util.*;
public class randomnumber
{
    public static void main(String[] args)
    {
        Random abc = new Random();
        int[] a = new int[6];
        int limit = 100,c=0;
        int chk = 0;
        boolean y = true;
        for(;c < 6;)
        {
            int x = abc.nextInt(limit+1);
            for(int i = 0;i<a.length;i++)
            {
                if(x==a[i])
                {
                    y=false;
                    break;
                }
            }
            if(y)
            {
                if(c!=0)if(x == (a[c-1]+1))continue;
                a[c]=x;
                c++;
            }
        }

        for (Integer number : a) 
        {
            System.out.println(number);
        }
    }
}

if you don't understand the last for loop , please tell , i will update it.

Darsh
  • 27
  • 8
  • Originally I want to generate numbers from 1-42 but our professors check it by using 1-6 for him to ensure that nothing will repeat. And honestly, I dont understand most of your code. I only know basics. :( – lazygeniusLANZ Jan 22 '14 at 13:14