Ich war überrascht, eine nette Rezension zu erhalten, als ich Python an CheckIO und seine Erklärung schrieb

Als ich auf den Code zurückblickte, den ich vor mehr als zwei Jahren in Python auf einer Programmierseite namens CheckIO geschrieben hatte, war ich ein wenig beeindruckt von dem Vorschlag des Refactorings und teilte ihn als Erklärung mit. Machen.

Die Antwort auf die Frage und der daraus resultierende Thread sind nur für die Person sichtbar, die das Problem gelöst hat Es scheint, dass ich es hier kopieren werde. Alle folgenden Zitate stammen aus dieser Ausgabe und diesem Thread.

Problem

Da das Labyrinth in einer zweidimensionalen Anordnung von "0" und "1" passiert wird, ist der Pfad, der zuerst "(10, 10)" von den Koordinaten von "(1, 1)" des Labyrinths erreicht, "N", "S". Rückgabe als Zeichenfolge bestehend aus "E", "W". "0" steht für den Boden und "1" für die Wand. N steht für oben, S steht für unten, E steht für rechts und W steht für links. Diese Figur dreht sich alles um. Es kann mehrere Routen geben, aber Sie müssen nur eine Route zurückgeben, die schließlich das Ziel erreicht.

problem.png

Meine (nicht gute) Antwort

Ich wollte sowieso nicht tippen, also hielt ich die Antwort kurz.

python:answer.py:


def checkio(data):
    result = []
    dirs = [[-1, 0, "W"], [+1, 0, "E"], [0, -1, "N"], [0, +1, "S"]]
    def move(path, x, y, field):
        field[y][x] = 1
        if x == 10 and y == 10:
            result.append(path)
        for d in dirs:
            if field[y + d[1]][x + d[0]] == 0:
                move(path + d[2], x + d[0], y + d[1], field)
    move("", 1, 1, data)
    return result[0]

Kommentar

Eine typische rekursive Füllsuche. Die Verschiebungsfunktion verwendet die bisher zurückgelegten "Pfade", den "Suchursprung" und das "Feld" als Argumente und ruft die Verschiebungsfunktion rekursiv für alle ** Stockwerke ** nach oben, unten, links und rechts auf. Die Verschiebungsfunktion malt den Pfad, den Sie in eine "Wand" gegangen sind (Feld [x] [y] = 1), neu, damit Sie den Pfad, von dem Sie gekommen sind, nicht zurückdrehen. Wenn Sie das Ziel erreicht haben, fügen Sie es als Zielkandidaten zum Ergebnisarray hinzu. Dadurch werden alle Richtungen, die das Ziel erreichen können, in das Array eingefügt. Geben Sie am Ende den Anfang und das Ende zurück. Normalerweise ist es üblich, mit Dyxtra oder A * ohne Verschwendung zu suchen, aber da ich es trotzdem kurz geschrieben habe, passt es in 12 Zeilen.

Bewertung erhalten

Obwohl diese Antwort selbst etwas verwirrend ist, scheinen einige Leute in der Lage zu sein, das Problem zu lösen, das zunächst ärgerlich schien, und ich erhielt die meisten Stimmen unter den Antworten auf diese Antwort.

voted.png

Teilweise wegen der Aufregung des Threads lieferte veky eine höfliche Überprüfung und Umgestaltung. Das Hauptthema ist von hier.

veky.png

Da die Antwort auf Englisch ziemlich lang ist, werde ich nur den wichtigen Teil der Antwort erklären.

Die Antwort, die er gegeben hat, ist:

python:answer.py:


def checkio(data):
    def move(path="", x=1, y=1):
        data[y][x] = 1
        if x == y == 10:
            yield path
        for x, y, way in (x-1,y,"W"), (x+1,y,"E"), (x,y-1,"N"), (x,y+1,"S"):
            if not data[y][x]:
                yield from move(path + way, x, y)
    return next(move())

Es wurde auf 9 Zeilen reduziert. Die Punkte, die verbessert wurden, sind wie folgt.

