ранжирование перестановок с последовательностью DI - PullRequest
0 голосов
/ 11 июня 2019

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

Пример длины перестановки 4:

У нас есть входная длина битовой строки 3 (всегда длина перестановки - 1)

010

0 означает, что 2 последовательных элемента I увеличиваются.

1 означает, что 2 последовательных элемента D смазывают.

Для этой цепочки битов существует подмножество со следующими перестановками: 1324, 1423, 2314, 2413, 3412

Определенное подмножество цепочек битов, которое я хочу оценить и отменить? Есть ли у данного алгоритма алгоритм для этой цепочки битов?

1 Ответ

1 голос
/ 12 июня 2019

Позвольте мне переформулировать проблему, которую, я думаю, вы имеете в виду.

У вас есть битовая строка длиной n-1. Если его цифры представляют собой шаблон увеличения / уменьшения, это описывает набор перестановок, которые соответствуют шаблону. Этот набор можно поставить в порядке возрастания.

Вы хотите иметь возможность решить две проблемы.

  1. Учитывая перестановку, которая соответствует шаблону, скажите, где он находится в этом порядке (то есть "оцените" его)
  2. Учитывая число, произведите перестановку, которая находится в том месте в заказе (то есть, "unrank" это)

И в идеале вы хотели бы иметь возможность решить их без необходимости генерировать все перестановки, которые соответствуют шаблону.

Ключом к обоим является следующая функция:

def count_matching (bitstring, start):
    ''' Returns how many permutations of 1..(len(bitstring) + 1)
    ''' match bitstring with starting value start
    # some implementation here.

Это можно довольно легко вычислить рекурсивно. Однако, делая это, наивный способ порождает все перестановки. Но если мы добавим кеширующий слой к memoize этому, то мы храним полиномиальный объем данных и делаем полиномиальное количество вызовов, чтобы заполнить его.

Вот данные, которые вы получаете, когда они кешируются для вашего примера:

{
    ('010', 1): 2,
    ('010', 2): 2,
    ('010', 3): 1,
    ('010', 4): 0,
    ('10', 1): 0,
    ('10', 2): 1,
    ('10', 3): 1,
    ('0', 1): 1,
    ('0', 2): 0,
    ('', 1): 1
}

Теперь это похоже на большое количество данных для небольшого количества паттернов. Но для перестановки длиной n количество записей увеличивается как O(n^2), а количество вызовов для заполнения увеличивается как O(n^3). (Любой читатель с орлиными глазами может выяснить, как его заполнить вовремя O(n^2). Я собираюсь с простой версией.)


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

Предположим, что мы хотим найти перестановку ранга 4. Наш начальный список чисел (1 2 3 4). Мы можем пропустить 0 перестановок, которые начинаются с ('010', 1), и ответом будет второе из 2 с ('010', 2).

Возьмем второе число 2, и наша частичная перестановка будет [2, и у нас есть числа (1 3 4). Мы ищем 2-й для цепочки битов '10'. Мы пропускаем 0 перестановок, которые начинаются с ('10', 1), 1 с ('10', 2) и хотим получить первое из 1 с ('10', 3).

Возьмите третье число 4, и наша частичная перестановка будет [2, 4, и у нас есть числа (1 3). Как и прежде, мы обнаруживаем, что мы хотим получить первое из 1 с ('0', 1).

Возьмите первое число 1, и наша частичная перестановка будет [2, 4, 1, и у нас есть числа (3). Выборов не так много.

Итак, мы заканчиваем и получаем [2, 4, 1, 3]. Что вы можете проверить это 4-й.

И так мы заканчиваем с [2, 4, 3, 1].


Мы также можем пойти другим путем. Взяв ту же перестановку, мы начинаем с [2, 4, 3, 1] и хотим получить его ранг.

Сколько перед ним, которые отличаются первой цифрой? Он использовал 2-й возможный первый номер. Из записи для ('010', 1) мы знаем, что их 2. И оставшиеся цифры: 1 3 4.

Сколько перед ним, которые отличаются второй цифрой? Он использует 3-й возможный второй номер. Из записей для ('10', 1) и ('10', 2) мы знаем, что перед ним еще 1.

Теперь у нас есть номера 1 3. Никто не дошел до него в третьей цифре. И опять ни одного в последнем.

С 3 перед ним, он должен иметь ранг 4.


И вот оно у вас. Для запоминания одной рекурсивной функции вы теперь можете легко найти перестановки по рангу или ранжировать данную перестановку.

...