Построить пермутер

9

Для этой задачи вы создадите функцию (ваша функция может быть полной программой), которая принимает список в качестве входных данных и возвращает перестановку этого списка. Ваша функция должна соответствовать следующим требованиям.

  • Это должно быть детерминированным.

  • Составление вашей функции с самим собой переменное число раз должно быть в состоянии получить список для любой из ее перестановок.

Это вопрос кода-гольфа, поэтому ответы будут оцениваться в байтах, причем меньше байтов будет лучше.

Дальнейшие правила

  • Вы можете взять любой тип списка, ( [Integer], [String], [[Integer]]) до тех пор , как это

    • Может быть не пустым
    • Может содержать отдельные объекты с не менее 16 возможных значений. (Вы не можете использовать Haskell [()]и заявить, что ваша функция есть id)
    • Может содержать повторяющиеся объекты (без наборов)
  • Вы можете написать программу или функцию, но должны подчиняться стандартному IO.

Специальный охотник за гарфами
источник
Но S_nэто только цикличность дляn<3
Leaky Nun
@LeakyNun, он не запрашивает единственную перестановку, которая генерирует симметричную группу: он запрашивает next_permutationфункцию.
Питер Тейлор
Достаточно ли будет переставлять только списки 0 и 1?
xnor
Я не уверен, что понимаю смысл этого ограничения. Если вы разрешаете списки логических значений, какой смысл не разрешать итерации для любых двух разных элементов?
Деннис
@ Денис Вы делаете хорошую мысль. Я буду запрещены списки логических. Или типы, которые имеют менее 16 возможных значений.
Специальный охотник за

Ответы:

4

CJam (11 байт)

