Ich habe versucht, die Zusammenführungssortierung in Python mit möglichst wenigen Zeilen zu implementieren

Es ist wahrscheinlich natürlich zu hören, dass meine Freunde von Zeit zu Zeit die Implementierung von Algorithmen studieren und an der Implementierung von Zusammenführungssorten arbeiten. Es wurde ein mysteriöses Spiel abgehalten, in dem es besser war, es mit so wenig Zeilen wie möglich zu implementieren, weil es eine große Sache war. Ich habe gehört, dass mein Freund es in Python machen wollte, also habe ich beschlossen, es in Python zu machen. Ich werde nicht verlieren

Regel

--Verwenden Sie ein Datenarray, in dem Zahlen von 1 bis 10 zufällig angeordnet sind.

Der Code des gemeinsamen Teils lautet wie folgt

from data import generate_data

data = generate_data() #Zahlen von 1 bis 10 sind in Stücken aufgereiht
print(data)

#Darunter implementiert

In einer anderen Datei befindet sich data.py, und die Funktion generate_data generiert dort die Daten. Die Daten sind so etwas wie "[5, 1, 3, 9, 2, 8, 7, 4, 10, 6]". Ich habe gerade den Inhalt von data.py richtig gemacht, also werde ich ihn hier weglassen.

Implementierungsergebnis

Als ich es nach den oben genannten Regeln schrieb, wurde es so.

from data import generate_data

data = generate_data() #Zahlen von 1 bis 10 sind in Stücken aufgereiht
print(data)

