2016-01-08 62 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