在 Python 查询中生成随机列表

Generating random lists in Python query

我希望我的程序获取从 1 到 X 的数字,并在 X/2 个列表之间随机分配这些数字 Y 次。我不想在一次洗牌中重复一个数字,我也不希望列表重复。因此,如果有列表 [1,2],则在同一洗牌中不应该有另一个包含 1 或 2 的列表,并且整个结果中不应该有另一个 [1,2] 或 [2,1]。

这是我想到的,但是,它一直在重复数字。有什么建议吗?

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()

您不希望在一次随机播放中有任何重复的数字,以及任何重复的列表...等等。这不是一件容易的事。另外一个事实是,唯一的数字集是固定的,不能设置得太高。例如,如果您设置 "Numbers up to:" 5,并且 "Number of shuffles: " 20,您肯定会得到重复的数字。

我知道你的代码的问题是在这个 if 语句中:

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

(twos or list(reversed(twos))) 逻辑或,结果为twos,因为twos不为空。我建议您将 if 语句更改为:

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

以下代码 (python 2.7x) 使用排列和洗牌生成数字列表。接下来,使列表唯一(例如,同一列表中没有 [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: 

正如 ccf 所指出的,您的要求并非微不足道。再执行几个步骤,您就会拥有一个数独生成器:)
我尝试了一些解决方案,但它们要么没有产生随机输出,要么效率很低。 Ccf 的解决方案写得很好,但似乎有同样的问题;它产生有序的输出(例如 [1, 2], [1, 3], [1, 4], [1, 5], [1, 6])。

@cff - 使用 itertools.combinations 而不是 itertools.permutations 来避免产生重复不是更好吗?

这是一个与 ccf 非常相似的 "solution"(也不产生随机输出):

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]]

这里有一个有点老套的解决方案,它似乎可以产生您想要的输出,但效率低下。它依赖于一个集合来过滤掉不需要的组合,但仍然浪费资源来首先产生它们。

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]]