Генерация всех комбинаций из 2 списков (игра в игру)

1

Я пытаюсь создать все возможные комбинации между двумя списками A и B в python с несколькими ограничениями. A и B чередуются с выбором значений, всегда выбирает сначала. A и B могут иметь перекрывающиеся значения. Если A уже выбрал значение, B не может выбрать его, и наоборот.

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

Также элементы, выбранные каждым, должны быть в порядке возрастания, т.е. A[1] < A[2] <.... A[n] и B[1] < B[2] <.... B[n] где A[i] и B[i] - элемент i -th, выбранный соответственно A и B

Пример:

A = [1, 2, 3, 4]
B = [2, 5]

Решение, в котором я нуждаюсь

(1), (2), (3), (4),
(1,2), (1,5), (2,5), (3,2), (3,5), (4,2), (4,5),
(1,2,3), (1,2,4), (3,2,4), (1,5,2), (1,5,3), (1,5,4), (2,5,3), (2,5,4), (3,5,4),
(1,2,3,5), (1,2,4,5), (3,2,4,5)
(1,2,3,5,4)

Я считаю, что itertools в python могут быть полезны для этого, но я действительно не понял, как реализовать его для этого случая.

На данный момент я так решаю:

A = [1, 2, 3, 4]
B = [2, 5]
A_set = set(A)
B_set = set(b)
#Append both sets
C = A.union(B)
for L in range(len(C), 0, -1):
        for subset in itertools.combinations(C, L):
        #Check if subset meets constraints and print it if it does
  • 2
    Покажите свой код в своем вопросе :)
  • 0
    Это звучит так странно, как выбирать комбинации, что в itertools не может быть чего-то, что делает это.
Показать ещё 11 комментариев
Теги:
itertools

1 ответ

0
Лучший ответ

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

Что-то вроде этого (это может быть улучшено путем добавления параметров для текущего индекса в обоих списках вместо фактического отсечения списков для рекурсивных вызовов):

def solve(n, lst1, lst2, selected):
    if n == 0:
        yield []
    elif lst1:
        for i, x in enumerate(lst1):
            if x not in selected:
                selected.add(x)
                for rest in solve(n-1, lst2, lst1[i+1:], selected):
                    yield [x] + rest
                selected.remove(x)

Или немного конденсировано:

def solve(n, lst1, lst2, selected):
    if n == 0:
        yield []
    elif lst1:
        yield from ([x] + rest for i, x in enumerate(lst1) if x not in selected
                               for rest in solve(n-1, lst2, lst1[i+1:], selected.union({x})))

Пример:

A = [1, 2, 3, 4]
B = [2, 5]
result = [res for n in range(1, len(A)+len(B)+1) for res in solve(n, A, B, set())]

В result:

[[1], [2], [3], [4],
 [1, 2], [1, 5], [2, 5], [3, 2], [3, 5], [4, 2], [4, 5],
 [1, 2, 3], [1, 2, 4], [1, 5, 2], [1, 5, 3], [1, 5, 4], [2, 5, 3], [2, 5, 4], [3, 2, 4], [3, 5, 4], 
 [1, 2, 3, 5], [1, 2, 4, 5], [3, 2, 4, 5],
 [1, 2, 3, 5, 4]]
  • 0
    Благодарю. Это именно то, что я хочу

Ещё вопросы

Сообщество Overcoder
Наверх
Меню