Verwenden Sie Standardargumente

Python kann den Argumentwert angeben, wenn das Argument weggelassen wird, indem = und die rechte Seite zur formalen Argumentliste der Funktion hinzugefügt werden.

Verwendung eines Mehrzeitvergleichs

Im Fall von Python können Sie mehrere Begriffe gleichzeitig vergleichen. Die Anweisung "x == 10 und y == 10" kann mechanisch als "x == y == 10" umgeschrieben werden.

Verwendung des Generators

Grob gesagt ist die Generator-Anweisung in Python eine Variante der Funktion, die "Yield" anstelle von "Return" verwendet. Wenn Sie "Yield" in eine Funktion schreiben, wird die Funktion als ** Generatorgenerierungsfunktion ** interpretiert, die das Argument für Yield zurückgibt. Wenn Sie der Funktion einen Wert geben und ihn aufrufen, wird ein ** Generator ** generiert. Jedes Mal, wenn die Funktion next () aufgerufen wird, wird der Generator von der Innenseite der Funktion bis zur nächsten Ausbeute ausgeführt. Es ist üblich, die Funktion "next ()" aufzurufen und zu stoppen, wenn die Ausnahme "StopIteration" ausgelöst wird. In Python können Sie also einfach alle Elemente lecken, indem Sie der Anweisung "for" einen Generator geben.

python:generator.py:


def fruit_generator(num):
    yield "apple: " + str(num)
    yield "banana: " + str(num)
    yield "orange: " + str(num)

for fruit in fruit_generator(3):
    print(fruit)

:Ausführungsergebnis:


apple: 3
banana: 3
orange: 3

Wenn Sie eine Verarbeitung wiederholen, möchten Sie häufig, dass die Funktion einzelne Zustände hat, aber Sie möchten sie nicht von außen übergeben. Normalerweise ist es ehrlich, eine Klasse zu definieren und als Mitglied zu haben, aber es gibt viele Fälle, in denen dasselbe durch Ausdrücken mit einem Generator erreicht werden kann und es noch übersichtlicher und in Kürze geschrieben werden kann.

Verwendung von Tapple

In Python gibt es "Liste" und "Tupel", die sich wie Arrays verhalten. Auf beide kann über Indizes zugegriffen werden, aber die Liste wird durch "[]" und das Tupel durch "()" dargestellt. list kann Elemente hinzufügen / entfernen und Werte für tiefgestellte Referenzen mit append usw. neu schreiben. Dies erwartet der Programmierer als Array.

python:list.py:


a = []
a.append(2)  # a == [2]
a.append(3)  # a == [2, 3]
a[1] = 10    # a == [10, 3]

tuple kann nicht wie append geändert oder in eine tiefgestellte Referenz umgeschrieben werden.

python:tuple.py:


a = (2,3,4)
a[2]  # 4
a.append(5)  # AttributeError: 'tuple' object has no attribute 'append'
a[1] = 3  #TypeError: 'tuple' object does not support item assignment

Wenn Sie also programmieren, können Sie als klare Botschaft ausdrücken: "Dies ist ein Wert, von dem Sie nicht erwarten, dass er während der Ausführung neu geschrieben wird."

Taple auspacken

Es ist üblich, den Wert eines Taples mehreren Variablen zuzuweisen. Sie können gleichzeitig zuweisen, indem Sie mehrere Variablen mit Kommas in den Wert der Zuweisungsanweisung schreiben.

python


tup = (1,2,3)
a, b, c = tup
print(a)  # 1
print(b)  # 2
print(c)  # 3

Dies kann auch am Anfang der for-Anweisung verwendet werden.

python


x = 0
y = 0
for x, y, way in (x-1,y,"W"), (x+1,y,"E"), (x,y-1,"N"), (x,y+1,"S"):
    print("x={x} y={y} way={w}".format(x=x, y=y, w=way))

:Ausführungsergebnis:


