Генерация случайных списков в запросе Python

Я хочу, чтобы моя программа принимала числа от 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()

2 ответа

Решение

Как указал ccf, ваши требования не являются тривиальными. Еще несколько шагов, и вы получите генератор судоку:)
Я попробовал несколько решений, но они либо не давали случайного вывода, либо были довольно неэффективными. Решение Ccf ясно написано, но, похоже, та же проблема; он производит упорядоченный вывод (например, [1, 2], [1, 3], [1, 4], [1, 5], [1, 6]).

@cff - не лучше ли использовать itertools.combination вместо 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]]

И вот немного хакерское решение, которое, кажется, дает желаемый результат, но неэффективно. Он опирается на набор для фильтрации нежелательных комбинаций, но все же тратит ресурсы, производя их в первую очередь.

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

Вам не нужны повторяющиеся числа в одном случайном порядке и любой повторный список... и так далее. Это не простая задача. Плюс еще один факт, что уникальные наборы чисел являются фиксированными, которые не могут быть установлены слишком высоко. Например, если вы установите "Numbers до:" 5 и "Number of shuffles: " 20, то наверняка вы получите повторяющиеся числа.

Проблема с вашим кодом, я вижу, заключается в следующем операторе if:

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

(twos или list(полностью измененный (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: 
Другие вопросы по тегам