Tipps zum Golfen in Pyth


46

Pyth ist eine von Python inspirierte prozedurale Programmiersprache, die vom PPCG-Benutzer isaacg erstellt wurde .

Welche allgemeinen Tipps haben Sie zum Golfen in Pyth? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme im Allgemeinen anwenden lassen, die zumindest etwas spezifisch für Pyth sind.

Ein Tipp pro Antwort, bitte.

Antworten:


25

Schreiben Sie zuerst den Code in Python

Pyth ist Python so ähnlich, dass es ziemlich einfach ist, Python-Programme in Pyth zu übersetzen. Da es sich bei Pyth jedoch um eine Sprache mit einem Buchstaben pro Befehl handelt, ist es manchmal schwierig, Pyth zu schreiben. Wenn Sie zuerst in Python schreiben, müssen Sie weniger überlegen (da Python eine ziemlich einfach zu codierende Sprache ist).


1
Sie können auch erwähnen, dass Sie in Python weiterhin Python-Syntax verwenden können, sodass Sie Teile des Programms einzeln konvertieren oder bei Bedarf einfach Python verwenden können. (Wie du es hier
getan

@ mbomb007 Laden Sie den Pyth-Interpreter herunter und lesen Sie die Dokumente durch. Nur so kann ich zuverlässig ein Pyth-Programm schreiben.
Justin

@ mbomb007 Entschuldigung; Auf diese Weise habe ich gelernt, Pyth zu schreiben (indem ich den Quellcode durchgesehen habe). Grundsätzlich gibt es keine Dokumentation zu Pyth. Sie müssen die Syntax im Grunde durch Ausprobieren lernen.
Justin

22

Kenne deine Variablen

In Pyth gibt es drei Kategorien von Variablen: generische vorinitialisierte Variablen, auf der Grundlage von Benutzereingaben vorinitialisierte Variablen und Variablen, die bei der ersten Verwendung implizit eine Zuweisung generieren.

Generische Variablen:

b = "\n"
d = " "
k = ""
G = "abcdefghijklmnopqrstuvwxyz"
H = {}                            # (empty dict)
N = '"'
T = 10
Y = []
Z = 0

Eingabeinitialisierte Variablen:

Q = eval(input())
z = input()

Beachten Sie, dass diese Initialisierungen nur in einem bestimmten Programm ausgeführt werden, wenn die zugehörige Variable außerhalb einer Zeichenfolge im Code verwendet wird. Außerdem ist die Reihenfolge Qdann z, wenn beide verwendet werden.

Zuordnung bei Erstverwendungsvariablen:

Jund K. Wenn Sie beide auf denselben Wert initialisieren möchten, können Sie einen Ausdruck wie verwenden KJ0, der dem längeren Wert entspricht J0K0.


18

Verwenden Sie den noch neueren Online-Dolmetscher , um Ihre Antworten zu testen.

Beachten Sie, dass dies eine neue Software ist und daher möglicherweise fehlerhaft ist. Bitte melden Sie mir Probleme.


2
Genial! Ich konnte das mit Google nicht finden, genau das, was ich brauchte!
Theonlygusti

12

Zeichenfolgen am Zeilenende benötigen keine Anführungszeichen. Zum Beispiel:

"Hello, world!

ist ein vollständig gültiges Hello World-Programm.


Ganz offensichtlich, es ist das erste Google-Ergebnis für "Pyth Programming Language". Hast du deine eigene Seite auf esolangs erstellt?
Theonlygusti

3
@theonlygusti Ja, ich habe. Es war auch nicht das erste Ergebnis im letzten Oktober.
Isaacg

9

Verwenden Sie diese Option Cfür die Basiskomprimierung

Dies ist tatsächlich undokumentiert. C auf einer Zeichenfolge ist tatsächlich nicht direkt chr -> int, sondern Basis 256 -> Basis 10 (was auf einer Zeichenfolge dasselbe ist). Dies ist sehr hilfreich beim Komprimieren eines Int. Wir können dieses Skript verwenden, um Folgendes zu komprimieren:

sCMjQ256

Nehmen Sie 12345678910, es ergibt sich ßÜ>(einige Unprintables drin).

Mit einem Array von Ints können Sie sie auch verketten und mit großen Zeichenfolgen, indem Sie sie in Codepunkte konvertieren und als Basis-128-Zahl behandeln.

Eine andere Verwendung von C, danke @xnor, dass Sie mir dies gezeigt haben, ist das Erstellen einer willkürlich großen Zahl. Der naive Weg ist:

^TT

Aber wir können ein Byte besser machen mit:

CG

Diese Basis 256 dekonvertiert das gesamte Alphabet. Ergebnisse 156490583352162063278528710879425690470022892627113539022649722= ~ 1.56e62.


Jetzt zum Dokument hinzugefügt.
isaacg


8

Verwenden Sie die Kurzfunktion ... err ...

Wenn die Lambda - Argument mapoder reducegilt nur einem Arbeitsgang auf die Argumente ,, können Sie die Kurzformen verwenden, Mund F. fMxist gleichbedeutend mit mfdxund fFxist dasselbe wie .UfbZx. Nehmen wir zum Beispiel an, wir nehmen eine Liste von Zahlen als Eingabe und geben jede inkrementierte Zahl aus. Ein erster Ansatz könnte sein:

mhdQ

Dies kann jedoch wie folgt umgeschrieben werden:

hMQ

Ähnliches gilt für reducemit F. Angenommen, es ist eine Herausforderung, das Produkt einer Liste von ganzen Zahlen zu berechnen. Wieder kann ein erster Versuch sein:

.U*bZQ

Mit Fkann dies jedoch verkürzt werden auf:

*FQ

Rasiert drei Bytes weg ... nicht schlecht!


Und Sie brauchen nicht Q, wie es ergänzt wird, wenn die Funktion eine Eingabe fehlt, machen es*F
Stan Strum

7

Halten Sie Ihre Pyth-Implementierung auf dem neuesten Stand.

Ich verbessere Pyth ziemlich regelmäßig, entferne weniger nützliche Funktionen und füge mehr nützliche Funktionen hinzu. Achten Sie also auf neue Funktionen und aktualisieren Sie Ihre Kopie der Implementierung regelmäßig.

Einige kürzlich hinzugefügte Funktionen: (Stand 19.10.14)

y: Funktioniert wie *2bei Zahlen und als Liste aller Teilmengen von Zeichenfolgen und Listen. Zum Beispiel:

pyth -c 'y"abc'
['', 'a', 'b', 'c', 'ab', 'ac', 'bc', 'abc']

f: fist normalerweise der Filterbefehl. Wenn es nun mit einer Zahl als zweitem Argument aufgerufen wird, filtert es über die unendliche Folge, beginnend mit dieser Zahl, und zählt sie um eins hoch, und gibt dann das erste Element der resultierenden Folge zurück.

Hier ist zum Beispiel der Code, um die kleinste Primzahl über eine Milliarde zu finden:

pyth -c 'f!tPT^T9'
1000000007

Diese sehen aus wie nützliche Ergänzungen, aber was können Sie anstelle der alten verwenden yz? mvdczdkann nicht der kürzeste Weg sein ...
Dennis

1
@Dennis Ich habe das alte weggeworfen, yweil ich nicht glaube, dass Pyth mehrere superleicht zu analysierende Eingabeformate haben muss, nur eines, zB das Python-Format. Also ja, ich denke mvdczdmuss leider machen.
isaacg

@Dennis Problem gelöst, habe dies gerade zu r's String Processing Suite hinzugefügt .
isaacg

rsieht ziemlich nützlich aus.
Dennis

@isaacg Sorry, wenn dies nicht zum Thema gehört, aber ich frage mich, wie ich die Root-Operation @in Fdr1 + 1 @ Q2Iq% Qd0d verwenden kann, um einen Faktorrechner zu erstellen. Wenn ich versuche, es zu benutzen, wird indexstattdessen die Bedeutung verwendet. Gibt es einen Weg, um dieses Verhalten zu umgehen?
StardustGogeta

5

Benannte Argumente in Funktionen (nicht mehr unterstützt)

Manchmal können Standardwerte in Funktionen zum Golfen nützlich sein. Pyth unterstützt dies tatsächlich (sehr zu meiner Überraschung). Zum Beispiel:

DC=Z1RZ;C;C5

Druckt:

1
5

Sie können dabei auch J und K verwenden, um Zeichen zu speichern:

DgJ1K1R+JKg;g2;g2 3

druckt:

2
3
5

Dies ist normalerweise nützlich für rekursive Algorithmen.

Das funktioniert nicht mehr, aber ich habe es hier gelassen, falls jemand mit einer alten Version von Pyth Golf spielen möchte.


16
Wow - Auch ich habe nicht bemerkt, dass Pyth dies unterstützt, und ich habe die Sprache geschrieben!
Isaacg

Leider funktioniert dies in neueren Versionen von Pyth nicht mehr.
isaacg

Sollte dieser Tipp wie einer der anderen veralteten Tipps gelöscht werden? Wenn nicht, sollte möglicherweise angegeben werden, für welche Version (en) dieser Tipp gilt.
mbomb007

@ mbomb007 Ich wollte die Version finden, war aber zu faul. Ich lösche es, wenn du denkst, dass es so besser ist, bis ich es finde.
FryAmTheEggman

@FryAmTheEggman Ich denke, es liegt an dir, da im Titel steht, dass es nicht unterstützt wird.
mbomb007

5

Auspacken von 2 Elementtupeln mit F

Angenommen, Sie haben ein 2-Element-Tupel J = (a, b)und möchten r(a,b)für eine 2-Aritätsfunktion r.

Der naive Weg, dies zu tun, ist rhJeJ.

Die ausgefallene Möglichkeit, dies zu tun, besteht darin r.*J, den Entpack-Operator zu verwenden.

Der wirklich ausgefallene Weg, dies zu tun, ist die rFJVerwendung des Fold-Operators.


ist es noch möglich das zu nutzen .u? .uscheint jetzt kumulativ zu reduzieren.
Ven

.u ->. * Dies war eine Änderung, die vor einiger Zeit vorgenommen wurde, aber nie aktualisiert wurde.
Isaacg

4

Verwenden Sie die kurzen Rechenfunktionen

h: Gibt nicht das erste Element einer Liste zurück, sondern erhöht eine Zahl, z . B. hTergibt 11. Kürzer als +1T.

t: Dies dekrementiert eine Zahl (außer das Ende einer Liste zurückzugeben), z . B. tTergibt 9. Kürzer als -T1.

y: Dies verdoppelt eine Zahl, zB yTergibt 20, kürzer als *T2oder +TT.


4

Verwenden Sie mapdiese Option , um Listen zu erstellen

Es ist im Grunde ein Äquivalent zu den ausgefallenen Listenverständnissen von Python. Verwenden Sie eine vorhandene Liste oder einen Bereich, um die einzelnen Werte zu durchlaufen und zuzuordnen, auch wenn der Wert keine Rolle spielt.

Zwei Beispiele:

  • Erstellen Sie eine Liste mit 8 Nullen.

    mZ8 Anstatt von *8]Z

  • Erstellen Sie eine Liste mit 5 Zufallszahlen zwischen 0 und 9:

    mOT5 Anstatt von V5~Y]OT)

    Die zweite ordnet die Liste automatisch zu Y(nun ja, sie hängt an Y an), ist aber noch =YmOTU5kürzer.