x=-1 y=0 way=W
x=1 y=0 way=E
x=0 y=-1 way=N
x=0 y=1 way=S

In meinem ersten Code gab es eine implizite Angabe, dass "von dem Array der Länge 3 die erste die x-Koordinate, die zweite die y-Koordinate und die dritte die Richtung ist", und der Indexzugriff wurde ursprünglich entsprechend durchgeführt. Die Assoziation zwischen nicht trivialen Zahlen und Bedeutungen (allgemein bekannt als ** magische Zahlen **) sollte nicht verwendet werden. Es ist einfacher, die Bedeutung zu vermitteln, wenn Sie jede Variable entpacken und benennen.

Verwendung der Ausbeute aus Aussage

Durch die Verwendung von "Ausbeute aus" aus Python 3.3 wird der Generator mit rekursiv prägnant ausgedrückt. Ich denke, dass viele Leute mit "Ausbeute von" nicht vertraut sind. Um es ein wenig richtig zu erklären, ist es ein Satz für die erfolgreiche Übertragung des Generators.

python:yield_from.py:


def foo():
    yield 1
    yield 2

def gen():
    for x in range(5):
        yield from foo()  #Verwenden Sie die Ausbeute von hier

d = gen()
for x in d:
    print(x)

:Ausführungsergebnis:


1
2
1
2
1
2
1
2
1
2

Obwohl es nicht in den Sinn kommt, selbst wenn es als Übertragung bezeichnet wird, wird das gleiche Ergebnis zurückgegeben, selbst wenn die Funktion "gen ()" wie folgt umgeschrieben wird.

python:without_yield_from.py:


def gen():
    for x in range(5):
        for f in foo():
            yield f

Dies ist eine nützliche Notation, wenn Sie möchten, dass stattdessen die Ergebnisse anderer (oder rekursiv selbst) Generatoren zurückgegeben werden.

Zusammenfassung

――Wenn Sie auch nur einen heiklen Code verfügbar machen, erhalten Sie möglicherweise nützliches Wissen. Lassen Sie uns diesen also immer mehr offenlegen. ――CheckIO ist ein guter Ort, um Einblicke in das Forum zu erhalten

Recommended Posts

