Генерация номера лотереи Python - PullRequest
0 голосов
/ 10 мая 2019

Я работаю над программой генерации лотерейных номеров. У меня есть фиксированный список разрешенных номеров (1-80), из которых пользователи могут выбрать 6 номеров. Каждый номер может быть выбран только один раз. Я хочу эффективно генерировать все возможные комбинации. Текущая реализация занимает более 30 секунд, если allow_numbers - [1, ..., 60]. Кроме того, он замораживает мою систему.

from itertools import combinations
import numpy as np


LOT_SIZE = 6


allowed_numbers = np.arange(1, 61)
all_combinations = np.array(list(combinations(allowed_numbers, LOT_SIZE)))
print(len(all_combinations))

Я думаю, что мне нужен массив NumPy (не уверен, если 2D). Что-то вроде

[[1,2,3,4,5,6],
[1,2,3,4,5,,7],...]

потому что я хочу (быстро) выполнить несколько операций над этими комбинациями. Эти операции могут включать,

  • Удаление комбинаций, имеющих только четные числа
  • Удаление комбинаций, чья сумма больше 150 и т. Д.
  • Проверка наличия только одной пары последовательных чисел (допустимо: [1,2,4,6,8,10] {Pair: (1,2)} | Недопустимо: [1,2,4, 5,7,9] {пары: (1,2) и (4,5)})

Любая помощь будет оценена.

Спасибо

Ответы [ 2 ]

0 голосов
/ 10 мая 2019

Некоторые опции:

1) применить фильтры к итерируемым вместо данных, используя filter:

def filt(x):
    return sum(x) < 7

list(filter(filt, itertools.combinations(allowed, n)))

сэкономит ~ 15% времени по сравнению с созданием списка и применением фильтров, т. Е .:

[i for i in itertools.combinations(allowed, n) if filt(i) if filt(i)]

2) Использование np.fromiter

arr = np.fromiter(itertools.chain.from_iterable(itertools.combinations(allowed, n)), int).reshape(-1, n)
return arr[arr.sum(1) < 7]

3) работа на самом объекте генератора. В приведенном выше примере вы можете остановить itertools.combinations, когда первое число больше 7 (как пример):

def my_generator():
    for i in itertools.combinations(allowed, n):
        if i[0] >= 7:
            return
        elif sum(i) < 7:
            yield i
list(my_generator())   # will build 3x times faster than option 1

Обратите внимание, что np.fromiter становится менее эффективным для составных выражений, поэтому маска применяется впоследствии

0 голосов
/ 10 мая 2019

Вы можете использовать itertools.combinations(allowed_numbers, 6), чтобы получить все комбинации длины 6 из вашего списка (это самый быстрый способ выполнить эту операцию).

...