Zusammenführen, sortieren
In dieser Challenge implementieren Sie die Merge-Subroutine von merge sort. Insbesondere müssen Sie eine Funktion oder ein Programm, ein Verb oder Ähnliches erstellen, das zwei Listen verwendet, die in aufsteigender Reihenfolge sortiert sind, und diese in einer Liste zusammenfasst, die in aufsteigender Reihenfolge sortiert ist. Bedarf:
- Ihr Algorithmus muss eine asymptotisch lineare Zeit in der Größe der Eingabe benötigen. Bitte geben Sie keine O (n ^ 2) -Lösungen mehr an.
- Sie dürfen keine integrierten Funktionen verwenden, mit denen eine Liste sortiert oder zusammengeführt werden kann. Ermessen des Autors.
- Der Code sollte in der Lage sein, wiederholte Elemente zu verarbeiten.
- Mach dir keine Sorgen über leere Listen.
Beispiele:
merge([1],[0,2,3,4])
[0,1,2,3,4]
merge([1,5,10,17,19],[2,5,9,11,13,20])
[1, 2, 5, 5, 9, 10, 11, 13, 17, 19, 20]
Das ist Code-Golf , also kann der kürzeste Code gewinnen!
b=a;b=b.length
könnte das gesamte Array duplizierena
(und zu O (n ^ 2) -Zeit führen, wenn es für jedes Element ausgeführt wird) oder nur den Verweis auf das Array duplizieren (O (n) -Zeit). Welches zählt?Antworten:
Rebmu (
3532 Zeichen)Prüfung
Über
Rebmu ist ein Dialekt von Rebol, der es erlaubt, in Situationen, die Kürze erfordern, regulären Code zu „mushen“. Unmushed funktioniert der Code wie folgt:
Ich glaube, dass dies die O (n) -Anforderung erfüllt, da der till-Block höchstens so oft wie die Länge der Eingabe durchgeschleift wird (und
reverse
nur die Reihenfolge des Containers der Eingabeblöcke ändert, nicht die Blöcke selbst). Verwendentake
ist vielleicht eine Freiheit, aber immer noch ein kleiner Effizienzschaden.Rebol (
8375 Zeichen)Nur ein kleines bisschen anders: In Rebol sind Pfade ein kürzerer Ausdruck als
first
odersecond
.a
ist der Eingabeblock, der die beiden Blöcke enthält:quelle
OP's Lösungen:
Haskell
494440Python
1311051019993Mit Dank an @Evpok:
quelle
a%b=a++b
nach dem Hauptmustervergleich schreiben , um leere Listen zu bearbeiten, die einige Zeichen abschneiden.Python (79)
Python (95, wenn wir keinen Generator zurückgeben dürfen)
Itertools ist die Lösung für alle weltweiten Probleme.
Bonus: Die beiden arbeiten an einer beliebigen Anzahl von Listen und sorgen sich um leere Listen (wie in, nehmen sie gerne 2 leere Listen und geben eine leere Liste zurück oder nehmen 1 leere und 1 nicht leere Liste, und sie werden die nicht leere zurückgeben. Ein weiteres zusätzliches Merkmal der 2 nicht ergebenden: Sie werden auch ohne Argumente ausgeführt und geben nur eine leere Liste zurück.)
Ungolfed:
quelle
r+=[...]
anstelle vonr.append(...)
(spart jedes Mal 4 Zeichen)C - 75
Dies funktioniert auf
NULL
terminierten Arrays vonint *
, obwohl es für Zeiger auf andere Typen genauso gut funktionieren würde, wenn die entsprechende Vergleichsfunktion für**b < **a
(zstrcmp(*b, *a) < 0
. B. ) eingesetzt würde.Ungolfed:
quelle
Golfscript,
2927302926 Bytesoder
Wie es funktioniert
Der Befehl
wird wie folgt verarbeitet:
Die Ausgabe ist:
quelle
[1 1 1 ... 2]
und[1 1 1 ... 3]
), da das Vergleichen der Arrays (und nicht ihrer ersten Elemente) in diesem Fall sehr langsam wäre.J -
4233Geänderte Version von hier + der Kommentar von @algorithmshark
k
Stellt den Kopf des rechten Arrays vor die zusammengeführten Endpunkte beider Arrays.k~
ist das gleiche, aber mit umgedrehten Arrays.(>&{.)
vergleicht die Köpfe. Der Code wird einen Fehler auslösen, wenn eines der Arrays leer ist. In diesem Fall geben wir nur ihre Verkettung zurück,
.quelle
/:~ a,b
die verbotene Antwort (zusammen mit[:/:~,
) ist, für die kürzeste Antwort schießen, die es nicht gibt/:
, oder?m=:k~`k@.(>&{.)`,@.(0=*&#)
spart 2 Zeichenk=:(m}.),~0{]
undm=:k~`k@.(>&{.) ::,
. Wir verwenden,0{
um einen Fehler zu werfen, wenn die Liste leer ist, und diesen Fehler dann abzufangen und mit zu beenden,
.JavaScript (ES6),
69 bis79 ByteWie es funktioniert
quelle
<
Operator ist nicht gültig, da hier ein Stringvergleich durchgeführt wird:f([123, 456, 789], [1, 2, 3, 4, 5]) => [1, 123, 2, 3, 4, 456, 5, 789]
[]
und das anschließende Umwandeln in einen String erfordert O (n) Zeit. Dies einmal für alle n Elemente des Arrays zu tun, benötigt O (n ^ 2) Zeit.Python
(63) (69)(71)Ich habe dies geschrieben, bevor ich die Kommentare von OP zu den Laufzeiten anderer Antworten gesehen habe. Dies ist also eine andere Lösung, die O (n) im Algorithmus, aber keine Implementierung ist.
quelle
return[a.pop(0)]+(a and m(a,b)or b)
Haskell, 35 Bytes
Haskell, 30 Bytes (nicht konkurrierend)
Diese nicht konkurrierende Version garantiert nur dann eine lineare Laufzeit, wenn
a
undb
mit disjunkten Elementen. Andernfalls wird es weiterhin ordnungsgemäß ausgeführt, es wird jedoch möglicherweise eine quadratische Zeit verwendet.quelle
PHP
91 9891 Bytesedit # 1: Leer
$b
erfordert eine zusätzliche Bedingung in den geschweiften Klammern (+7).edit # 2: Minor Golfings
edit # 3: Zweite Version hinzugefügt
ziemlich einfach. Der schönste Teil ist der Dreiklang in der
array_shift
(was fehlschlägt, wenn Sie es ohne die Locken versuchen)
oder
ungolfed
Prüfung
quelle
$a&(!$b|$a[0]<$b[0])?$a:$b
anstatt${$a&(!$b|$a[0]<$b[0])?a:b}
array_shift
Parameter wird als Referenz verwendet. Es muss eine Variable sein; Ein Ausdruck wird nicht funktionieren.Los, 124 Zeichen
quelle
JavaScript - 133
Gleiche Vorgehensweise wie bei OPs.
quelle
Perl, 87 Zeichen / Perl 5,14, 78 + 1 = 79 Zeichen
Diese Implementierung überlastet die Referenzen der Eingabearrays. Davon abgesehen ist es ziemlich einfach: Während beide Arrays etwas haben, verschieben Sie die untere der beiden. Geben Sie dann das zusammengeführte Bit zurück, das mit den verbleibenden Bits verbunden ist (es bleibt nur eines von @ $ x oder @ $ y übrig). Straight-Up Perl5, 87 Zeichen:
Unter Verwendung von Perl 5.14.0 und seiner neuen Arrayref-Verschiebung: 78 Zeichen + 1 Zeichen Strafe = 79 Zeichen:
quelle
*
Statt&&
wird ein Byte gespeichert. Und noch mehr, wennsub M{map{shift(!@$x+@$y*($$y[0]<$$x[0])?$y:$x)}map@$_,($x,$y)=@_}
Java: 144
Das ist ziemlich einfach. Eine Funktion, die zwei Arrays verwendet und eines zurückgibt, die zusammengeführte Version, golfen und ohne Compilation-Wrapper:
Ungolfed (mit kompilierbarem und lauffähigem Wrapper):
Beispielausführungen:
Alle Tipps zu verkürzen wäre dankbar.
quelle
Scala, 97 Bytes
Rekursive Lösung mit O (n). Um den Code zu verkürzen, wird manchmal eine Operation durchgeführt, indem die 2 austauschbaren Parameter umgeschaltet werden, dh f (a, b) ruft f (b, a) auf.
Ungolfed:
quelle
APL (32)
Erläuterung:
quelle
LISP, 117 Bytes
Der Algorithmus endet in
n + 1
Iterationen, wobein
die Länge der kürzesten Liste in der Eingabe ist.quelle
PYG (50)
PYG (wieder 64, wenn keine Generatoren erlaubt sind.):
Eine Anpassung von meiner Python Antwort .
quelle
Python - 69 Bytes
Wenn die Reihenfolge von Eingabe und Ausgabe absteigend wäre, könnte dies auf 61 Byte verkürzt werden :
Und weiter bis zu 45 Bytes, wenn Generatoren erlaubt sind:
quelle
pop(0)
in O (1)+=
implementiert werden können und zumindest besser als O (n) implementiert werden können (siehe den Link). Übrigens, Ihre Lösung verwendet+=
(dhappend
undextend
) so oft wie meine. Wie auch immer, all das ist eine Implementierungsfrage (soweit ich weiß), also ist meine Funktion in einer (fiktiven) Python-Implementierung, in der Listen als Listen implementiert werden, O (n). Schließlich musste bei Ihrer Frage der Algorithmus O (n) sein, und meiner ist.Perl 6: 53 Zeichen
Verschieben Sie den Wert von
a
oderb
mit dem kleineren Wert, bisa
XORb
(a^b
) wahr ist. Geben Sie dann alles zurück, was noch übrig ist, und reduzieren Sie[]
die Arrays in der Liste (a[],b[]
).Unter der Annahme, dass die Verschiebung vom Anfang eines Arrays an O (n) ist, sind zwei Vergleiche und eine Verschiebung pro Element der schlimmste Fall, sodass der Algorithmus O (n) ist.
quelle
JavaScript (ES5)
908690 Bytesedit: (90 -> 86) Verschob den Ternären in die for-Schleifenbedingung. Idee von Dennis gestohlen.
edit: (86 -> 90) Die Umwandlung von Array in String wurde entfernt, da das O (n) gebrochen wird -Anforderung verletzt.
quelle
Mathematica,
137,135Eingang:
Ausgabe:
Ungolfed:
Könnte es wahrscheinlich besser machen.
quelle
m[a:{x___,y_},b:{___,z_}]:=If[y<z,b~m~a,{x}~m~b~Join~{y}];{}~m~b_=b;
R 80
Gleiche Lösung wie in Scala und anderen Sprachen. Ich bin mir nicht so sicher, ob x [-1] O (1) ist.
quelle
Mathematica, 104 Bytes
Anonymous-Funktion, speichert die Länge der beiden Eingabelisten in den Variablen
m
undn
dann ist jede Iteration derDo
SchleifeSow
ein Element einer der Listen, die den Zähler für diese Liste erhöhen (i
für die erste,k
für die zweite) um eins wird. Wenn einer der Zähler die Länge der Liste überschreitet, wird dieIf
Anweisung immerSow
das Element aus der anderen Liste sein. Nach dern+m
Operation sind alle Elemente erledigt.Reap
oder vielmehr[[2,1]]
ist ein Teil seiner Ausgabe eine Liste von Elementen in der Reihenfolge, in der sie warenSow
n waren.Ich bin mir der Interna nicht sicher (greift auf einen Teil einer Liste zu)
O(1)
Operation oder nicht), aber die Timings auf meinem Computer sahen in Bezug auf die Länge der eingegebenen Liste recht linear aus.quelle