Ich war überrascht, eine nette Rezension zu erhalten, als ich Python an CheckIO und seine Erklärung schrieb
Eine Geschichte über das Schreiben von AWS Lambda und ein wenig Abhängigkeit von den Standardwerten von Python-Argumenten
Ich habe eine Klasse in Python3 und Java geschrieben
Ein Hinweis, dem ich beim Ausführen von Python mit Visual Studio Code verfallen war
Eine Geschichte, der ich nach der SFTP-Kommunikation mit Python verfallen war
Wovon ich süchtig war, als ich Python Tornado benutzte
Ich habe schnell ein Programm geschrieben, um DI mit Python zu lernen
Wovon ich süchtig war, als der Processing-Benutzer zu Python wechselte
Ich möchte eine schöne Ergänzung zu input () in Python hinzufügen
Versuchen Sie einfach, einen Webhook mit ngrok und Python zu erhalten
Als ich versuchte, mithilfe von Anforderungen in Python zu kratzen, war ich süchtig nach SSLError, also einem Workaround-Memo
Ich war überrascht, wie man Objekte mit Python speichert, was schlank und sehr energiesparend ist.
Wovon ich süchtig war, als ich ALE in Vim für Python einführte
Ein Hinweis, von dem ich süchtig war, als ich unter Linux einen Piepton machte
Ich habe eine Funktion zum Laden des Git-Erweiterungsskripts in Python geschrieben
Ich habe versucht, mit Selenium und Python einen regelmäßigen Ausführungsprozess durchzuführen
Ein Hinweis, dem ich beim Erstellen einer Tabelle mit SQL Alchemy verfallen war
Ich habe ein Skript geschrieben, um Webseiten-Links in Python zu extrahieren
Ich war süchtig nach falschen Klassenvariablen und Instanzvariablen in Python
[Python] Ich habe eine REST-API mit AWS API Gateway und Lambda geschrieben.
Ich habe ein Skript geschrieben, um goodnotes5 und Anki bei der Zusammenarbeit zu unterstützen
Ich bin gestorben, weil ich dachte, eine Python-Klassenvariable sei eine Instanzvariable
[Python] Als ich versuchte, ein Dekomprimierungswerkzeug mit einer Zip-Datei zu erstellen, die ich gerade kannte, war ich süchtig nach sys.exit ()
Ich war überrascht, als ich mit udp Gesichtsberechtigungen vom iPad gesendet und mit Python weitergeleitet, empfangen und angezeigt habe!
Ich habe einen Code geschrieben, um die Quaternion mit Python in einen Ölerwinkel vom Typ z-y-x umzuwandeln
Als ich versuchte, Python auszuführen, wurde ich zum Microsoft Store übersprungen
Beim Versuch, Xgboost und seine Lösung zu installieren, ist ein Fehler aufgetreten
Ich war süchtig danach, eine Python-Venv-Umgebung mit VS Code zu erstellen
Wenn ich mit xonsh Screenfetch mache, kommt Python x.x heraus und es ist traurig
Ich erhalte einen UnicodeDecodeError, wenn ich versuche, mit Python sqlalchemy eine Verbindung zu Oracle herzustellen
Der Dateiname war in Python schlecht und ich war süchtig nach Import
Ich habe ein Beispiel für den Zugriff auf Salesforce mit Python und Bottle erstellt
Ich möchte eine Webanwendung mit React und Python Flask erstellen
Ich möchte eine Python-Umgebung erstellen
Was ich süchtig nach Python Autorun war
Ich habe versucht, einen periodischen Prozess mit CentOS7, Selenium, Python und Chrome durchzuführen
Wovon ich beim Erstellen von Webanwendungen in einer Windows-Umgebung abhängig war
Ich möchte nur scipy hinzufügen, aber es ist ein lustiges Memo. Ubuntu, Python 3.
Ich möchte eine Datei auf tkinter ablegen und ihren Pfad abrufen [Tkinter DnD2]
Als ich versuchte, mit Python eine virtuelle Umgebung zu erstellen, funktionierte dies nicht
Als ich mit VScode eine Verbindung zu einem entfernten Jupyter-Server herstellte, war dieser entfernt, aber lokal.
Ich möchte ein Programm ausführen und verteilen, das die Größe von Bildern in Python3 + Pyinstaller ändert
Beachten Sie, dass ich süchtig danach war, TensowFlow einzurichten
Eine Geschichte, von der ich sehr überzeugt war, als ich den Code für das Monty Hall-Problem schrieb und die Gewinnrate berechnete
Es ist ein Jahr her, seit ich in die Abteilung für Webanwendungsentwicklung gewechselt bin, also blicke ich zurück
Ein Memo, das ich schnell in Python geschrieben habe
Python: Ich konnte in Lambda rekursieren
Ein netter Nimporter, der Nim und Python verbindet
Ich möchte mit Python ein Fenster erstellen
Ich möchte ein Spiel mit Python machen
Geschrieben "Einführung in die Effektüberprüfung" in Python
Python Hinweis: Wenn Sie einer Zeichenfolge einen Wert zuweisen
Ich habe ein Skript geschrieben, um ein WordPress-Plug-In hochzuladen
Python-Memo- "wenn nicht A und B" war "wenn (nicht A) und B"
Was ich beim Update von Python 2.6 auf 2.7 gemacht habe
Ich möchte mit Python in eine Datei schreiben
Ich war nüchtern süchtig danach, awscli von einem in crontab registrierten Python 2.7-Skript aus aufzurufen
Eine Geschichte, die praktisch war, als ich versuchte, das Python-IP-Adressmodul zu verwenden
[Python] Ich möchte nur den Index verwenden, wenn ich eine Liste mit einer for-Anweisung schleife