2016-01-08 35 views
2

我想创建一个随机的数字串。创建随机数字的特定要求的字符串

  • 从0-9。
  • 10位数字。
  • 第一个数字不能是0.
  • 其中一个数字必须在字符串中2次,一个数字必须根本不存在。
  • 或者一位数字必须在那里3次,其他2位数字根本就不存在。

为了使这一点更清楚这里有一些例子:

1223456789 - 10位,没有起始零,一个数字(2)有2次和一位数字(0)是不存在的所有

1000345678 - 10位,没有起始零,一个数字(0)是有3次,两个数字(2,9)是根本不存在

起始零是很容易与startsWith抓 - 方法,但我还没有找到一种方法来检查其余的,我不是特别擅长正则表达式,而我也不是确信你甚至可以使用正则表达式来做到这一点。

为了生成随机字符串本身,我使用了Random类以及RandomStringUtils,它们都没有创建数字的限制。

有没有人知道如何做到这一点?

+0

在你的两个例子中,多次出现的数字顺序出现。这是规范的一部分吗?或者“1030456078”仍然是你的“出现三次”情况的有效例子? –

+0

这个问题似乎有两个部分:生成数字和验证数字。正如@sprinter指出的那样,您可以解决验证问题,然后随机生成一串10位数字并检查它们。 –

+0

顺序的出现只是巧合,因为我把数字从我的脑海中拉出来,然后写下来。事实上,他们可以在任何地方。感谢您指出了这一点。 – user5760519

回答

0

的理念是:第一产生与每个0-9随机字符串一次,而不是与0开始,则:1.取代数字将另一个或2.replace 2个七段与另一个中的一个。

import java.util.Random; 

public class Main { 
    public static void main(String[] args) { 
     System.out.println(generateRandomString()); 
     System.out.println(generateRandomString()); 
    } 


    public static String generateRandomString() { 
     String alphabet = ""; 
     String result = ""; 
     Random random = new Random(); 
     // build a random string construct will 0-9 and each digital appear once 
     for (int i = 0; i < 10; i++) { 
      int index = random.nextInt(alphabet.length()); 
      if (i == 0) { // first cannot be 0 
       index = random.nextInt(alphabet.length() - 1) + 1; 
      } 
      String c = alphabet.substring(index, index + 1); 
      result += c; 
      alphabet = alphabet.replace(c, ""); 
     } 
     return random.nextInt(2) == 0 ? shuffle1(random, result) : shuffle2(random, result); 
    } 

    // One of the digits has to be in the String 2 times and one has to not be there at all. 
    private static String shuffle1(Random random, String result) { 
     int from = random.nextInt(10); 
     int to = random.nextInt(9) + 1; 
     while (from == to) { 
      to = random.nextInt(9) + 1; 
     } 
     result = result.replace(result.substring(to, to + 1), result.substring(from, from + 1)); 
     return result; 
    } 

    // One digit has to be there 3 times, and 2 other digits can not be there at all 
    private static String shuffle2(Random random, String result) { 
     int from = random.nextInt(10); 
     int to1 = random.nextInt(9) + 1; 
     int to2 = random.nextInt(9) + 1; 
     while (from == to1) { 
      to1 = random.nextInt(9) + 1; 
     } 
     while (from == to2 || to2 == to1) { 
      to2 = random.nextInt(9) + 1; 
     } 
     result = result.replace(result.substring(to1, to1 + 1), result.substring(from, from + 1)); 
     result = result.replace(result.substring(to2, to2 + 1), result.substring(from, from + 1)); 
     return result; 
    } 

} 
+0

感谢您的回答。作品完全像它应该是。我欠你一个人情! – user5760519

0

如果您不太关心性能,那么最简单的方法就是随机生成一个数字列表,并根据您的条件进行检查,直到找到可用的数字。最好以数字形式进行过滤,然后在最后转换为字符串,而不是使用正则表达式。

public String getRandomInts() { 
    Random random = new Random(); 
    int[] ints; 
    do { 
     ints = random.ints(10, 0, 10).toArray(); 
    } while (!meetsCriteria(ints)); 
    return Arrays.stream(ints).mapToObj(String::valueOf).collect(Collectors.joining("")); 
} 

private boolean meetsCriteria(int[] ints) { 
    if (ints[0] == 0) { 
     return false; 
    } 
    if (frequency(ints, 0) == 1 
      && frequency(ints, 1) == 8 
      && frequency(ints, 2) == 1) { 
     return true; 
    } 
    if (frequency(ints, 0) == 2 
      && frequency(ints, 1) == 7 
      && frequency(ints, 3) == 1) { 
     return true; 
    } 
    return false; 
} 

