Numerazione delle permutazioni


9

La sfida

Per un dato set di n numeri interi, scrivi un programma che produrrà il suo indice lessicografico.

Le regole

  • L'input deve essere solo un insieme di numeri interi non negativi univoci separati da spazi.
  • Dovresti generare l'indice lessicografico (intervallo da 0 a n! -1 incluso) della permutazione.
  • Non è possibile utilizzare librerie di permutazioni o incorporamenti di permutazioni.
  • Non è possibile generare l'insieme di permutazioni o alcun sottoinsieme di permutazioni dell'input per aiutarti a trovare l'indice.
  • Inoltre, non è possibile incrementare o decrementare la permutazione data alla permutazione successiva / precedente (lessicograficamente).
  • Punti bonus (-10 byte) se trovi un modo per completarlo senza usare fattoriali.
  • Il tempo di esecuzione dovrebbe essere inferiore a 1 minuto per n = 100
  • Vince il codice più breve per numero di byte
  • Vincitore scelto martedì (22 luglio 2014)

Maggiori informazioni sulle permutazioni

Esempi

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
Possiamo avere più tempo fino a quando non viene scelto un vincitore? Tre giorni sono troppo poco tempo.
xnor

Risposte:


4

GolfScript, 12 (22 caratteri - 10 bonus)

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

Punti bonus per non usare fattoriali. L'input deve essere fornito su STDIN nel formato descritto nella domanda. Puoi provare il codice online .


Ahah non è proprio quello che stavo cercando quando ho detto "senza usare fattoriali" ma suppongo che conti. Kudos
Kyle McCormick,

4

CJam, 31 anni, con fattoriali

q~]{__(f<0+:+\,,(;1+:**\(;}h]:+

Perché ricevo ancora voti? La risposta GolfScript può essere riscritta in CJam con soli 23 caratteri.
jimmy23013,

6
Perché alla gente piace la tua risposta.
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

Tale leggibile. Molto integrato. Wow.

Usiamo il fatto che l'indice lessicografico di una permutazione è la somma degli elementi delle permutazioni del numero di inversioni sopra quell'elemento (valori dopo di esso ma sotto di esso) moltiplicato per il fattoriale del numero di elementi dopo di esso. Piuttosto che valutare questa espressione polinomiale termine per termine, usiamo qualcosa di simile al metodo di Horner .

Invece di passare in rassegna gli indici di array, rimuoviamo ripetutamente il primo elemento dell'elenco ed elaboriamo gli elementi rimanenti. L'espressione sorted(p).index(p.pop(0))conta il numero di inversioni oltre il primo indice assumendone la posizione nell'elenco ordinato e contemporaneamente effettuando la rimozione.

Purtroppo, ho dovuto usare Python 2 e prendere altri 4 caratteri per raw_input(sebbene -1 per print) perché in Python 3 map(int,...)produce un oggetto mappa, che non supporta le operazioni di elenco,


1

Pyth (13 = 23-10)

JVPwdWJ=Z+*ZlJXovNJ;J)Z

Una porta della mia risposta Python .

Una traduzione Python (con alcune cose irrilevanti filtrate):

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)

I numeri di input rimangono stringhe ma vengono ordinati come ints usando eval come chiave. L'elenco è invertito in modo da popprendere il fronte anziché il retro.


1

Cobra - 202

Ovviamente Cobra non sta davvero competendo in questo.

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])

0

J, 5 byte (15-10)

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

Funziona in tempo O ( n 2 ) ed è in grado di gestire facilmente n = 100.

uso

   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

Spiegazione

#\.#.+/@(<{.)\.  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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.