Нумерация перестановок

9

Соревнование

Для данного набора из n целых чисел напишите программу, которая выведет свой лексикографический индекс.

Правила

  • Входные данные должны быть только набором уникальных неотрицательных целых чисел, разделенных пробелами.
  • Вы должны вывести лексикографический индекс (от 0 до n! -1 включительно) перестановки.
  • Никакие библиотеки перестановок или встроенные перестановки не могут быть использованы.
  • Вы не можете генерировать набор перестановок или любое подмножество перестановок входных данных, чтобы помочь вам найти индекс.
  • Вы также не можете увеличивать или уменьшать данную перестановку до следующей / предыдущей (лексикографически) перестановки.
  • Бонусные баллы (-10 байт), если вы найдете способ выполнить это без использования факториалов.
  • Время выполнения должно быть менее 1 минуты для n = 100
  • Самый короткий код по количеству байтов выигрывает
  • Победитель выбран во вторник (22 июля 2014 г.)

Подробнее о перестановках

Примеры

0 1 2 --> 0
0 2 1 --> 1
1 0 2 --> 2
1 2 0 --> 3
2 0 1 --> 4
2 1 0 --> 5
0 1 2 3 4 5 6 7 --> 0
0 1 2 3 4 5 7 6 --> 1
0 1 2 3 4 6 5 7 --> 2
1 3 5 17        --> 0
781 780 779 13  --> 23
81 62 19 12 11 8 2 0 --> 40319
195 124 719 1 51 6 3 --> 4181
Кайл Маккормик
источник
1
Можем ли мы иметь больше времени до выбора победителя? Три дня слишком мало времени.
xnor

Ответы:

4

GolfScript, 12 (22 персонажа - 10 бонусов)

~]0\.,{.,@*\.(@$?@+\}*

Бонусные баллы за неиспользование факториалов. Входные данные должны быть указаны в STDIN в формате, описанном в вопросе. Вы можете попробовать код онлайн .

Говард
источник
Ха-ха, не совсем то, что я искал, когда сказал «без использования факториалов», но я полагаю, это имеет значение. Слава
Кайл Маккормик
4

CJam, 31, с факториалами

q~]{__(f<0+:+\,,(;1+:**\(;}h]:+
jimmy23013
источник
Почему я все еще получаю upvote? Ответ на GolfScript можно переписать в CJam, используя всего 23 символа.
jimmy23013
6
Потому что людям нравится ваш ответ.
Seequ
1

Python 2 (77 = 87-10)

p=map(int,raw_input().split())
s=0
while p:s=s*len(p)+sorted(p).index(p.pop(0))
print s

Такой читабельный. Многое встроено. Ух ты.

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

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

К сожалению, мне пришлось использовать Python 2 и взять еще 4 символа для raw_input(хотя -1 для print), потому что в Python 3 map(int,...)создает объект карты, который не поддерживает операции со списками,

XNOR
источник
1

Пиф (13 = 23-10)

JVPwdWJ=Z+*ZlJXovNJ;J)Z

Порт моего Python ответа .

Перевод на Python (с некоторыми несущественными вещами, отфильтрованными):

Z=0
J=rev(split(input()," "))
while J:
 Z=plus(times(Z,len(J)),index(order(lambda N:eval(N),J),J.pop()))
print(Z)

Введенные числа остаются строками, но сортируются как целые, используя eval в качестве ключа. Список перевернут так, что popзанимает переднюю, а не заднюю часть.

XNOR
источник
1

Кобра - 202

Очевидно, что Кобра на самом деле не конкурирует в этом.

class P
    var n=0
    var t=CobraCore.commandLineArgs[1:]
    def main
        .f(.t[0:0])
    def f(l as List<of String>)
        if.t.count==l.count,print if(.t<>l,'',.n+=1)
        else,for i in.t.sorted,if i not in l,.f(l+[i])
Οurous
источник
0

J, 5 байтов (15 - 10)

#\.#.+/@(<{.)\.

Это выполняется за время O ( n 2 ) и может легко обработать n = 100.

Применение

   f =: #\.#.+/@(<{.)\.
   f 0 1 2
0
   f 0 2 1
1
   f 1 0 2
2
   f 1 2 0
3
   f 2 0 1
4
   f 2 1 0
5
   f 0 1 2 3 4 5 6 7
0
   f 0 1 2 3 4 5 7 6
1
   f 0 1 2 3 4 6 5 7
2
   f 1 3 5 17
0
   f 781 780 779 13
23
   f 81 62 19 12 11 8 2 0
40319
   f 195 124 719 1 51 6 3
4181
   NB. A. is the builtin for permutation indexing
   timex 'r =: f 927 A. i. 100'
0.000161
   r
927

объяснение

#\.#.+/@(<{.)\.  Input: array P
             \.  For each suffix of P
          {.       Take the head
         <         Test if it is greater than each of that suffix
     +/@           Sum, count the number of times it is greater
#\.              Get the length of each suffix of P
   #.            Convert to decimal using a mixed radix
миль
источник