#Darunter implementiert
divide = lambda data: data if len(data) == 1 else [min(data), max(data)] if len(data) <= 2 else [divide([data[i] for i in range(len(data) // 2)]), divide([data[i] for i in range(len(data) // 2, len(data))])]
merge = lambda left, right: [right.pop(0) if len(left) == 0 else left.pop(0) if len(right) == 0 else left.pop(0) if left[0] < right[0] else right.pop(0) for i in range(len(left) + len(right))] if type(left[0]) is int and type(right[0]) is int else merge(left, merge(right[0], right[1])) if type(left[0]) is int else (merge(merge(left[0], left[1]), right) if type(right[0]) is int else merge(merge(left[0], left[1]), merge(right[0], right[1])))
print(merge(divide(data)[0], divide(data)[1]))

Ausgabe


[5, 1, 3, 9, 2, 8, 7, 4, 10, 6]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Es war kein Problem, auch wenn mir "Lang. In drei Zeilen" gesagt wurde. Ich werde es vorerst erklären.

Rauer Fluss

Die Zusammenführungssortierung scheint auf der "Teilungsregelmethode" zu basieren, und es scheint, dass das Datenarray einmal auf die minimale Einheit aufgeteilt ist und die Daten aus den jeweils geteilten Daten entsprechend ausgewählt, kombiniert und dann neu angeordnet werden. Die Person, die dachte Die Details des Algorithmus werden hier weggelassen, da viele Vorfahren verschiedene Dinge erklärt haben.

Das Implementierungsergebnis der obigen drei Zeilen ist also Zeile 1: Teilen Zeile 2: Beitreten Zeile 3: Ausgabe Die Rollen sind so aufgeteilt.

Beginnen wir mit "Teilen".

Implementierung von "split"

Zweck

Dies ist der betreffende Code.

"Split" -Code


divide = lambda data: data if len(data) == 1 else [min(data), max(data)] if len(data) <= 2 else [divide([data[i] for i in range(len(data) // 2)]), divide([data[i] for i in range(len(data) // 2, len(data))])]

Wenn das Datenarray "[7, 6, 3, 2, 4, 5, 1, 8]" ist, ist der Zweck des "Aufteilens" von diesem Array.

[
    [
        [6, 7],
        [2, 3]
    ],
    [
        [4, 5],
        [1, 8]
    ],
]

Dies bedeutet, dass ein Mehrfacharray mit einer solchen hierarchischen Struktur generiert wird. Teilen Sie die Mindesteinheit in zwei Hälften, sodass die Anzahl der Elemente 2 oder weniger beträgt. Wenn die Anzahl der Elemente in der Mindesteinheit 2 oder weniger beträgt, ordnen Sie sie in aufsteigender Reihenfolge an. Ich mache so etwas. Diejenigen, die in aufsteigender Reihenfolge angeordnet sind, sind ursprünglich die Rolle der "Kopplung", aber es ist zweckmäßig, dies hier zu tun, also werde ich es an dieser Stelle tun.

Umschreiben

Die "Split" -Funktion ist ursprünglich so.

Ursprüngliche Form


def divide(data):
    if (len(data) <= 2):
        return data if len(data) == 1 else [min(data), max[data]]
    else:
        half_count = len(data) // 2
        left = [data[i] for i in range(half_count)]
        right = [data[i] for i in range(half_count, len(data))]
        return [divide(left), divide(right)]

Wenn die Anzahl der Elemente 2 oder weniger beträgt, wird das Array in aufsteigender Reihenfolge zurückgegeben, und in anderen Fällen kann die obige hierarchische Struktur realisiert werden, indem in "links" und "rechts" in zwei Hälften geteilt und zurückgezogen wird. Ich werde.

Wenn Sie nach "else" die Variable "half_count" direkt mit "len (data) // 2" verwenden, können Sie die Verwendung der Variablen vermeiden. Oh, ich habe left und right nur einmal benutzt! Wenn Sie es so machen, wie es innerhalb des Rückgabepreises liegt

Der Rückgabewert ist verrückt ~


def divide(data):
    if (len(data) <= 2):
        return data if len(data) == 1 else [min(data), max[data]]
    else:
        return [divide([data[i] for i in range(len(data) // 2)]), divide([data[i] for i in range(len(data) // 2, len(data))])]

Wird sein. Ah, sowohl if als auch else haben nur einen return Satz. Es ist ein ternärer Operator und nur eine Zeile.

Es ist eine Zeile mit einem ternären Operator


def divide(data):
    return data if len(data) == 1 else [min(data), max(data)] if len(data) <= 2 else [divide([data[i] for i in range(len(data) // 2)]), divide([data[i] for i in range(len(data) // 2, len(data))])]

Es beruhigt sich auf das Gefühl. Wenn die Funktion nur eine "Rückgabe" enthält, verwenden Sie einen Lambda-Ausdruck

Machen Sie es zu einem Lambda-Stil


divide = lambda data: data if len(data) == 1 else [min(data), max(data)] if len(data) <= 2 else [divide([data[i] for i in range(len(data) // 2)]), divide([data[i] for i in range(len(data) // 2, len(data))])]

Es passt perfekt in eine Linie. Es ist schön, Wiederholungen auch in Lambda-Ausdrücken verwenden zu können.

Implementierung von "join"

Zweck

Dies ist der betreffende Code.

"Join" -Code


merge = lambda left, right: [right.pop(0) if len(left) == 0 else left.pop(0) if len(right) == 0 else left.pop(0) if left[0] < right[0] else right.pop(0) for i in range(len(left) + len(right))] if type(left[0]) is int and type(right[0]) is int else merge(left, merge(right[0], right[1])) if type(left[0]) is int else (merge(merge(left[0], left[1]), right) if type(right[0]) is int else merge(merge(left[0], left[1]), merge(right[0], right[1])))

Guhe, Nageyo ... Der Zweck des "Beitritts" ist

Daten nach der Teilung


[
    [
        [6, 7],
        [2, 3]
    ],
    [
        [4, 5],
        [1, 8]
    ],
]

Es besteht darin, die geteilten Daten in der Reihenfolge der unteren Ebene zu kombinieren und schließlich alle zu kombinieren, um zur ursprünglichen Form einer Ebene zurückzukehren. Als Fluss

Fluss 1


[
    [2, 3, 6, 7],
    [1, 4, 5, 8]
]

Fluss 2


[1, 2, 3, 4, 5, 6, 7, 8]

Und so weiter. Um diesen Fluss zu erreichen, wird die Funktion "Zusammenführen" verwendet

Ich werde so etwas tun. Es ist schwer zu verstehen, selbst wenn Sie es in Worten erklären. Schauen wir uns also den Code an.

Umschreiben

Die "Join" -Funktion ist ursprünglich so.

Ursprüngliche Form


def merge(left, right):
    if type(left[0]) is int and type(right[0]) is int: #Beides, wenn das untergeordnete Element eine Zahl ist
        result = [] #Bereiten Sie ein neues Array vor
        for i in range(len(left) + len(right)):
            # left,Wenn das richtige Element verschwindet, platzieren Sie das noch vorhandene
            if len(left) == 0:
                result.append(right.pop(0))
            elif len(right) == 0:
                result.append(left.pop(0))
            #Wenn beide noch übrig sind, platzen Sie den kleineren
            elif left[0] < right[0]:
                result.append(left.pop(0))
            else:
                result.append(right.pop(0))
        return result
    else:
        """ 
Abhängig von der Hierarchie können die untergeordneten Elemente auch auf derselben Ebene Zahlen oder Arrays sein.
Ziehen Sie sich mit dem untergeordneten Element so zurück, wie es ist
        """
        if type(left[0]) is int:
            return merge(left, merge(right[0], right[1]))
        elif type(right[0]) is int:
            return merge(merge(left[0], left[1]), right)
        else:
            return merge(merge(left[0], left[1]), merge(right[0], right[1]))

Einzelheiten zur Implementierung finden Sie in den Kommentaren. Ich habe es absichtlich mit "if-elif-else" vervollständigt. Dies bedeutet, dass Sie den ternären Operator verwenden können, um den Rückgabewert in eine Zeile zu setzen, und Sie können die Funktion auch in eine Zeile mit einem Lambda-Ausdruck schreiben, genau wie im Fall von "split"!

Als ich versuchte, "Ergebnis" in der Listeneinschlussnotation auszudrücken, war ich besorgt, dass "Pop" die Elemente richtig reduzieren würde, aber als ich es tatsächlich versuchte, nahm es richtig ab. Ich konnte den for Teil in einer Zeile mit der Listeneinschlussnotation und dem ternären Operator darstellen.

Implementierung von "Ausgabe"

Code "Ausgabe"


print(merge(divide(data)[0], divide(data)[1]))

Ursprünglich hier

data = divide(data)
print(merge(data[0], data[1]))

Und dividieren sollte nur einmal ausgeführt werden, aber wie Sie sehen können, ist es eine Verschwendung der Anzahl von Zeilen, 1 zu üben, um die Variable zu sichern, also führe ich sie zwangsweise zweimal aus. Wenn die Anzahl der Elemente ungefähr 10 beträgt, ist dies ein Fehler.

Ende

Ich bin mir sicher, dass es der Gewinncode für die Fucking Code of the Year Awards in mir sein wird. Vielen Dank.

Recommended Posts

Ich habe versucht, die Zusammenführungssortierung in Python mit möglichst wenigen Zeilen zu implementieren
Ich habe versucht, eine selektive Sortierung in Python zu implementieren
Ich habe versucht, PLSA in Python zu implementieren
Ich habe versucht, Permutation in Python zu implementieren
Ich habe versucht, PLSA in Python 2 zu implementieren
Ich habe versucht, ADALINE in Python zu implementieren
Ich habe versucht, PPO in Python zu implementieren
Ich habe versucht, TOPIC MODEL in Python zu implementieren
Ich habe versucht, Mine Sweeper auf dem Terminal mit Python zu implementieren
Ich habe versucht, einen Pseudo-Pachislot in Python zu implementieren
Ich habe versucht, Drakues Poker in Python zu implementieren
Ich habe versucht, künstliches Perzeptron mit Python zu implementieren
Ich habe versucht, GA (genetischer Algorithmus) in Python zu implementieren
Ich habe versucht, einen eindimensionalen Zellautomaten in Python zu implementieren
Ich habe versucht, die Mail-Sendefunktion in Python zu implementieren
Ich habe versucht, Harry Potters Gruppierungshut mit CNN umzusetzen
Ich habe versucht, das Blackjack of Trump-Spiel mit Python zu implementieren
Ich habe versucht, Autoencoder mit TensorFlow zu implementieren
Ich habe versucht, ein missverstandenes Gefangenendilemma in Python zu implementieren
Ich habe versucht herauszufinden, ob ReDoS mit Python möglich ist
Ich habe versucht, CVAE mit PyTorch zu implementieren
Ich habe versucht, eine Blockchain zu implementieren, die tatsächlich mit ungefähr 170 Zeilen funktioniert
Ich habe versucht, die Bayes'sche lineare Regression durch Gibbs-Sampling in Python zu implementieren
Ich habe versucht, Trumps Kartenspiel in Python zu implementieren
Ich habe versucht, das Lesen von Dataset mit PyTorch zu implementieren
Ich habe versucht, Keras in TFv1.1 zu integrieren
Ich habe versucht, CloudWatch-Daten mit Python abzurufen
Ich habe versucht, LLVM IR mit Python auszugeben
Ich möchte verschachtelte Dicts in Python zusammenführen
Ich habe versucht, die Herstellung von Sushi mit Python zu automatisieren
Ich habe versucht zu erklären, wozu der Python-Generator so einfach wie möglich ist.
Ich habe versucht, ein scheinbar Windows-Snipper-Tool mit Python zu implementieren
Ich habe versucht, die in Python installierten Pakete grafisch darzustellen
Ich möchte Timeout einfach in Python implementieren
Ich habe versucht, DCGAN mit PyTorch zu implementieren und zu lernen
Ich habe versucht, mit Blenders Python script_Part 01 zu beginnen
Ich habe versucht, eine CSV-Datei mit Python zu berühren
Ich habe versucht, Soma Cube mit Python zu lösen
Ich habe versucht, mit Blenders Python script_Part 02 zu beginnen
Ich war süchtig danach, 2020 mit Selen (+ Python) zu kratzen
Ich möchte mit einem Roboter in Python arbeiten.
Ich habe versucht zusammenzufassen, wie man Pandas von Python benutzt
Ich habe versucht, das Problem mit Python Vol.1 zu lösen
Ich habe versucht, Grad-CAM mit Keras und Tensorflow zu implementieren
Ich habe versucht, SSD jetzt mit PyTorch zu implementieren (Dataset)
Ich habe versucht, AOJs Integer-Theorie mit Python zu lösen
Ich habe fp-Wachstum mit Python versucht
Ich habe versucht, mit Python zu kratzen
[Für Anfänger von Wettkampfprofis] Ich habe versucht, 40 AOJ "ITP I" -Fragen mit Python zu lösen
Ich habe versucht, PCANet zu implementieren
Ich habe gRPC mit Python ausprobiert
Ich habe versucht, mit Python zu kratzen
Ich habe versucht, StarGAN (1) zu implementieren.
Ich habe versucht, mit Quantx eine Linie mit gleitendem Durchschnitt des Volumens zu implementieren
Ich habe versucht, die Entropie des Bildes mit Python zu finden
Ich habe versucht zu simulieren, wie sich die Infektion mit Python ausbreitet
Ich habe versucht, API list.csv mit Python aus swagger.yaml zu erstellen