Merge Sort ist ein Sortieralgorithmus, bei dem eine bestimmte Liste in zwei Hälften geteilt, beide kleineren Listen rekursiv sortiert und zu einer sortierten Liste zusammengeführt werden. Der Grundfall der Rekursion trifft auf eine Singleton-Liste, die nicht weiter aufgeteilt werden kann, sondern per Definition bereits sortiert ist.
Die Ausführung des Algorithmus in der Liste [1,7,6,3,3,2,5]
kann folgendermaßen visualisiert werden:
[1,7,6,3,3,2,5]
/ \ split
[1,7,6,3] [3,2,5]
/ \ / \ split
[1,7] [6,3] [3,2] [5]
/ \ / \ / \ | split
[1] [7] [6] [3] [3] [2] [5]
\ / \ / \ / | merge
[1,7] [3,6] [2,3] [5]
\ / \ / merge
[1,3,6,7] [2,3,5]
\ / merge
[1,2,3,3,5,6,7]
Die Aufgabe
Schreiben Sie ein Programm oder eine Funktion, die eine Liste von ganzen Zahlen als Eingabe verwendet und die verschiedenen Partitionen dieser Liste visualisiert, während sie nach einem Sortieralgorithmus für das Zusammenführen sortiert werden. Dies bedeutet, dass Sie kein Diagramm wie oben ausgeben müssen, aber nur die Listen sind in Ordnung:
[1,7,6,3,3,2,5]
[1,7,6,3][3,2,5]
[1,7][6,3][3,2][5]
[1][7][6][3][3][2][5]
[1,7][3,6][2,3][5]
[1,3,6,7][2,3,5]
[1,2,3,3,5,6,7]
Darüber hinaus ist jede vernünftige Listennotation in Ordnung, daher wäre auch Folgendes eine gültige Ausgabe:
1 7 6 3 3 2 5
1 7 6 3|3 2 5
1 7|6 3|3 2|5
1|7|6|3|3|2|5
1 7|3 6|2 3|5
1 3 6 7|2 3 5
1 2 3 3 5 6 7
Schließlich liegt es an Ihnen, eine Liste in zwei kleinere Listen aufzuteilen, solange sich die Länge der beiden resultierenden Listen höchstens um eins unterscheidet. Das heißt, anstatt [3,2,4,3,7]
in [3,2,4]
und [3,7]
aufzuteilen, können Sie auch aufteilen, indem Sie jedes Mal Elemente mit geraden und ungeraden Indizes ( [3,4,7]
und [2,3]
) verwenden oder die Aufteilung nach dem Zufallsprinzip vornehmen.
Das ist Code-Golf , also gewinnt der kürzeste Code in jeder Sprache, gemessen in Bytes.
Testfälle
Wie oben erwähnt, liegt das tatsächliche Format und die Möglichkeit, Listen in zwei Hälften zu teilen, bei Ihnen.
[10,2]
[10][2]
[2,10]
[4,17,1,32]
[4,17][1,32]
[4][17][1][32]
[4,17][1,32]
[1,4,17,32]
[6,5,4,3,2,1]
[6,5,4][3,2,1]
[6,5][4][3,2][1]
[6][5][4][3][2][1]
[5,6][4][2,3][1] <- Important: This step cannot be [5,6][3,4][1,2], because 3 and 4 are on different branches in the the tree
[4,5,6][1,2,3]
[1,2,3,4,5,6]
quelle
[[1,2],[3],[4,5],[6]]
Bühne ist eigentlich die richtige Lösung, da die Sortierung beim Zusammenführen rekursiv funktioniert. Das heißt , wenn wir beginnen mit[1,2,3,4,5,6]
und teilen Sie es in[1,2,3]
und[4,5,6]
, dann werden diese Listen unabhängig voneinander verarbeitet , bis sie im letzten Schritt zusammengeführt werden.[3]
und aufteilen[2,1]
, befinden sich diese auf verschiedenen Zweigen, sodass wir nicht zusammenführen können[3]
und[2]
danach[2,1]
in[2]
und aufgeteilt wird[1]
.Antworten:
Haskell ,
137128127125121109106 Bytes(-2) + (- 4) = (- 6) Bytes dank nimi ! Wenn Sie es ändern, um alle Schritte in einer Liste zu erfassen (erneut aufgrund von nimi), werden 12 weitere Bytes gespart.
Weitere 3 Bytes aufgrund von Laikoni , mit Pattern-Guard-Bindung und einer geschickten Verwendung des Listenverständnisses zum Codieren des Guard.
Probieren Sie es online!
Das Aufteilen der Listen in ungerade und gerade positionierte Elemente ist ein kürzerer Code als das Aufteilen in zwei aufeinanderfolgende Hälften, da wir das
length
dann nicht messen müssen.Arbeitet, indem die Listen "gedruckt" werden, dann mit den geteilten Listen (
x >>= h
) wiederholt wird, wenn tatsächlich eine Teilung durchgeführt wurde, und die sortierten Listen "gedruckt" werden; beginnend mit der einen Eingabeliste; Annahme der nicht leeren Eingabe. Und anstatt zu drucken, sammeln Sie sie einfach in einer Liste.Die Liste, die von
g[[6,5..1]]
Zeile für Zeile gedruckt wird, lautet:quelle
p=print
und dreimalp
. Probieren Sie es online!g
Sie alle Schritte in einer Liste sammeln und zurückgeben. Probieren Sie es online!g x|y<-x>>=h=x:[z|x/=y,z<-g y++[sort<$>x]]
spart etwas mehr Bytes.Wolfram Language (Mathematica) ,
146127111102 BytesProbieren Sie es online!
Gibt ein zurück
List
, das die Schritte enthält.Erläuterung
Teilen Sie in einer Eingabe alle auf
List
s, die 2 oder mehr Ganzzahlen enthalten, in zwei Hälften. Die erste Unterliste enthält die ungeradzahligen Elemente (1-indiziert) und die zweite die geradzahligen Elemente.Wiederholen Sie dies, bis sich nichts mehr ändert (dh alle Unterlisten haben die Länge 1). Behalten Sie alle Zwischenergebnisse bei. Speichern Sie diese (die
List
aller Schritte) inu
.Löschen Sie das letzte Element von
u
und kehren Sie es um.Sortieren Sie aus dem obigen Ergebnis alle Vorkommen einer Liste von ganzen Zahlen.
quelle
Sauber ,
228206168157140121104 BytesErstellt die Liste der Stufen von den Enden nach innen unter Verwendung der Tatsache, dass das
n
-te Element vom Ende die sortierte Version von istn
-ten Elements vom Anfang ist.Idee aus dem Kommentar von JungHwan Min
Probieren Sie es online!
quelle
Charcoal ,
145133123122 BytesProbieren Sie es online! Link ist eine ausführliche Version des Codes.
Immer noch um Holzkohle-Bugs herumarbeiten müssen ...Bearbeiten: 5 Bytes gespart, indem ein DoubleMap
als Array-Verständnis eines armen Mannes verwendet wird. 4 Bytes wurden mit gespeichert,Pop
um die Iteration über ein Array zu verdoppeln. 3 Bytes durch Verkettung anstelle von gespeichertPush
. Es wurden 10 Byte eingespartwhile
, indem ein besserer Golf- Zustand erreicht wurde, der auch einen Charcoal-Bug vermeidet. 1 Byte gespart, indem festgestellt wurde, dass Charcoal tatsächlich einen Filteroperator hat. Erläuterung:Teilen Sie die Eingabe in Leerzeichen auf und verpacken Sie das Ergebnis in ein äußeres Array
q
.Wiederholen, während das erste Element von
q
mehr als ein Element hat. (Das erste Element vonq
hat aufgrund der Zweiteilung der Listen immer die meisten Elemente.)Drucken Sie die Elemente der Verbindung
q
mit Leerzeichen und vertikalen Linien. (Das Array bewirkt, dass das Ergebnis in einer eigenen Zeile gedruckt wird. Es gibt andere Möglichkeiten, dies bei gleicher Bytezahl zu erreichen.)Erstellen Sie eine Liste, indem Sie jedes Element von duplizieren
q
, dann über diese Liste mappen und die Hälfte jeder Liste (unter Verwendung des alternativen Elementansatzes) nehmen und das Ergebnis wieder in speichernq
.Drucken Sie die Elemente der Verbindung
q
mit Leerzeichen und vertikalen Linien. Momentan sind die Elemente vonq
entweder leere Listen oder Listen mit einzelnen Elementen. Wenn Sie sie verbinden, werden sie einfach in leere Zeichenfolgen oder ihre Elemente konvertiert. Die leeren Zeichenfolgen würden unnötige nachgestellte Zeilen hinzufügen, damit sie herausgefiltert werden. Ein Flachmann wäre allerdings golfer gewesen (so etwas wie⟦⪫Σθ|⟧
).Wiederholen, während
q
mehr als ein Element hat. (Der folgende Code erfordert eine gerade Anzahl von Elementen.)Kopieren
q
nachh
, jedoch rückgängig gemacht (siehe unten) undq
auf eine leere Liste zurücksetzen .Wiederholen, bis
h
leer ist.Extrahieren Sie das nächste Element von
h
ine
. (Pop
Auszüge aus dem Ende, weshalb ich umkehren mussq
.)Initialisieren Sie
z
auf eine leere Liste.Schleife über die Elemente des nächsten Elements von
h
.Kopieren Sie
e
aufd
und setzen Siee
auf eine leere Liste.Schlaufe über die Elemente von
d
.Schieben Sie sie auf
z
odere
abhängig davon, ob sie kleiner als das aktuelle Element des nächsten Elements von sindh
.Schieben Sie das aktuelle Element des nächsten Elements von
h
nachz
.Verketten Sie
z
mit allen Elementen, die noch enthalten sind,e
und verschieben Sie diese aufq
. Damit ist die Zusammenführung von zwei Elementen von abgeschlossenh
.Drucken Sie die Elemente der Verbindung
q
mit Leerzeichen und vertikalen Linien.quelle
while (...Map(...)...)
bug I already told you about.Python 2,
145144 bytesIdea from JungHwan Min's comment
-1 byte thanks to Jonathan Frech
Try it online!
quelle
<2
instead of==1
.JavaScript (ES6), 145 bytes
Takes input as an array within an array, i.e.
f([[6,5,4,3,2,1]])
. Works by generating the first and last lines of the output, then splitting and calling itself again, until every sub-array has length 1. Here's a basic demonstration of how it works:quelle
Husk, 14 bytes
Takes an array containing a single array. Try it online!
Explanation
The built-in
½
takes an array and splits it at the middle. If its length is odd, the first part is longer by one element. A singleton array[a]
results in[[a],[]]
and an empty array[]
gives[[],[]]
, so it's necessary to remove the empty arrays before applyingU
.quelle
Stax,
116(÷3>)3829 bytesCP437-9 bytes per comment by @recursive. Now the input is given as a singleton whose only element is an array of the numbers to be sorted.
Try it online!
Unpacked version with 35 bytes:
Explanation
The code can be splitted to two parts. The first part visualizes splitting and the second visualizes merging.
Code for visualizing splitting:
The code for visualizing merging:
Old version, actually building the nested list structure.
cc0+=
is used thrice in the code to check whether the top of stack is a scalar or an array.{{cc0+=!{x!}Mm',*:}}X
builds a block that recursively calls itself to output a nested array of numbers properly. (Default output in Stax vectorizes a nested array before printing).There are two other blocks that performs the splitting and the merging, respectively. They are too verbose and I don't care to explain (there are a little bit more information in the historical version of this post but don't expect too much).
quelle
cH!
can be used in place ofcH%!
.{Nd}M
can be replaced byT
also.