{_e!_@a#(=}

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

рассечение

{      e# Define a block
  _e!  e#   Find all permutations of the input. Note that if there are duplicate
       e#   elements in the input then only distinct permutations are produced.
       e#   Note also that the permutations are always generated in lexicographic
       e#   order, so the order is independent of the input.
  _@a# e#   Find the index of the input in the list
  (=   e#   Decrement and get the corresponding element of the list
       e#   Incrementing would also have worked, but indexing by -1 feels less
       e#   wrong than indexing by the length, and makes this more portable to
       e#   GolfScript if it ever adds a "permutations" built-in
}
Питер Тейлор
источник
2

Mathematica + Combinatorica (встроенный пакет) 34 байта

19 байт для загрузки пакета и 15 для функции.

<<"Combinatorica`";NextPermutation

Применение:

%@{c, b, a}

Без встроенного, 61 байт

Extract[s=Permutations[Sort@#],Mod[s~Position~#+1,Length@s]]&

Предполагается, что Combinatorica полностью включена в Mathematica, но я думаю, что функция NextPermutation была упущена.

Келли Лоудер
источник
2

C ++, 42 байта

#include <algorithm>
std::next_permutation

Эта точная операция встроена в C ++.

orlp
источник
2
Почему пространство после #include?
Yytsi
2

JavaScript (ES6), 145 139 137 134 108 байт

Благодаря @Neil удалось сэкономить 25 байтов!

Принимает ввод в виде массива букв алфавита. Возвращает следующую перестановку как другой массив.

a=>(t=x=y=-1,a.map((v,i)=>v<a[i+1]?(t=v,x=i):y=i>x&v>t?i:y),a[x]=a[y],a[y]=t,a.concat(a.splice(x+1).sort()))

Как?

Это поколение в лексикографическом порядке, которое обрабатывает 4 следующих шага на каждой итерации:

  1. Найдите наибольший индекс X такой, что a [X] <a [X + 1]

    a.map((v, i) => v < a[i + 1] ? (t = v, x = i) : ...)
  2. Найдите наибольший индекс Y, больший чем X, такой, что a [Y]> a [X]

    a.map((v, i) => v < a[i + 1] ? ... : y = i > x & v > t ? i : y)
  3. Поменяйте местами значение [X] со значением [Y]

    a[x] = a[y], a[y] = t
  4. Сортировать последовательность от [X + 1] до конечного элемента включительно в порядке возрастания лексикографии.

    a.concat(a.splice(x + 1).sort())

Пример:

меры

демонстрация

Arnauld
источник
Разве вы не можете сортировать, а не наоборот? Также я думаю, что v<a[i+1]&&(t=v,x=i)экономит байт, и вы могли бы сделать больше экономии, используя spliceвместо двух slices.
Нил
@Neil Хороший улов!
Arnauld
Я думаю, что я также смог объединить два maps для 112 байтов:a=>(t=x=y=-1,a.map((v,i)=>v<a[i+1]?(t=v,x=i):y=i>x&v>t?i:y),a[x]=a[y],a[y]=t,t=a.splice(++x).sort(),a.concat(t))
Нейл
Я должен признать, что я не думал, что a.concat(a.splice(++x).sort())собирался работать, иначе я попытался бы это ...
Нил
@Neil Спасибо! Обновлено. (С сохранением еще 4 байтов, потому что нам не нужно t для concat () ).
Арнаулд
1

Желе , 6 байт

Œ¿’œ?Ṣ

Циклы по перестановкам в порядке убывания лексикографии.

Попробуйте онлайн!

Как это работает

Œ¿’œ?Ṣ  Main link. Argument: A (array)

Œ¿      Compute the permutation index n of A, i.e., the index of A in the
        lexicographically sorted list of permutations of A.
  ’     Decrement the index by 1, yielding n-1.
     Ṣ  Sort A.
   œ?   Getthe (n-1)-th permutation of sorted A.
Деннис
источник
1

C 161 байт

Фактический алгоритм O (n).

#define S(x,y){t=x;x=y;y=t;}
P(a,n,i,j,t)int*a;{for(i=n;--i&&a[i-1]>a[i];);for(j=n;i&&a[--j]<=a[i-1];);if(i)S(a[i-1],a[j])for(j=0;j++<n-i>>1;)S(a[i+j-1],a[n-j])}

Пример использования:

int main(int argc, char** argv) {
    int i;
    int a[] = {1, 2, 3, 4};

    for (i = 0; i < 25; ++i) {
        printf("%d %d %d %d\n", a[0], a[1], a[2], a[3]);
        P(a, 4);
    }

    return 0;
}
orlp
источник
1

Python 2 , 154 байта

x=input()
try:exec'%s=max(k for k in range(%s,len(x))if x[%s-1]<x[k]);'*2%tuple('i1kjii');x[i-1],x[j]=x[j],x[i-1];x[i:]=x[:i-1:-1]
except:x.sort()
print x

Попробуйте онлайн!

Деннис
источник
Я думаю, что это короче как функция, которая переставляет список на месте.
orlp
Я попробовал это, но execдал мне все виды ошибок в функции
Деннис
0

Желе , 10 байт

ṢŒ!Q©i⁸‘ị®

Попробуйте онлайн!

Сортировать> все перестановки> найти вход> добавить 1> индекс в "все перестановки

Дрянная Монахиня
источник
@PeterTaylor Я исправил это.
Утренняя монахиня
Есть определенные встроенные функции для перестановок (то есть вы можете просто сделать Œ¿‘œ?Ṣ). Мне не хотелось воровать, ну, в общем, тот же алгоритм.
Эрик Outgolfer
@EriktheOutgolfer это может быть немного грязно для входов, которые содержат дубликаты.
Утренняя монахиня
Хм ... наверное, у меня была версия, которая раньше работала для этого, но вы, кажется, использовали эту Qштуку. Вы все еще можете играть в гольф ṢŒ!Qµi³‘ị.
Эрик Outgolfer
0

PHP , 117 байт

Принимает ввод / вывод как строковый список строчных букв

$a=str_split($s=$argn);rsort($a);if(join($a)!=$s)for($n=$s;($c=count_chars)(++$n)!=$c($s););else$n=strrev($s);echo$n;

Попробуйте онлайн!

Йорг Хюльсерманн
источник