简体   繁体   English

如何生成4个不重复数字的随机数

[英]How can I generate 4 random numbers with unrepeated digits

I want to generate 4 random numbers and they can't have repeated digits.我想生成4 个随机数,它们不能有重复的数字。

For instance 4567 , (it doesn't have a repeated value like 4557 ).例如4567 ,(它没有像4557这样的重复值)。

I want them to be random .我希望它们是随机的

Is there any way to achieve this?有没有办法实现这一目标?

This will generate 4 digit random numbers with no repeating digits.这将生成没有重复数字的 4 位随机数。

It works by generating 4 unique digits in the same fashion that one might shuffle a deck of cards in a computer game.它的工作原理是生成 4 个唯一的数字,就像在电脑游戏中洗一副纸牌一样。 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.如果数字小于1000 ,则表示使用了0并且在开头。 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);

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. “generateWithLoop”方法涵盖了@WJS 的答案。

    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 Streams 已用时间:81367089 纳秒

Elapsed time with Loop : 75093 nano seconds循环运行时间:75093 纳秒

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;
    }
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.这是将字符串转换为 int。 But this will work you can use it.但这会起作用,您可以使用它。

Steps:脚步:

  1. Create a List that will hold each individual number of the generated 4-digit number创建一个List ,将保存生成的 4 位数字的每个单独的数字
  2. Generate a random number for the units place between 1 and 9, and put it in the list为1到9之间的单位生成一个随机数,并将其放入列表中
  3. Create a loop to generate a random number between 0 and 9 for the ten's place until the last place;创建一个循环,为十位到最后一位生成一个0到9之间的随机数; 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;最终列表的大小现在是 4; combine these 4 individuals into a String , and convert to Integer .将这 4 个个体组合成一个String ,并转换为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()));

A solution using stream and Lambdas from Java-8 onwards:Java-8开始使用streamLambda 的解决方案:

  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).在这里,我们将整数流从 1 展平到 9(第一个数字不能为 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.同时,我们进一步将整数流从 0 展平到 9。上述过程又进行了 2 次,从而使其成为四位数字,我们有一个自定义过滤器,可确保所有四位数字都是唯一的。

At last we are collecting them as keys and values making sure the digits are unique and key itself in a map is unique.最后,我们将它们收集为键和值,以确保数字是唯一的,并且映射中的键本身也是唯一的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM