Рассмотрим перестановку целых чисел 1
, ... n
, такую как эта для n = 6
:
[5,2,4,3,6,1]
Если вы рассматриваете перестановку как отображение из [1,2,3,4,5,6]
в [5,2,4,3,6,1]
, перестановка может быть разложена на непересекающиеся циклы . Цикл - это подмножество элементов, которые отображаются друг на друга. Например, 1
сопоставляется 5
, сопоставляется 6
, сопоставляется обратно 1
. Итак, один цикл есть [1,5,6]
. Другие циклы [2]
и [3,4]
. Таким образом, число циклов для этой перестановки равно 3
.
В общем, циклы перестановки являются уникальными (с точностью до порядка), и число циклов для перестановки размера n
варьируется от 1
до n
.
Соревнование
Если дана непустая перестановка, выведите количество циклов.
Входной массив , образованный n
целых чисел 1
, 2
, ..., n
, где n > 0
. Каждое целое число встречается ровно один раз. Порядок, в котором они появляются, определяет перестановку, как в примере выше.
Вместо массива вы можете использовать список, строку с разделителем между числами, отдельный ввод для каждого числа или все, что разумно.
Для перестановки размера n
вместо набора целых чисел на основе 1 1
, ... n
можно последовательно использовать набор на основе 0 0
, ..., n-1
. Если это так, пожалуйста, укажите это в своем ответе.
Код должен работать n
до , чтобы 20
в течение разумного времени, скажем , менее чем за одну минуту.
Код гольф. Все встроенные разрешены.
Контрольные примеры
Это предполагает ввод с массива на основе 1.
[1] -> 1
[3,2,1] -> 2
[2,3,4,5,1] -> 1
[5,2,4,3,6,1] -> 3
[8,6,4,5,2,1,7,3] -> 2
[4,5,11,12,7,1,3,9,10,6,8,2] -> 1
[4,2,5,11,12,7,1,3,9,10,6,8] -> 5
[5,8,6,18,16,9,14,10,11,12,4,20,15,19,2,17,1,13,7,3] -> 3
[14,5,17,15,10,18,1,3,4,13,11,16,2,12,9,7,20,6,19,8] -> 7
Связанный
В этой связанной задаче запрашиваются фактические циклы перестановок, а не их количество. Требование только количества циклов может привести к более коротким алгоритмам, которые обходят создание фактических циклов.
источник
1
, ...,n
в этом порядке. Можете ли вы уточнить, как отображение может быть входом? Это структура данных?dict
. Я хочу иметь{1: 2, 2: 1}
в качестве входа вместо[2, 1]
.Ответы:
J, 4 байта
Это предполагает, что перестановка основана на 0. Он использует встроенную
C.
функцию, которая дает список, представляющий прямую перестановку, выводит список циклов. Затем#
составляется@
на том, что возвращает количество циклов в этом списке.Попробуй это здесь.
источник
JavaScript,
9998 байтВ этом решении предполагается, что массив и его значения имеют нулевую индексацию (например,
[2, 1, 0]
).объяснение
источник
Mathematica, 45 байт
Он генерирует график и считает его связанные компоненты.
источник
Mathematica,
372827 байтСпасибо @alephalpha за сохранение 9 байт и @miles за еще 1 байт.
источник
PermutationCycles[#,Length]&
PermutationCycles
мог бы взять второй аргумент, чтобы изменить заголовок его вывода. Вы также можете использовать инфиксную нотацию для сохранения другого байта#~PermutationCycles~Length&
.#&
это немного короче, чемIdentity
. ;)Python,
776967 байтисточник
(not p[i-1])
можно сделать как0**p[i-1]
Желе,
12109 байтСохранено 1 байт благодаря @ Dennis .
Это использует перестановки на основе 1. Он работает, применяя перестановку несколько раз, пока не достигнет предыдущей перестановки, сохраняя при этом свои предыдущие значения. Отслеживая изменения, он создаст орбиту для каждого значения вдоль столбцов этой таблицы. Затем, найдя минимум или максимум каждого столбца, можно создать метку для этого цикла. Затем дедуплицируйте этот список меток и получите его длину, которая будет числом непересекающихся циклов.
Попробуй это здесь.
объяснение
источник
ị³$ÐĿ«/QL
должно сработать.Python, 64 байта
Этот гольф-код оказался идиоматичным и читабельным. Использует 0-индексацию.
Каждое значение смотрит на то, на что оно указывает и на что указывает указанное значение, и указывает на меньшее из двух. После достаточного количества повторений каждый элемент указывает на наименьший элемент своего цикла. Число отдельных элементов, на которые указывают, равно количеству циклов.
Достаточно сделать
n
итерации. В качестве альтернативы, мы можем выполнять итерации, пока список больше не изменится. Эта стратегия дала мне рекурсивную функцию той же длины, 64 байта:Сокращение составило 65 байт
Эти
set(_)
преобразования могут быть сокращены , чтобы{*_}
в Python 3.5, сэкономив 2 байта.источник
Haskell, 111 байт
Использует индексирование на основе 0
источник
1l!i|iIi!!1ll1|
Pyth, 9 байт
Использует индексы на основе 0. Попробуйте онлайн .
Как это работает
источник
JavaScript (ES6), 49 байт
Используется индексирование с нуля. Объяснение:
reduce
используется для вызова внутренней функцииg
каждого элемента массива.c
количество циклов,e
элементi
массива, индекс массива. Если элемент меньше индекса, то это потенциальный цикл - элемент используется для индексации в массиве для рекурсивного поиска следующего элемента в цикле. Если мы начинаем или заканчиваем с исходного индекса, то это новый цикл, и мы увеличиваем количество циклов. Если в какой-то момент мы найдем значение, превышающее индекс, мы посчитаем этот цикл позже.источник
[2,1,0,3,4,5]
, он вылетел с сообщением «Превышен максимальный размер стека вызовов».C, 90 байтов
Вызов
f()
с изменяемымint
массивом, 1 на основе индексации. Второй параметр - это размер массива. Функция возвращает количество циклов.Попробуйте это на Ideone .
Алгоритм:
источник
GAP , 30 байт
Прямо, второй аргумент
Cycles
дает множество, на которое должна действовать перестановка:источник