Ich soll eine Liste von Zahlen sortieren, aber ich bin super faul. Es ist wirklich schwer herauszufinden, wie man alle Zahlen vertauscht, bis sie alle in aufsteigender Reihenfolge vorliegen. Deshalb habe ich einen eigenen Algorithmus entwickelt, der sicherstellt, dass die neue Liste sortiert ist¹. So funktioniert das:
Für eine Liste der Größe N benötigen wir N-1 Iterationen. Bei jeder Iteration
Überprüfen Sie, ob die N-te Zahl kleiner als die N + 1-te Zahl ist. Wenn dies der Fall ist, sind diese beiden Zahlen bereits sortiert, und wir können diese Iteration überspringen.
Wenn dies nicht der Fall ist, müssen Sie die ersten N Zahlen kontinuierlich dekrementieren, bis diese beiden Zahlen in Ordnung sind.
Nehmen wir ein konkretes Beispiel. Angenommen, die Eingabe war
10 5 7 6 1
Bei der ersten Iteration vergleichen wir 10 und 5. 10 ist größer als 5, also dekrementieren wir es, bis es kleiner ist:
4 5 7 6 1
Jetzt vergleichen wir 5 und 7. 5 ist kleiner als 7, sodass wir bei dieser Iteration nichts tun müssen. Also gehen wir zum nächsten und vergleichen 7 und 6. 7 ist größer als 6, also dekrementieren wir die ersten drei Zahlen, bis sie kleiner als 6 sind, und wir erhalten Folgendes:
2 3 5 6 1
Jetzt vergleichen wir 6 und 1. Auch hier ist 6 größer als 1, also dekrementieren wir die ersten vier Zahlen, bis sie kleiner als 1 sind, und wir erhalten Folgendes:
-4 -3 -1 0 1
Und wir sind fertig! Jetzt ist unsere Liste perfekt sortiert. Und um die Sache noch besser zu machen, mussten wir die Liste nur N-1- mal durchlaufen , sodass dieser Algorithmus Listen in O (N-1) -Zeit sortiert. Ich bin mir ziemlich sicher, dass dies der schnellste Algorithmus ist, den es gibt.²
Ihre Herausforderung für heute ist es, diese Lazy Sort zu implementieren. Ihr Programm oder Ihre Funktion erhält ein Array von Ganzzahlen in einem beliebigen Standardformat, und Sie müssen diese verzögerte Sortierung durchführen und die neue "sortierte" Liste zurückgeben. Das Array wird niemals leer sein oder Nicht-Ganzzahlen enthalten.
Hier sind einige Beispiele:
Input: 10 5 7 6 1
Output: -4 -3 -1 0 1
Input: 3 2 1
Output: -1 0 1
Input: 1 2 3
Output: 1 2 3
Input: 19
Output: 19
Input: 1 1 1 1 1 1 1 1 1
Output: -7 -6 -5 -4 -3 -2 -1 0 1
Input: 5 7 11 6 16 2 9 16 6 16
Output: -27 -25 -21 -20 -10 -9 -2 5 6 16
Input: -8 17 9 7
Output: -20 5 6 7
Wie immer ist dies Code-Golf , schreiben Sie also das kürzeste Programm, das Sie können!
¹ Dies bedeutet nicht, wie es sich anhört, aber es ist technisch wahr
² Ich mache nur Spaß, bitte hasse mich nicht
quelle
<sarcasm>
Dieser Sortieralgorithmus wird immer noch zeitaufwändig,O(N^2)
da Sie alle zuvor aufgerufenen Elemente in der Liste durchgehen müssen, um sie zu dekrementieren. Ich empfehle stattdessen, die Liste rückwärts durchzugehen und bei Bedarf nur eine Zahl pro Schritt zu verringern. Dies wird Ihnen wahreO(N)
Komplexität geben!</sarcasm>
O(n^2)
in Bezug auf Speicherzugriffe, aber ist es nichtO(n)
für Vergleiche?O(N^2)
.Antworten:
Jelly ,
14 12 119 Bytes-2 Bytes dank ETHproductions (benutze die minimale Dyade,
«
)Ein monadischer Link, der Listen mit ganzen Zahlen aufnimmt und zurückgibt.
Probieren Sie es online! oder sehen Sie sich die Testsuite an .
Ich glaube wirklich nicht, dass dies Lazy ™ genug ist!
Wie?
quelle
Haskell , 40 Bytes
Probieren Sie es online!
quelle
JavaScript (ES6), 61 Byte
Testfälle
Code-Snippet anzeigen
quelle
Gelee , 12 Bytes
Probieren Sie es online!
Wie es funktioniert
Die Grundidee lautet: Wenn Sie die Eingabe- und Ausgabearrays vertauschen, ist die Ausgabe einfach die Eingabe, wobei jedes Delta von 0 oder höher durch -1 ersetzt wird. Zum Beispiel:
quelle
k, 20 Bytes
Probieren Sie es online aus.
Erläuterung:
quelle
Haskell, 56 Bytes
Probieren Sie es online!
Behalten Sie den ersten Teil der Liste als Parameter bei
a
. Fügen Sie bei jedem Schritt das nächste Elementx
zum Ende von hinzua
und erhöhen Sie alle Elemente von a um das Minimum von(y-x-1)
und0
.quelle
Python , 54 Bytes
Probieren Sie es online!
Nimmt eingegebenen splatted wie
f(1,2,3)
. Gibt eine Liste aus. Verwendet exponentielle Zeit.quelle
76 Bytes
Dadurch wird die Liste geändert. Es geht die Liste rückwärts durch und behält eine laufende Summe des Deltas bei, das für jede Zahl gilt.
quelle
JavaScript (ES6), 59 Byte
quelle
f=
für JS-Antwortenf(a)
), sodass der Name weiterhin benötigt wird.Brain-Flak , 153 Bytes
Probieren Sie es online!
Dies gilt auch
+1
für die-r
Flagge.quelle
R, 56 Bytes
function(s){s-c(rev(cumsum(rev(pmax(0,-diff(s)+1)))),0)}
quelle
diff
, ich habe versucht , herauszufinden, wie die zur Arbeit kommen ... By the way, können Sie loszuwerden, die Klammern um die Funktion Körper für -2 Bytes, aber besser noch, können Sies=scan()
anstelle einer Funktion Definition, um ein paar Bytes mehr zu sparen. Es wäre toll, wenn Sie einen Link zu Try it online einfügen würden, damit andere Personen überprüfen können, ob dieser Code für alle Testfälle funktioniert.JavaScript (ES6), 68 Byte
Ein- und Ausgabe ist ein Array von ganzen Zahlen.
Testschnipsel
quelle
JavaScript (ES6), 50 Byte
Erläuterung:
Dies ist eine rekursive Lösung, bei der zuerst das Array geklont und dann alle Werte verringert werden, bis ein Element größer oder gleich dem nächsten Element im Array ist.
Die Funktion ruft sich selbst auf, solange Elemente nicht in Ordnung sind. Wenn die Elemente endgültig sortiert sind, wird der Klon zurückgegeben. (Das Array selbst kann nicht zurückgegeben werden, da die
some()
Methode alle seine Elemente dekrementiert und sie alle um -1 deaktiviert hätte.)Testfälle:
quelle
SWI-Prolog, 194 Bytes
Vielleicht können Sie es hier online ausprobieren: http://swish.swi-prolog.org/p/LazySort.pl
Sie fragen,
l(L, [10,5,7,6,1]).
welche sagt "lösen für L, wobei L die träge sortierte Version dieser Liste ist".Die zwei Funktionen sind:
l
azysortiert (A, B) - gibt an, dass A die lazysortierte Version von B ist, wenn beide leere Listen sind oder wenn A durch Umkehren von B, Aufrufen einer Hilfsfunktion zum Durchlaufen der Liste und Subtrahieren mit einem Akkumulator erhalten werden kann Schieben Sie jeden Wert niedriger als den vorherigen und kehren Sie das Ergebnis wieder in die richtige Richtung um.f
Der Helfer vergleicht zwei Listen, den Wert der vorherigen Nummer in der Liste und einen fortlaufenden Differenzakkumulator, und berechnet, dass der neue Wert der aktuellen Listenposition der ursprüngliche Wert abzüglich des Differenzakkumulators ist, optional abzüglich eines neuen Werts, der erforderlich ist, um dies zu erzwingen Wert unter der vorherigen Nummer in der Liste undf
muss mit dem nun erhöhten Differenzakkumulator rekursiv nach dem Ende der Liste aufgelöst werden.Screenshot der Testfälle auf Swish:
quelle
JavaScript (ES6), 61 Byte
Nicht die kürzeste Lösung, aber ich konnte die Gelegenheit nicht nutzen
reduceRight
.quelle
C # (.NET Core) ,
89 88 8679 Bytesfor
s gespeichert .Probieren Sie es online!
Zuerst
for
durchläuft es das Array, dann berechnet es die Dekrementierung und schließlichfor
dekrementiert das zweite die Elemente, falls erforderlich, bis zuri
vierten Position.Ist es gültig, nur das ursprüngliche Array zu ändern, anstatt ein neues zurückzugeben (gewöhnt sich immer noch an die Regeln)?
quelle