4

Implizites Q bei EOF

Dies ist ab heute eine neue Änderung.

Qist die Variable, die für den ausgewerteten Eingang automatisch initialisiert wird. Es wird implizit an das Ende des Pyth-Programms angehängt, so oft es erforderlich ist, damit die Arität funktioniert. Angenommen, wir möchten die Collatz-Funktion der Eingabe berechnen, um ein Beispiel für die Verwendung dieser Funktion zum Golfen zu sehen .

Ein kürzester Weg, es zu schreiben, ist wie folgt:

@,/Q2h*3QQ

Da die Qs jedoch am Ende der Datei implizit sind, können wir einfach schreiben:

@,/Q2h*3

2 Bytes speichern.

Beachten Sie, dass in Funktionen mit nicht erforderlichen Argumenten diese Argumente nicht angegeben werden. Beispielsweise c"12 12"wird kein implizites Argument angegeben Q, da cnur 1 Argument erforderlich ist.


3

Verwenden Sie "Reduzieren", um eine Funktion wiederholt anzuwenden.

Angenommen, Sie müssen eine Variable auf eine Funktion von sich selbst festlegen und eine bestimmte Anzahl von Malen wiederholen. Nehmen Sie zum Beispiel das Problem, die Nummer 100 später in der Collatz-Sequenz aus der Eingabe zu finden. Der kürzeste Weg, um die nächste Nummer in der Sequenz zu finden Q, ist , wenn die Anfangsnummer ist

