Мне нужен итератор для всех наборов различные k кортежей целых чисел длиной a и суммой d с точностью до перестановки элементов кортежей.
Например, если k=2, a=2 и d =3, это все наборы различных k кортежей целых чисел длины a и суммы d:
Код: Выделить всё
{(3,0), (0,3)}, {(3,0), (2,1)}, {(3,0), (1,2)}, {(1,2), (2,1)}, {(0,3), (2,1)}, {(0,3), (1,2)}
Код: Выделить всё
{(3, 0), (2, 1)}: 2,
{(3, 0), (1, 2)}: 2,
{(3, 0), (0, 3)}: 1,
{(2, 1), (1, 2)}: 1}
В качестве еще одного примера рассмотрим случай с k=2, a=3, d=3 (поэтому наборы пар кортежей длины 3 с сумма 3).
Код: Выделить всё
{(2, 1, 0), (3, 0, 0)}: 6, {(1, 2, 0), (3, 0, 0)}: 6, {(0, 3, 0), (3, 0, 0)}: 3, {(1, 1, 1), (3, 0, 0)}: 3, {(0, 2, 1), (3, 0, 0)}: 6, {(1, 2, 0), (2, 1, 0)}: 3, {(2, 0, 1), (2, 1, 0)}: 3, {(1, 1, 1), (2, 1, 0)}: 6, {(0, 2, 1), (2, 1, 0)}: 6, {(0, 1, 2), (2, 1, 0)}: 3
Мой вопрос (надеюсь, на него есть положительный ответ): это где-то уже было сделано?
Самый близкий ответ, который мне удалось найти, - это эта библиотека, которая решает более общую проблему, но с k=1 (она просто перечисляет кортежи, а не наборы кортежей длиной k).
В неудачном случае этого никогда раньше не делалось, вот мои попытки найти решение.
Обратите внимание, что я не добавляю к вопросу явный код. Это потому, что оба подхода, которые я пробовал, неверны: первый работает, но это не итератор. Вторые просто не работают, но не из-за программирования, а из-за того, что алгоритм неправильный. Для вашего удобства/любопытства я добавляю несколько примеров кода, написанного на Python3 (если я смогу создать работающий код, я, конечно, буду рад им поделиться!)
Мой первый — бесполезный — подход заключался в том, чтобы просто построить результат, перебирая все наборы, а затем применить перестановки для сокращения списка. Это слишком медленно и требует много памяти. (Пример кода, опять же, это работает, но это не итератор)
Мой второй — незаконченный — подход, надеюсь, был немного умным: (Пример кода, это не работает, см. объяснение ниже)
- Первый шаг, я перебираю упорядоченные кортежи цифр: для k=2, a=3, d =3 Я получаю только (3,0,0), (2, 1, 0), (1, 1, 1).
- Второй шаг, я перехожу к создаю список цифр, которые составят окончательные кортежи: сначала я использую (3,0,0) дважды, затем (3,0,0) и (2,1,0), затем (3,0,0) и (1,1,1) и так далее.
- Третий шаг. Для каждого выбора цифры, мне нужно вычислить все возможные перестановки. Я делаю это с помощью рекурсии. Вот три примера:
- Цифры (3,0,0) дважды. Первый кортеж — это просто (3,0,0) (поскольку я работаю над перестановкой). Что касается второго кортежа, мне нужно запомнить, что в первом есть два нуля, чтобы я мог поменять вторую и третью цифры и создать набор {, (0,3,0)
Код: Выделить всё
(3,0,0) - Цифры (3,0,0) и (2,1,0). Как и раньше, первый кортеж — (3,0,0), и я могу поменять местами вторую и третью цифры, поэтому для выбора второго кортежа у меня есть {, (2,1,0)}, {
Код: Выделить всё
(3,0,0), (1,2,0)}, {Код: Выделить всё
(3,0,0), (0,2,1)Код: Выделить всё
(3,0,0) - Цифры (2,1,0) и (2,1,0). Как и раньше, первый кортеж — это (2,1,0), и теперь, поскольку все цифры разные, я могу поместить все перестановки для второго кортежа:
{, (2,0,1)}, {Код: Выделить всё
(2,1,0), (1,2,0)}, {Код: Выделить всё
(2,1,0), (1,0,2)}, {Код: Выделить всё
(2,1,0), (0,2,1)}, {Код: Выделить всё
(2,1,0), (1,0,2)} то же самое, что {Код: Выделить всё
(2,1,0), (0,1,2)}. [b]ЭТО СОДЕРЖИТ ПРОБЛЕМУ![/b] Это неправильно, потому что я перечисляю несколько кортежей дважды: {(2,1,0), (0,2,1)}, поместив третью цифру на первое место, первую цифру на второе место и вторую цифру на третье место.Код: Выделить всё
(2,1,0)
Первая проблема с этим подходом: Мне нужно удалить последние дубликаты. Однако я знаю, что нужно просто сравнить их друг с другом, и для этого нужен полный список (так что... не итератор).
Вторая проблема с этим подходом : Мне также нужно прикрепить к парам метку, описывающую, сколько их существует с точностью до перестановки ({(2, 1, 0), (3, 0, 0)}: 6, означает, что есть 6 возможных пар кортежей, которые можно получить перестановкой этого). Однако известный мне способ вычисления по сути эквивалентен первому подходу, заключающемуся в перечислении всех перестановок этой единственной пары, так что, опять же, слишком медленно
Подробнее здесь: https://stackoverflow.com/questions/789 ... rmutations