Einführung
Die lexikographischen Permutationen einer Liste mit n Elementen können von 0 bis n nummeriert werden ! - 1. Zum Beispiel die 3! = 6 Permutationen (1,2,3)
wären (1,2,3)
, (1,3,2)
, (2,1,3)
, (2,3,1)
, (3,1,2)
, (3,2,1)
.
Wenn eine Permutation auf eine Liste angewendet wird, werden ihre Elemente in derselben Reihenfolge wie die Nummern in der Permutation sortiert. Zum Beispiel die Permutation (2,3,1)
auf l = (a,b,c)
Ausbeuten anwenden (l[2],l[3],l[1]) = (b,c,a)
.
Die Umkehrung einer Permutation ist definiert als die Permutation, die diesen Vorgang umkehrt, dh eine Permutation anwendet und dann durch ihre Umkehrung (oder umgekehrt) das Array nicht verändert. Zum Beispiel kann die Inverse von (2,3,1)
IS (3,1,2)
, da das Aufbringen (b,c,a)
Ausbeuten (a,b,c)
.
Auch die Umkehrung einer Permutation, die auf die Permutation selbst angewendet wird, ergibt die ganzen Zahlen 1… n . Zum Beispiel (3,1,2)
auf (2,3,1)
Renditen anwenden (1,2,3)
.
Wir definieren nun die Funktion revind ( x ) als Index der inversen Permutation der Permutation mit dem Index x . (Dies ist A056019 , wenn Sie interessiert sind.)
Da eine Permutation mit Index i nur die letzten k Elemente der Liste ändert, wenn 0 ≤ i < k ! Ist , können wir eine beliebige Anzahl von Elementen an den Anfang der Liste setzen, ohne revind ( i ) zu beeinflussen. Daher hat die Länge der Liste keinen Einfluss auf das Ergebnis.
Herausforderung
Ihre Aufgabe ist es, revind ( x ) zu implementieren . Sie schreiben ein vollständiges Programm oder eine Funktion, die eine einzelne nichtnegative Ganzzahl x als Eingabe / Argument verwendet und das Ergebnis als einzelne nichtnegative Ganzzahl ausgibt / zurückgibt.
Die Eingabe und Ausgabe können 0-indiziert oder 1-indiziert sein, dies muss jedoch zwischen ihnen konsistent sein.
Builtins, die Permutationen nach Index generieren, den Index einer Permutation zurückgeben oder die inverse Permutation finden, sind gesperrt. (Builtins, die alle Permutationen oder die nächste Permutation erzeugen, sind erlaubt.)
Es gelten die Standardregeln für Code-Golf .
Beispiele
Die folgenden Beispiele sind 0-indiziert.
Input Output
0 0
1 1
2 2
3 4
4 3
5 5
6 6
13 10
42 51
100 41
1000 3628
2000 3974
10000 30593
100000 303016
Referenzimplementierung (Python 3)
def revind(n):
from math import factorial
from itertools import permutations, count
l = next(filter(lambda x: factorial(x) > n, count(1)))
pms = list(permutations(range(l)))
return [k for k in range(len(pms)) if tuple(pms[n][i] for i in pms[k]) == pms[0]][0]
quelle
(a,b,c)
extrem unübersichtlich. Bitte erläutern Sie genau, was eine inverse Permutation ist.Ụ
(grade up), das die Indizes eines Arrays nach ihren entsprechenden Werten sortiert. Dies geschieht, um eine Permutation von 1, ..., n zu invertieren , funktioniert jedoch nicht für andere Permutationen. IstỤ
eine verbotene eingebaut?Antworten:
Gelee , 6 Bytes
E / A verwendet eine 1-basierte Indizierung. Sehr langsam und speicherhungrig.
Nachprüfung
Solange der Eingang 8 nicht überschreitet ! = 40320 ist es ausreichend, alle Permutationen des Arrays [1,…, 8] zu berücksichtigen . Für den letzten Testfall genügen die Permutationen von [1,…, 9] .
Mit leicht modifiziertem Code, der nur die Permutationen der ersten 8 oder 9 positiven Ganzzahlen berücksichtigt , können Sie es online ausprobieren! oder überprüfen Sie alle verbleibenden Testfälle .
Wie es funktioniert
Alternativer Ansatz, 6 Bytes (ungültig)
Es ist genauso lang und verwendet das verbotene Atom der höheren Klasse
Ụ
, aber es ist (wohl) idiomatischer.Durch das Voranstellen von 8 (oder 9 für den letzten Testfall) können wir es tatsächlich online ausprobieren !
Wie es funktioniert
quelle
Mathematica, 74 Bytes
Verwendet 1-Indizierung. Sehr ineffizient. (Verwendet ~ 11 GB Speicher, wenn der Eingang ist
11
)Erläuterung
Erstellen Sie eine Liste von 1 bis N. Speichern Sie diese in
j
.Hier finden Sie alle Permutationen von
j
. Bewahren Sie das ini
.Speichern Sie die
Position
Funktion ink
. (um die Anzahl der Bytes beiPosition
erneuter Verwendung zu verringern )Finden Sie die inverse Permutation der N-ten Permutation.
Finde das
k
(Position
) der inversen Permutation ini
(allen Permutationen)Mit eingebauten
4643 Bytes1-indiziert.
quelle
MATL , 15 Bytes
Eingang und Ausgang sind 1-basiert.
Entspricht der CJam-Antwort von @ MartinEnder, ermittelt jedoch die inverse Permutation, indem alle möglichen Permutationen mit der in der Eingabe angegebenen zusammengesetzt und die identitätsgebundene Permutation ermittelt werden.
Im Online-Compiler ist nicht genügend Speicher für die Eingabe vorhanden
10
.Probieren Sie es online!
Erläuterung
quelle
Pyth, 12 Bytes
Testsuite
0 indiziert.
Erläuterung:
quelle
05AB1E ,
1413 BytesSehr ineffizienter Speicher.Jetzt noch mehr Speicher ineffizient (aber 1 Byte kürzer).0-basierter Bereich.
Verwendet CP-1252- Codierung.
Probieren Sie es online! oder als modifizierte Testsuite
Erläuterung
quelle
CJam , 16 Bytes
Indizes sind 0-basiert.
Probieren Sie es online!
Ich werde nicht viel ineffizienter als dies ... mit Javas Standardeinstellungen für Eingaben größer als
8
(funktioniert aber im Prinzip für beliebige Eingaben bei einer ausreichenden Anzahl von Zeit- und Speicheruniversen).Erläuterung
quelle
GAP , 108 Bytes
1-indiziert. Zeilenumbrüche werden nicht gezählt, sie werden nicht benötigt. Ich muss die endgültige Funktion nicht wirklich einem Namen zuweisen, aber ...
h
ist eine Curry-Funktion, die eine Liste von Permutationen und einen Index in diese Liste aufnimmt und den Index der inversen Permission zurückgibt. Ohne Einschränkungen würde ich einfach tunPosition(l,l[n]^-1)
.f
ruft diese Funktion mit den sortierten Permutationen einer ausreichend großen symmetrischen Gruppe und der gegebenen aufn
.Ich könnte einfach schreiben
SymmetricGroup(n)
, dann könnte die Funktion für Werte bis 9 berechnet werden. Da es bereits viel kleinere Lösungen gibt, bevorzuge ich dies:Eine wirklich effiziente Lösung mit 0 Indizes, die für Argumente unter 99 geeignet ist! (und kann auf Kosten eines Bytes für Argumente unter 999 verwendet werden!)
Nach dem Löschen des Leerzeichens hat dies 255 Bytes.
quelle
JavaScript (ES6),
163120110 Byte0-indiziert. Konvertiert den Index in eine Permutation, invertiert ihn und konvertiert ihn dann zurück in einen Index. Bearbeiten: Durch
f
Invertieren und Umkehren der Permutation und anschließendesg
Zurückkonvertieren der umgekehrten Permutation in einen Index wurden ca. 25% eingespart . Es wurden weitere 10 Byte gespeichert, indem die beiden rekursiven Aufrufe zu einer einzigen Funktion kombiniert wurden. Ungolfed:quelle
f
die Permutation umkehren kann, anstattg
...J
5550 BytesBasierend auf dem J Essay on Permutation Index .
Dieser Code benötigt nur Speicher in der Größenordnung von, benötigt
n
jedoch mehr Zeit, da er die Listenzeiten sortiertn
und nachn
jedem Index durchsucht .Mit dem eingebauten Code,
/:
der den Grad einer Liste und die Umkehrung einer Permutation findet, gibt es eine 42-Byte-Lösung, die effizienter ist.Diese Version benötigt nur 44 Sekunden, um den letzten Testfall im Vergleich zu dem anderen zu berechnen, der 105 Sekunden benötigt.
Verwendung
quelle
Jelly ,
14 139 Bytes-4 Bytes dank @Dennis (den er mit dem Quick
⁺
in seiner Antwort weiter ausbaute )Eine weitere sehr langsame Implementierung.
Hier wird eine 1-basierte Indizierung verwendet, daher sind die erwarteten Ergebnisse:
Es hat keinen Sinn, einen Online-IDE-Link einzurichten, da TIO bei einem Eingang von tötet
10
. Lokale Ergebnisse (Letzteres ist sehr langsam und erfordert eine Tonne Speicher!):Wie?
Hinweis: Es ist nicht erforderlich, die Permutationen zu sortieren, da sowohl die Permutation als auch und umgekehrt in derselben Reihenfolge ermittelt werden.
quelle
ÇịịÇ$iR
?R
VorherŒ!
implizit,Œ!ịịŒ!$iR
sollte also die Arbeit erledigen.Python 2,
116114 Bytesrepl.it
0-basiert. Langsam und speicherhungrig, aber wenig Bytes.
Verwenden Sie keine Permutationsfunktionen. speicher und zeiteffizient.
289285 Bytes-4 Bytes dank @Christian Sievers (volle Permutation bereits gebildet)
Ich weiß, dass es Codegolf ist, aber ich denke, dass @ Pietu1998 auch an effizienten Implementierungen interessiert ist.
Sehen Sie es in Aktion bei repl.it
Dabei werden mehr Bytes als bei der Referenzimplementierung verwendet, verglichen mit
n=5000000
:f
ist die Rückwärtsindexfunktion.f
zuerst wird das nächste faktorielles obenn
,t
und die ganze Zahl , dessen Fakultäts das heißt,x
durch den Aufrufh(n)
und setzeng=range(x)
, die Elemente , die die Permutation bilden werden,o=g[:]
und die Permutation Halter,r=[]
Als nächstes wird die Permutation am Index konstruiert,
n
indempop
die Indizes der faktoriellen Basisrepräsentationn
der Elemente der Reihe nach aus den Elementen gebildeto
und an diese angehängt werdenr
. Die faktorielle Basisdarstellung wird durch div und mod gefundenern
mitt
denent
sich durch div'dx
undx
dekrementiert bis auf1
.Schließlich findet es den Index der umgekehrten Permutation, indem es
i
mit der umgekehrten Permutation aufruft ,[r.index(v)for v in g]
h
ist eine Doppelfunktion zum Berechnen einer Fakultät einer nicht-negativen Ganzzahl oder zum Berechnen sowohl der nächsten Fakultät über einer nicht-negativen Ganzzahl als auch der ganzen Zahl, die diese Fakultät erzeugt.In seinem Standardzustand
v=1
und tut es das letzteres durch Multiplikationv
vonx
(auch anfänglich1
) und Inkrementieren ,x
bisn
zumindest so groß ist , dann kehrt siev
undx-1
in einem Tupel.Zur Berechnung
n!
einer Anrufe ,h(n,0)
die ein Vielfachesx
(zunächst1
) durchn
und dekrementiert ,n
bisn
ist ,0
wenn er zurückkehrtx
.i
bietet die lexikographische Index einer Permutationp
, der Elemente ,[0,1,...n]
indem die Produkte der Fakultäts der Fakultäts Basis eines jeden Index nach oben,h(len(p)-j-1,0)
und wie viele Elemente auf der rechten Seite des Index kleiner als der Wert in diesem Indexsum(k<p[j]for k in p[j+1:])
.quelle
t/=x
.(r+o)
durchr
.Python 2,
130129 Bytesquelle
Eigentlich ,
1811 BytesDiese Antwort verwendet den Algorithmus in Dennis 'Jelly-Antwort , ist aber 0-indiziert. Golfvorschläge willkommen! Probieren Sie es online!
Ungolfing
quelle