@,/Q2h*Q3Q

Die naheliegendste Möglichkeit, diese 100-mal anzuwenden und das Ergebnis auszudrucken, wäre

V100=Q@,/Q2h*Q3Q;Q

Schleife 100 Mal, wobei der Wert von Q jedes Mal aktualisiert wird. Beenden Sie dann die Schleife und geben Sie Q aus.

Stattdessen können wir eine Reduktionsfunktion verwenden, die die Sequenzvariable ( H) ignoriert .

u@,/G2h*G3GU100Q

Dies ist 2 Zeichen kürzer. Es ist 3 Zeichen kürzer, wenn Sie versuchen, so oft eine Schleife auszuführen, wie Elemente in einer Sequenz vorhanden sind.


3

Es gibt normalerweise kürzere Alternativen zu Any

Wenn Sie herausfinden möchten, ob eine Sequenz eine Bedingung erfüllt, verwenden Sie normalerweise .Em. Wenn Sie beispielsweise herausfinden möchten, ob eine Liste größer oder gleich 5 ist, gehen Sie wie folgt vor:

.Emgd5Q

Aber wenn es nur eine Wahrheit / Falschheit sein muss, nicht wahr / falsch, smwürde das funktionieren, da sum auf Bools funktioniert.

smgd5Q

Wir können sogar eine kürzere machen, mit filter:

