Неупорядоченные комбинации с ограниченными заменами - PullRequest
0 голосов
/ 25 мая 2018

Я должен составить список неупорядоченных комбинаций с ограниченными повторениями, т. Е. Для заданного списка уникальных элементов скажем, что card_set создает все комбинации длины combo_len, с элементом, повторяющимся с максимальным повторением в разы

нижекод для combo_len = 3 и repeat_limit = 2 с card_set = range (5)

обратите внимание, мне нужны неупорядоченные комбинации.т.е. (0,0,1) и (0,1,0) одинаковы, поэтому приведенная ниже ссылка на решение не удовлетворяет моим условиям

В этом посте рассказывается, как получить размеченные комбинациис ограниченным числом повторений

import itertools
import pprint
card_set = list(range(5))
a = sorted(set(itertools.combinations_with_replacement(card_set,3)))
neg = [(i,i,i) for i in card_set]
b = set(a) - set(neg)
print('a###')
pprint.pprint(a)
print('b###')
pprint.pprint(b)

приведенный выше код дает мне неупорядоченные комбинации с ограниченным 2 повторениями, т.е.neg содержит нежелательные повторы (0,0,0) (1,1,1) и т. д., поэтому b = set(a) - set(neg) дает мне необходимый набор

для combo_len = 3 и repeat_limit = 2, указанный выше код работает.Как мне сделать код для диапазона (13) combo_len = 7 и repeat_limit = 4

Вывод:

a###
[(0, 0, 0),
 (0, 0, 1),
 (0, 0, 2),
 (0, 0, 3),
 (0, 0, 4),
 (0, 1, 1),
 (0, 1, 2),
 (0, 1, 3),
 (0, 1, 4),
 (0, 2, 2),
 (0, 2, 3),
 (0, 2, 4),
 (0, 3, 3),
 (0, 3, 4),
 (0, 4, 4),
 (1, 1, 1),
 (1, 1, 2),
 (1, 1, 3),
 (1, 1, 4),
 (1, 2, 2),
 (1, 2, 3),
 (1, 2, 4),
 (1, 3, 3),
 (1, 3, 4),
 (1, 4, 4),
 (2, 2, 2),
 (2, 2, 3),
 (2, 2, 4),
 (2, 3, 3),
 (2, 3, 4),
 (2, 4, 4),
 (3, 3, 3),
 (3, 3, 4),
 (3, 4, 4),
 (4, 4, 4)]

b###
{(0, 0, 1),
 (0, 0, 2),
 (0, 0, 3),
 (0, 0, 4),
 (0, 1, 1),
 (0, 1, 2),
 (0, 1, 3),
 (0, 1, 4),
 (0, 2, 2),
 (0, 2, 3),
 (0, 2, 4),
 (0, 3, 3),
 (0, 3, 4),
 (0, 4, 4),
 (1, 1, 2),
 (1, 1, 3),
 (1, 1, 4),
 (1, 2, 2),
 (1, 2, 3),
 (1, 2, 4),
 (1, 3, 3),
 (1, 3, 4),
 (1, 4, 4),
 (2, 2, 3),
 (2, 2, 4),
 (2, 3, 3),
 (2, 3, 4),
 (2, 4, 4),
 (3, 3, 4),
 (3, 4, 4)}

Ответы [ 2 ]

0 голосов
/ 25 мая 2018

Вы можете использовать класс Counter из модуля collections, чтобы найти количество повторов каждого значения в данном кортеже.Для каждого кортежа составьте Counter и проверьте максимальное значение повторений.Если это максимальное значение достаточно мало, примите кортеж;в противном случае, отклоните его.

Вот процедура для этого.Если бы у меня было больше времени, я бы с этим справился.

Будьте осторожны с этой рутиной.Для заданных вами значений range_size=13, combo_len=7, repeat_limit=4 результатом будет список длиной 49 205

from collections import Counter
from itertools import combinations_with_replacement

def unordered_combinations_with_limited_replacements(
        range_size, combo_len, repeat_limit):
    return [t for t in combinations_with_replacement(range(range_size), combo_len)
            if max(Counter(t).values()) <= repeat_limit]

print(unordered_combinations_with_limited_replacements(5, 3, 2))
print(len(unordered_combinations_with_limited_replacements(13, 7, 4)))

Вот распечатка:

[(0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 2), (0, 2, 3), (0, 2, 4), (0, 3, 3), (0, 3, 4), (0, 4, 4), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 3), (1, 3, 4), (1, 4, 4), (2, 2, 3), (2, 2, 4), (2, 3, 3), (2, 3, 4), (2, 4, 4), (3, 3, 4), (3, 4, 4)]
49205
0 голосов
/ 25 мая 2018

Во-первых, neg, используемый в вашем примере кода, будет работать только в том случае, если repeat_limit равен combo_length.

Поэтому я искал что-то, что может подсчитать различные элементы в списке, и придумал Counter в модуле collections.Следующий шаг - перебрать все элементы, созданные itertools.combinations_with_replacement, с помощью простого цикла for.Если самый общий элемент в объекте Counter выше, чем ваш repeat_limit, удалите этот элемент из списка.

Этот код будет работать для каждого диапазона, combo_length и repeat_limit:

import itertools
from collections import Counter

def getUnorderedCombo(list_range, combo_len, repeat_lim):
    card_set = list(range(list_range))
    a = list(set(itertools.combinations_with_replacement(card_set,combo_len)))
    i = 0
    while i < len(a):
        c = Counter(a[i])
        if c.most_common(1)[0][1] > repeat_lim:
            del a[i]
            i -= 1
        i += 1
    return set(a)
...