#python #recursion #permutation #matching
#python #рекурсия #перестановка #сопоставление
Вопрос:
Предположим, что у нас есть массив X = (x_1, ..., x_N)
длины N
. Мы хотим вернуть все возможные массивы длины M
( M
фиксированной), элементы которых могут быть (x_1, ..., x_N, NaN)
такими, что каждый x_i
используется не более одного раза, и x_i
порядок сохраняется. Например, если N = 3
и M = 7
, несколько возможных векторов
Z = (x_1, NaN, NaN, x_2, x_3, NaN, NaN)
Z = (NaN, x_1, NaN, NaN, x_3, NaN, NaN)
Z = (x_3, NaN, NaN, NaN, NaN, NaN, NaN)
Z = (NaN, NaN, NaN, NaN, NaN, NaN, NaN)
Но следующие векторы неприемлемы:
Z = (x_1, x_1, NaN, x_2, x_3, NaN, NaN)
Z = (NaN, x_3, NaN, NaN, x_2, NaN, NaN)
Эту проблему можно рассматривать как сопоставление некоторых x_i
s с местоположениями 1,...,M
таким образом, чтобы x_i
порядок s сохранялся. Как я могу это сделать? Я думал об использовании рекурсивной функции f(X, M)
, которая обрезает вектор Z
во всех возможных точках ( for i in range(1,M 1)
), а затем объединяет f(x_1, i)
(определяется как базовый вариант) с f((x_2, ..., x_N), M-i 1)
(рекурсия) . Но этот подход не дает уникальных векторов, и мне приходится удалять дубликаты после этого, и это неэффективно. Есть ли лучший способ решить эту проблему? Может быть, с помощью itertools?
Комментарии:
1. какую реальную проблему вы пытаетесь решить? Как вы будете использовать такую функцию?
2. @aaaaaa Я хочу разработать функцию для возврата всех возможных
Z
s. Число можно вычислить математически, например, дляM = 7
иN = 3
должно дать 70 (я думаю) различныхZ
s. Позже я хочу использовать результат в других частях моего кода.3. Я понимаю ваш вопрос, но я хочу знать, может быть, большую проблему можно решить проще, чем вы думаете прямо сейчас. вы собираетесь часто вызывать этот генератор, например? почему ваше решение недостаточно эффективно?
4. @aaaaaa я вижу. Да, я буду часто вызывать этот генератор. В моей проблеме я
N = 3
исправил, ноM
варьируется (я думаю, от 3 до 10). Но, может быть, я могу вычислить их заранее и сохранить результаты генератора в словаре.5. тем не менее, было бы полезно опубликовать фрагмент кода, который использует эти списки. По сути, у вас есть M контейнеров подряд, и вы должны заполнить их, беря элементы один за другим X1, X2, X3, размещая в контейнерах по-разному?
Ответ №1:
Я думаю, что что-то подобное должно сработать для вас. Это в основном итеративное заполнение M
полей путем взятия элементов из списка X
. None
В этом случае используется содержимое по умолчанию, но вы должны иметь возможность настроить. Вы можете увидеть, как это работает на repl
N = 3
M = 6
X = range(N) # or example, can be [x1,x2,x3]
for j1 in range(M-N 1):
for j2 in range(j1 1,M-N 2):
for j3 in range(j2 1,M):
r = [None]*M
r[j1] = X[0]
r[j2] = X[1]
r[j3] = X[2]
print(r)
Это приведет к следующему выводу:
[0, 1, 2, None, None, None]
[0, 1, None, 2, None, None]
[0, 1, None, None, 2, None]
[0, 1, None, None, None, 2]
[0, None, 1, 2, None, None]
[0, None, 1, None, 2, None]
[0, None, 1, None, None, 2]
[0, None, None, 1, 2, None]
[0, None, None, 1, None, 2]
[0, None, None, None, 1, 2]
[None, 0, 1, 2, None, None]
[None, 0, 1, None, 2, None]
[None, 0, 1, None, None, 2]
[None, 0, None, 1, 2, None]
[None, 0, None, 1, None, 2]
[None, 0, None, None, 1, 2]
[None, None, 0, 1, 2, None]
[None, None, 0, 1, None, 2]
[None, None, 0, None, 1, 2]
[None, None, None, 0, 1, 2]
В идеале вы хотели бы обобщить его для произвольного N, чтобы вам не приходилось жестко кодировать j1
, j2
, и j3
индексы.