fgT5Q

Der letzte sieht allerdings wirklich hässlich aus.

Für .All kann ich mir nur vorstellen, die gegenteilige Bedingung zu verwenden und sie für einen Char Save Over zu negieren .Am:

!f<T5Q

3

Sehen Sie sich alle Kontrollflussoptionen an

Schleifen:

F: For-Schleife. Genau wie bei Python.

V: Für eine Schleife über einen Bereich. Weder Variable noch Bereich müssen angegeben werden, daher 2 Zeichen kürzer.

W: While-Schleife. Genau wie bei Python.

#: Endlose while-Schleife. Escape mit Fehler oder expliziter Unterbrechung. Nur try ... exceptverfügen jetzt in Pyth.

Funktionen:

D: Allgemein definieren. Genau wie Python.

L: 1 Argument, keine Zuweisungsfunktion, wie Pythons Lambda, aber benannt. Funktionsname, Variablenname und return ( R) müssen nicht angegeben werden, daher 3 Zeichen kürzer.

Funktionsprogrammierung:

f: Filter - Wählen Sie Elemente der Eingabesequenz aus, die bei Eingabe von Lambda die Wahrheit zurückgeben.

f: Erste Ganzzahl größer oder gleich der Eingabe, die ein wahrheitsgemäßes Filterergebnis liefert.

m: Map - transformiere Elemente der Eingabesequenz unter Verwendung von Eingabe-Lambda.

u: Eingangssequenz auf Eingangs-Lambda verkleinern, Akkumulator auf drittes Argument initialisieren.

o: Reihenfolge - ältere Elemente der Eingabesequenz mit Eingabe-Lambda als Schlüssel.

Normalerweise gibt es mehrere Möglichkeiten für ein bestimmtes Problem, und nur durch das Schreiben von Testlösungen mit jedem von ihnen können Sie herausfinden, welche am kürzesten ist.


.xkann in jüngerer Zeit für try-except-Blöcke verwendet werden.
mbomb007

@ mbomb007 gibt es außer block weg zu vernachlässigen, ich meine kann das leer bleiben? Für die Ex: .x{some_statments}{except_block - can this be empty}.
Gurupad Mamadapur

@ GurupadMamadapur # ... Bkann auf diese Weise verwendet werden, wenn Sie nicht in einem Ausdruck sind
isaacg

3

Zwei Elemente in einer Liste wechseln

