2016-03-06 55 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: