Найдите все способы разбиения двух наборов на n бинов размера m, в которые должны быть включены все элементы первого набора (но не второго) - PullRequest
0 голосов
/ 07 января 2019

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

Однако есть дополнительное ограничение: некоторые игроки должны быть включены как минимум на один корт. Пусть они будут "Set_A". Остальные места, доступные на кортах, заполняются игроками в «Set_B».

Пример игрушки с желаемым выводом:

Set_A = {0, 1, 2}
Set_B = {3, 4}

def func(set_a, set_b, courts, court_size):
  #insert code here
  return answer

>>>func(Set_A, Set_B, 2, 2)
(((0,1),(2,3)),((0,1),(2,4)),((0,2),(1,3)),((0,2),(1,4)),((0,3),(1,2)),((0,4),(1,2)))

В реальном примере может быть 3 корта, каждый из которых рассчитан на 4 игрока. В «Set_A» 10 игроков, а в «Set_B» 12 игроков. Я хочу найти все комбинации, в которые входят все 10 игроков из «Set_A» и ровно 2 из «Set_B».

Следующий код (который я нашел здесь ) достаточен для нахождения всех комбинаций, когда пробелы на корте равны количеству игроков в "Set_A", например, позвонив по номеру list(partitions(range(12), 4)):

def partitions(s, r):
"""
Generate partitions of the iterable `s` into subsets of size `r`.

>>> list(partitions(set(range(4)), 2))
[((0, 1), (2, 3)), ((0, 2), (1, 3)), ((0, 3), (1, 2))]
"""
s = set(s)
assert(len(s) % r == 0)
if len(s) == 0:
    yield ()
    return
first = next(iter(s))
rest = s.difference((first,))
for c in combinations(rest, r - 1):
    first_subset = (first,) + c
    for p in partitions(rest.difference(c), r):
        yield (first_subset,) + p

Однако для моих целей этого недостаточно.

Другая проблема - это скорость и память. 'partitions (16,4)' занимает ~ 14 секунд при каждом запуске, а 'partitions (20,4)' возвращает MemoryError. Вполне возможно, что комбинаторный взрыв означает, что он просто неразрешим для некоторых ценностей, с которыми я хочу работать. (Тем не менее, я думаю, что в большинстве случаев это будет правдоподобно, особенно если эти вычисления кэшируются для последующего просмотра).

1 Ответ

0 голосов
/ 07 января 2019

Вы ошибаетесь в своей проблеме и пытаетесь преждевременно оптимизироваться для загрузки.

Вы не пытаетесь увидеть все комбинации 20 игроков в 12 слотах. Комбинации не заботятся о порядке, поэтому у вас есть два набора. Set_A просто занимает слоты, так что вы действительно хотите увидеть комбинации из 12 игроков набора B в оставшихся 2 слотах.

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

Выясните, какой уровень детализации в каждом суде вас интересует - если только четыре игрока на каждом корте, то в случае с 20 игроками на трех кортах вы получите 45 комбинаций (set_A + наборы 2 от set_B) для положить на первый корт, затем 22 275 комплектов игроков, которые не попали на первый корт, чтобы увидеть, кто идет на второй корт, а кто - на третий корт. Это в основном дает вам 1,5 миллиона различных возможностей присутствия в каждом суде. Но если тебе все равно, кто идет против кого, или кто находится в каждом месте на площадке, тогда ... все, что я могу сделать, - это пожелать тебе удачи и спокойной ночи.

...