Das Umschalten von zwei Elementen kann eine ziemlich teure Aufgabe sein. Hier sind zwei Ansätze, die Sie verwenden möchten.

Tmp-variabler Ansatz

In Vorbereitung definieren wir eine Liste Yund füllen sie mit Zahlen. Das Ziel ist es, das zweite und dritte Element zu wechseln.

=Y[1 3 5 3 6 7)AGH,1 2

Wir weisen einfach die Variable tmp zu J = Q[G], führen die erste Listenzuweisung Y[G] = Y[H]und dann die vorletzte Zuweisung durch Y[H] = J. Der Trick dabei ist, die beiden Listenzuweisungen zu verschachteln, damit Sie das Drucken nicht unterdrücken und nicht zweimal auf referieren müssen Y.

J@YGXXYG@YHHJ

Anstatt von

J@YG XYG@YHXYHJ

Übersetzungsansatz

Wenn die Elemente, die Sie wechseln möchten, in der Liste eindeutig sind, verwenden Sie diesen Ansatz. Es ist sehr kurz. Also wechseln wir dieses Mal das erste und dritte Element (die Werte 1und 5sind eindeutig).

=Y[1 3 5 3 6 7)K,Z2

Dies nutzt die Übersetzungsfunktionalität der Liste:

XYm@YdK)

Diese Übersetzung ersetzt jedes Element Y[0]mit Y[1]und jedes Y[1]mit Y[0]. Wenn die Werte also nicht eindeutig sind, passieren schlimme Dinge. Zum Beispiel K,1 2ergibt [1, 5, 3, 5, 6, 7].

Beachten Sie, dass die schließenden Klammern optional sind, wenn die Anweisung die letzte in Ihrem Code ist.


3

Debuggen mit <newline>

Wenn Ihr Code in einem zwingenden Programmierstil geschrieben ist, ist das Debuggen ziemlich einfach, da Sie problemlos Zwischenergebnisse drucken können. ( Permalink )

FN.:Q2                loop
      =Y+-Y-FNhN      some random command
                Y     print intermediate result
                 ;Y   end for loop and print result

Eine große Anzahl von Pyth-Programmen verwendet jedoch Elemente der funktionalen Programmierung wie Map, Filter und Reduction, die ein so einfaches Drucken nicht ermöglichen. Aber es ist immer noch möglich, mit dem \nBefehl.

Der gleiche Code mit u(Verkleinern) wäre: ( Permalink )

u        .:Q2Y   reduce .:Q2, start with G = Y
 +-G-FHhH        random command

Wenn Sie die Zwischenwerte drucken möchten, fügen Sie einfach Folgendes ein \n: ( Permalink )

u         .:Q2Y   reduce
   \nG             print(G)
 +-\nG-FHhH        random command

\nadruckt aauf eine neue Zeile und kehrt zurück a. Sie können es also überall einfügen, ohne die Funktionalität des Programms ändern zu müssen.


Heutzutage können Sie dafür die Newline verwenden, die auch eine Newline druckt.
PurkkaKoodari

@ Pietu1998 Ja, ich benutze es die ganze Zeit. Zeit, den Beitrag zu aktualisieren.
Jakube

3

Ermitteln des Maximums von zwei ganzen Zahlen

g#

Angenommen, Sie haben J=5und K=12. Dann g#JK= 12 und auch g#KJ= 12.

Dies wurde von @ Pietu1998 entdeckt, der es so formulierte:

Ich bin mir nicht sicher, ob jemand es bereits gefunden hat, aber es gibt eine coole Möglichkeit, max (A, B) in 2 Bytes zu machen, ohne 3 für zu verwenden eS,AB. g#ABmacht das gleiche. (Es ist jedoch sehr ineffizient, da es maximal (1, A-B + 1) Mal eine Schleife durchläuft. Eine Optimierung besteht darin, die Zahl wahrscheinlich größer als B zu setzen.)


@ Jakube Das ist wahr. Ich habe anscheinend etwas falsch gedacht, als ich dies im Chat eingetippt habe.
PurkkaKoodari

2

Pyths joinMethode

Die joinMethode in Python kann oft etwas nervig sein, da sie nur Strings zusammenfügt. Pyth's joinist großzügiger. Standardmäßig werden alle Objekte in Zeichenfolgen transformiert.

