2016-03-06 61 views
1

我希望我的程序能夠從1到X中的數字,並隨機將這些數字在X/2個列表中的Y個列表之間分配。我不希望在一次洗牌過程中重複一個數字,也不希望這些列表重複。因此,如果列表[1,2]不應該在同一個shuffle中包含1或2的另一個列表,並且整個結果中不應該有另一個[1,2]或[2,1]。在Python查詢中生成隨機列表

這是我想出來的,但是,它不斷重複數字。任何adice?

import random 

def Shuffler(): 
    amount = int(raw_input("Numbers up to: ")) 
    times = int(raw_input("Number of shuffles: ")) 
    numberslist = range(1,amount+1) 
    twos = [] 
    thisshuffle = [] 
    final = [] 

    while len(final) < (amount/2)*times: 
     twos = [] 
     thisshuffle = [] 
     while len(twos) < 2: 
     if len(numberslist)!=0: 
      randomnumber = random.choice(numberslist) 
      if (randomnumber in twos) or (randomnumber in thisshuffle): 
      numberslist.remove(randomnumber) 
      else: 
      twos.append(randomnumber) 
      thisshuffle.append(randomnumber) 
      numberslist.remove(randomnumber) 
     else: 
      numberslist = range(1,amount+1) 

     if (twos or list(reversed(twos))) not in final: 
     final.append(twos) 

    k=0 
    for i in range(times): #this shit prints shit 
     print "%s:" % (i+1), final[k:k+amount/2] 
     print 
     k = k + amount/2 
    Shuffler() 

Shuffler() 

回答

0

正如CCF指出的那樣,你的要求是不平凡的。更多的步驟,你會有一個數獨發電機:)
我嘗試了一些解決方案,但他們要麼沒有產生隨機輸出或效率低下。 Ccf的解決方案顯然寫得很好,但似乎也有同樣的問題;它會產生有序的輸出(例如[1, 2], [1, 3], [1, 4], [1, 5], [1, 6])。

@cff - 使用itertools.combinations而不是itertools.permutations來避免重複產生會更好嗎?

這裏有一個「解決方案」這是相當類似CCF的(不產生隨機地輸出):

import itertools 

def Shuffler(): 
    amount = int(raw_input("Numbers up to: ")) 
    times = int(raw_input("Number of shuffles: ")) 
    rng = range(1, amount+1) 
    perms = list(itertools.combinations(rng, 2)) 
    lst_single = [] 
    lst_all = [] 
    for p in perms: 
     if len(lst_all) >= times: 
      for i, lst in enumerate(lst_all): 
       print str(i+1) + ": ", lst 
      break 
     if len(lst_single) == amount/2: 
      lst_all.append(lst_single) 
      lst_single = [] 
     elif p[0] < p[1]: 
      p = list(p) 
      lst_single.append(p) 

    Shuffler() 

輸出

Numbers up to: 6 
Number of shuffles: 3 
1: [[1, 2], [1, 3], [1, 4]] 
2: [[1, 6], [2, 3], [2, 4]] 
3: [[2, 6], [3, 4], [3, 5]] 

而這裏的一個稍微hackish的解決方案,它似乎產生輸出你想要的,但效率低下。它依靠一套過濾不需要的組合,但仍然浪費資源生產它們。

import random 

def Shuffler(): 
    amount = int(raw_input("Numbers up to: ")) 
    times = int(raw_input("Number of shuffles: ")) 
    rng = range(1, amount+1) 
    final = [] 
    lst_len = amount/2 
    combos_unique = set() 
    while len(combos_unique) < lst_len*times: 
     combo_rand = random.sample(rng, 2) 
     if combo_rand[0] < combo_rand[1]: 
      combos_unique.add(tuple(combo_rand)) 
    tmp = [] 
    for combo in combos_unique: 
     tmp.append(list(combo)) 
     if len(tmp) >= lst_len: 
     final.append(tmp) 
     tmp = [] 
    for i, lst in enumerate(final): 
     print str(i+1) + ": ", lst 
    Shuffler() 

輸出

Numbers up to: 6 
Number of shuffles: 3 
1: [[2, 6], [4, 6], [5, 6]] 
2: [[4, 5], [1, 3], [1, 6]] 
3: [[3, 4], [2, 4], [3, 5]] 
0

你不想在一個洗牌和任何重複列表中有任何重複的數字......等等。這不是一件容易的事。另外一個事實是,唯一的數字組是固定的,不能設置得太高。例如,如果您將「數字最多爲:」5和「洗牌次數」設置爲20,那麼您肯定會得到重複的數字。

與您的代碼的問題,我看到的,是在這個if語句:

if (twos or list(reversed(twos))) not in final: 
    final.append(twos) 

(三三兩兩或列表(逆轉(三三兩兩)))是邏輯或,結果是三三兩兩,因爲三三兩兩不空。我建議你改變if語句:

if (twos not in final) and (list(reversed(twos)) not in final): 
    final.append(twos) 

下面的代碼(Python的2.7倍)使用的排列和隨機生成的號碼列表。接下來,使列表唯一(例如,在同一列表中的否[1,2]和[2,1])。然後根據用戶指定的洗牌次數將它們分組。按任何字母,腳本將退出。希望它能幫助:

from itertools import permutations 
from random import shuffle 

def Shuffler(): 
    try: 
     amount = input("Numbers up to: ") 
     p = list(permutations(range(1, amount + 1), 2)) 
     p_uniq = [list(x) for x in p if x[::-1] in p and x[0]<=x[1]] 
     shuf_max = len(p_uniq) /(amount/2) 
     times = shuf_max + 1 # set a higher value to trigger prompt 

     while times > shuf_max: 
      shuffle(p_uniq) # shuffle the unique list in place 
      times = input("Number of shuffles (MAX %s): " % (shuf_max))    
     else: 
      for i, group in enumerate(list(zip(*[iter(p_uniq[: (amount /2) * times + 1])]* (amount/2)))): 
       print "%i: " % (i + 1), list(group) 
     Shuffler() 
    except: 
     print 'quitting...' 

Shuffler() 

輸出:

Numbers up to: 10 
Number of shuffles (MAX 9): 8 
1: [[6, 7], [1, 9], [2, 5], [5, 9], [9, 10]] 
2: [[1, 10], [3, 8], [4, 10], [8, 10], [1, 5]] 
3: [[1, 4], [6, 8], [3, 6], [2, 4], [4, 7]] 
4: [[2, 10], [5, 8], [3, 9], [1, 7], [4, 9]] 
5: [[1, 2], [7, 9], [1, 3], [6, 9], [1, 6]] 
6: [[2, 9], [4, 8], [3, 5], [8, 9], [7, 10]] 
7: [[2, 7], [2, 3], [7, 8], [3, 7], [3, 10]] 
8: [[3, 4], [2, 6], [5, 6], [5, 7], [4, 6]] 
Numbers up to: