2

I want to generate 4 random numbers and they can't have repeated digits.

For instance 4567, (it doesn't have a repeated value like 4557).

I want them to be random.

Is there any way to achieve this?

Ruzihm
  • 19,749
  • 5
  • 36
  • 48
  • 1
    Does `0123` is safe variant? I.e. what is possible values region - from `0123` to `9876`, or from `1023`? – Akina Jan 09 '20 at 19:48
  • 1
    Any random numbers or permutation of 4 specific digits ? – Mayowa Ayodele Jan 09 '20 at 19:50
  • Does this answer your question? [Four digit random number without digit repetition](https://stackoverflow.com/questions/35479416/four-digit-random-number-without-digit-repetition) – Volkan Albayrak Jan 09 '20 at 21:42
  • 1
    @VolkanAlbayrak Not a duplicate, merely related. This one is in a different programming language. – gparyani Jan 09 '20 at 22:25

5 Answers5

1

This will generate 4 digit random numbers with no repeating digits.

It works by generating 4 unique digits in the same fashion that one might shuffle a deck of cards in a computer game. It then simply builds up the four digit number by multiplication and addition.

If the number is less than 1000, then that means a 0 was used and was at the beginning. So just choose another digit to adjust.

    Random r = new Random();
    for (int k = 0; k < 10; k++) {
        int val = gen(r);
        System.out.println(val);
    }

    static int[] base = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    public static int gen(Random r) {
        int val = 0;
        int s=10;
        for (int i = 0; i < 4; i++) {
            int n = r.nextInt(s);
            val = val * 10 + base[n];
            int save = base[n];
            base[n] = base[--s];
            base[s] = save;
        }
        return val < 1000 ? val * 10 + base[r.nextInt(s)] : val;
    }

Here is a more straightforward way of doing it. The philosophy is the same as above. It may not be quite as efficient as the previous due to the shuffling of all the digits.

        // generate four digit numbers that have distinct digits.

        List<Integer> digits = Arrays.asList(0,1,2,3,4,5,6,7,8,9);
        Collections.shuffle(digits);

        // now just use the first four of the shuffled list

        if (digits.get(0) == 0) {
            // for a 4 digit number, first digit can't be zero
            // so choose another.
            digits.set(0, digits.get(4));
        }

        // now use simple arithmetic to create the four digit number.
        int n = 0;
        for (int d : digits.subList(0,4)) {
            n = n * 10 + d;
        }

        System.out.println(n);
WJS
  • 36,363
  • 4
  • 24
  • 39
1

I'm obsessed with streams nowadays. But streams are pretty slow. To show the slowness I wrote following main method. "generateWithLoop" method covers @WJS's answer.

    public static void main(String[] args) {

        long nanoStart = System.nanoTime();
        generateWithStreams();
        long nanoEnd = System.nanoTime();
        System.out.println("Elapsed time with Streams : " + (nanoEnd - nanoStart) + " nano seconds");

        nanoStart = System.nanoTime();
        generateWithLoop();
        nanoEnd = System.nanoTime();
        System.out.println("Elapsed time with Loop : " + (nanoEnd - nanoStart) + " nano seconds");
    }

Console output :

Elapsed time with Streams : 81367089 nano seconds

Elapsed time with Loop : 75093 nano seconds

With stream :

    public static void generateWithStreams() {

        List<Integer> orderedList = getOrderedList();

        for (int i = 0; i < 4; i++) {
            List<Integer> shuffledList = getShuffledList(orderedList);
            System.out.println(get4DigitNumber(shuffledList));
        }

    }

    public static List<Integer> getOrderedList() {
        return IntStream.range(0, 10).boxed().collect(Collectors.toList());
    }

    public static List<Integer> getShuffledList(List<Integer> list) {
        return list.stream().sorted((o1, o2) -> ThreadLocalRandom.current().nextInt(-1, 2)).collect(Collectors.toList());
    }

    public static Integer get4DigitNumber(List<Integer> shuffledList) {
        final Integer LIMIT = shuffledList.get(0).equals(0) ? 5 : 4;
        return shuffledList.stream().limit(LIMIT).reduce(0, (sum, current) -> sum * 10 + current);
    }

With loop :

    public static void generateWithLoop() {
        Random r = new Random();
        for (int k = 0; k < 4; k++) {
            int val = gen(r);
            System.out.println(val);
        }

    }

    static int[] base = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    public static int gen(Random r) {
        int val = 0;
        int s = 10;
        for (int i = 0; i < 4; i++) {
            int n = r.nextInt(s);
            val = val * 10 + base[n];
            int save = base[n];
            base[n] = base[--s];
            base[s] = save;
        }
        return val < 1000 ? val * 10 + base[r.nextInt(s)] : val;
    }
Community
  • 1
  • 1
Volkan Albayrak
  • 329
  • 1
  • 11
0
public static void main(String[] args) {
    List<Integer> list= new ArrayList<>();
    for(int j = 0; j < 10; j++){
        list.add(j);
    }
    Collections.shuffle(list);
    String randomDigit= "";
    for(int j = 0; j < 4; j++){
        randomDigit+= list.get(j).toString();
    }
    System.out.println(randomDigit);
}

This is converting the string to int. But this will work you can use it.

0

Steps:

  1. Create a List that will hold each individual number of the generated 4-digit number
  2. Generate a random number for the units place between 1 and 9, and put it in the list
  3. Create a loop to generate a random number between 0 and 9 for the ten's place until the last place; and each time, put the random number into your list. examine the number for each iteration that is not contained in your list

Eventually the size of the list is now 4; combine these 4 individuals into a String, and convert to Integer.

List<Integer> myNumber = new ArrayList<Integer>();
Random r = new Random();

// Generate a random number between 1 and 9 for units place
myNumber.add(r.nextInt(9) + 1);// adding 1 to avoid 0 in the units place

// Generate a random number between 0 and 9 for 10's and upcoming places
do {
    Integer num = r.nextInt(10);
    // Check the list doesn't contain that number
    if (!myNumber.contains(num)) {
        myNumber.add(num);
    }
}while (myNumber.size() < 4);

StringBuilder numStr = new StringBuilder();
for (int i = 0; i < myNumber.size(); i++)
    numStr.append(myNumber.get(i));

System.out.println(Integer.parseInt(numStr.toString()));
Zain
  • 37,492
  • 7
  • 60
  • 84
0

A solution using stream and Lambdas from Java-8 onwards:

  public static void main(String[] args) {
        Map<String, String> collect = IntStream.rangeClosed(1, 9).boxed()
                .flatMap(x -> IntStream.rangeClosed(0, 9).boxed()
                        .flatMap(y -> IntStream.rangeClosed(0, 9).boxed()
                                .flatMap(z -> IntStream.rangeClosed(0, 9).boxed()
                                        .flatMap(w -> IntStream.rangeClosed(1, 9).boxed().map(s -> s.toString()).filter(e -> noneRepete(x, y, z, w))
                                                .map(k -> x.toString() + y.toString() + z.toString() + w.toString())))))
                .collect(Collectors.toMap(Function.identity(), s -> s, (a, b) -> a));
        collect.keySet().forEach(System.out::println);
    }

    public static boolean noneRepete(Integer a, Integer b, Integer c, Integer d) {
        if (! a.equals(b) && ! a.equals(c) && ! a.equals(d) && a !=0) {
            if (! b.equals(c) && ! b.equals(d)) {
                return ! c.equals(d);
            }
        }
        return false;
    }

Explanation:

Here we are flattening the stream of Integers from 1 to 9(first digit cannot be 0). while in further we are flattening stream of Integers from 0 to 9. The above process goes 2 more time thus making it a four digit, we are having a custom filter which is making sure that all four digits are unique.

At last we are collecting them as keys and values making sure the digits are unique and key itself in a map is unique.

Vishwa Ratna
  • 5,567
  • 5
  • 33
  • 55