private int frequency(int[] ints, int count) { 
    return (int) IntStream.range(0, 10) 
      .filter(n1 -> Arrays.stream(ints).filter(n2 -> n1 == n2).count() == count) 
      .count(); 
} 
+0

这就像是“bogosorting”的问题。不要! – caulitomaz

+0

@caulitomaz我的一些最好的朋友是bogosorters :-)认真如果OP想要真正的随机数字只是有些过滤出来,那么这可能是最合理的方式去做。您可以生成满足条件的数字,但除非您预先做了很多数学运算,否则您将最终偏离分布。我怀疑性能会真的成为一个考虑因素(与排序算法不同)。 – sprinter

+0

我很担心这个的时间复杂性。达到标准可能与赢得彩票一样艰难。 1010概率中有多少数字符合标准? – caulitomaz

1

假设你有10个麻袋,他们每个人都有绣花对应的号码就可以了,从0到9,像这样:

.---.._     
    {------'; 
    }====={  
.´  '. 
/ .´| \  inside there are 
|  | | <--- stones with '1' engraved 
\: _|_ /
    -__ =.´ 

你也有一个硬币翻转正面或反面在你的手上。

 .------..-     
    ´ . /___ `.`. 
    ; // ´} ; ;  ______________________________ 
    : "|'__' // : : /       | 
    ' .|/__\. } \ ' ' /_ HEAD! You shall pick 3 | 
    '  /"../  ' ' | stones from the 1st sack! | 
    ; /\/ ͷ ; ;  \____________________________/ 
    `_/   ´ ´ 
     " -------´-´ 

首先,我们将决定是否有3个重复数字或2个重复数字。翻转硬币来决定!尾是3,头是2.我们将这个结果叫做ͷ。

解除0(零)的麻袋一会儿。

现在从你面前的9个麻袋中随机选择ͷ(2或3个)石头。请记住,你不能从0开始,这就是为什么我们删除了一会儿!把你刚刚从袋子里挑出来的麻袋永远地取下来。你不能从这个选择。将0(零)袋放回原处。

将您刚刚选择的宝石放置在自己前面。握住ͷ-1在你的手中。

现在重复,直到你有你的手9个结石:

选择一个随机袋,从中选择一个石头拿在手上。从 行中取出麻袋。

到这个过程结束时,你手中会有9块宝石,一块在你自己的面前。把你手中的东西洗干净。把它们放在你自己前面的一条直线上,在已经在你前面的石头旁边。

您将以10个数字结束,ͷ相同数字的重复将不会以零开始,而您面前的剩余麻袋只是沿途消除麻袋的副作用。

1

如何使用规则制作你想要的东西,然后构造剩下的东西。

这里是一个可能的想法

使用的第一条规则

One of the digits has to be in the String 2 times and one has to not be there at all.

  1. 创建一个LinkedList然后加1至9的数字吧。

  2. 生成0-8之间的一个随机数(列表的索引范围),使用索引从列表中检索一个值(如删除它),然后将其添加到该字符串中,以便第一个数字不是0.

  3. 将0加回到列表中,以便可以在其他地方使用。

  4. 现在,LinkedList中剩下9个数字,第一个数字不为零,并已按照步骤2在String变量中。从这里,在LinkedList索引范围内生成另一个随机数。无论这个数字是多少,从LinkedList中删除它将它两次添加到ArrayList。

  5. LinkedList中剩下8个数字,String中有1个非零数字。 ArrayList中有3个数字,序列中总共有4个数字被证实是正确的。你必须得到另外6个数字来完成它。到目前为止,它会看起来像这样。

String sequence => "4"

ArrayList beingBuilt => [2, 6, 6]

LinkedList available => [1, 3, 4, 5, 7, 8, 9, 0]

  • 看来你只能使用随机有10个数字,环路6次以上通过链表号码采取随机索引,从LinkedList中删除它将它添加到ArrayList。
  • 在此之后,ArrayList应该有9个数字,你可以随机洗牌使它更随机,然后将其转换为一个字符串,并追加到序列的末尾。你的规则现在应该得到满足。

    为了让它更随意,您可以操纵如何从LinkedList中提取数字,以及最后一条规则,您可以简单地更改它。由于删除速度更快,我使用了LinkedList,我考虑过使用一个集合,但可能更多的工作来处理随机数字索引被映射到集合中实际存在的数字。

    只是一个想法,虽然

    +0

    我觉得很酷,你和我达到了相同的算法,并以非常不同的方式解释它:B – caulitomaz