ZB jkUTgibt 0123456789oder jb["abc"4,5\f]7gibt

abc
4
(5, 'f')
[7]

Vor kurzem wurde noch mehr Transformations-in-String-Funktionalität hinzugefügt - das erste Argument wird ebenfalls in einen String umgewandelt, z. B. j2\a\b->"a2b"
isaacg

1

Feststellen, ob eine Zahl eine ganze Zahl ist

Ein Iguter Trick besteht darin, mit nvariant festzustellen, ob eine Zahl eine ganze Zahl ist:

sI

Hiermit wird überprüft, ob sich die Zahl nicht ändert, wenn Sie sie abschneiden. Wenn es sich um eine ganze Zahl handelt, wird dies nicht der Fall sein.

Zum Beispiel können Sie dies als perfekte quadratische Prüfung verwenden:

sI@Q2

1

Verwenden Sie Packed Pyth

Packed Pyth ist eine neue "Programmiersprache", die genau wie Pyth ist, außer dass sie 7 Bits pro Zeichen anstelle von 8 Bits pro Zeichen verwendet.

Klonen Sie dazu das Pyth-Repository . Die Datei packed-pyth.pyist der Interpreter.

Sagen Sie, Ihr Code ist "Hello, world!.

Legen Sie es zuerst in eine Datei: echo -n '"Hello, world!' > code.pyth

Als nächstes packen Sie den Pyth-Code in die Packed Pyth-Datei: python3 packed-pyth.py -p code.pyth code.ppyth

Führen Sie zum Schluss den Packed Pyth-Code aus: python3 packed-pyth.py code.ppyth

Wenn Sie Code ausführen, können Sie das -dFlag angeben, um zu sehen, welcher Pyth-Code tatsächlich ausgeführt wird, und Sie können nach der Datei, die den Code enthält, eine Eingabe als zweites Befehlszeilenargument angeben.

Oberseite:

  • Code ist um 1/8 kürzer.

Nachteil:

  • Nur ASCII.

  • Keine interaktive Eingabe.

  • Vollständige Debug-Optionen sind nicht verfügbar.

  • Schlimmer noch die Fehlermeldung.


1
Können wir es, wie wir es für den abgesicherten Modus getan haben, in eine Flagge verschieben?
Maltysen

Das ist übrigens großartig: D
Maltysen

@Maltysen Ich denke, das würde den Bytewert um eins erhöhen.
Isaacg

Kann Pyth nicht weiter gepackt werden, da es nur druckbares ASCII verwendet?
Lirtosiast

1

Teilbarkeitstests mit Iund GCD

Haftungsausschluss: Dies funktioniert nur für nicht negative ganze Zahlen.

Um zu überprüfen, ob zwei nicht negative ganze Zahlen teilbar sind, können Sie Folgendes tun:

iI<divisor><dividend>

Ist a durch b teilbar und a ≥ b ≥ 0 , so gilt gcd (a, b) = b .

Es spart nicht notwendigerweise Bytes !%<dividend><divisor>, aber es könnte Ihnen eine Ersparnis bringen, weil:

  • Möglicherweise können Sie die impliziten Dinge am Ende eines Pyth-Programms (wie das Löschen Q) optimieren , wenn Sie mit der Dividende arbeiten.
  • Sie können es als eine verwenden <pfn>, da es eine Funktion für sich ist.
  • Es handhabt Modulo von 0.

Versuch es!


Ein weiterer Vorteil: iIIst eine Funktion für sich, während dies !%nicht der Fall ist, sodass Sie sie als Präfixfunktion verwenden können.
Erik der Outgolfer

@EriktheOutgolfer Danke, hinzugefügt, um die Liste der Vorteile :)
Herr Xcoder

0

Zuweisen einer Variablen zu einer auf sich selbst angewendeten Funktion

Wenn Sie eine Funktion der Arität 1 haben und diese auf eine Variable und auf sich selbst anwenden möchten, können Sie die folgende Syntax verwenden:

=<function><variable>

Anstatt von:

=<variable><function><variable>

Wenn Sie beispielsweise die Variable erhöhen möchten Z, können Sie Folgendes tun:

=hZ

Das spart ein Byte mehr =ZhZ.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.