Welche allgemeinen Tipps haben Sie zum Golfen in PHP? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme im Allgemeinen anwenden lassen, die zumindest etwas PHP-spezifisch sind (z. B. "Kommentare entfernen" ist keine Antwort). Bitte posten Sie einen Tipp pro Antwort.
37
Antworten:
Verstehen Sie, wie Variablen und Leerzeichen mit den Sprachkonstrukten von PHP interagieren.
In meiner (zugegebenermaßen kurzen) Zeit beim Golfen habe ich festgestellt, dass sich die Sprachkonstrukte von PHP (z. B. Echo, Return, For, While usw.) bei der Interaktion mit Variablen und Leerzeichen weniger intuitiv verhalten.
echo$v;
Beispielsweise ist es ebensoreturn$v;
wie andere ähnliche Konstrukte durchaus gültig . Diese geringfügige Verringerung des Leerraums kann zu einer signifikanten kumulativen Verkürzung der Länge führen.Beachten Sie jedoch, dass Variablen vor Sprachkonstruktionen ein Leerzeichen benötigen, wie im folgenden Beispiel dargestellt:
Da
AS
ein Sprachkonstrukt ist ein Raum nicht vor den Variablen erforderlich$b
, aber wenn man den Raum auszulassen ist , bevor sie , was$aAS
würde dies als Variablennamen und führt zu einem Syntaxfehler analysiert werden.quelle
foreach($a[1]as$b)
braucht keinen Leerraum. Hierbei handelt es sich nicht um Sprachkonstrukte und Variablen, sondern um Leerzeichen zwischen Wortzeichen verschiedener Wörter.echo $a+5." text"
wird nicht funktionieren, weil PHP denkt, das.
ist ein Dezimalpunkt für die5
. Damit es funktioniert, müssten Sie ein Leerzeichen wie das folgendeecho $a+5 ." text"
echo$a+5," text";
. Mit demecho
Konstrukt können Sie mehrere Parameter übergeben. wo man schreiben müssteecho"result: ".($a+5)."!";
, kann man schreibenecho"result: ",$a+5,"!";
. In der Tat ist die Übergabe mehrerer Parameter an eineecho
eine Mikrooptimierung, da der Code geringfügig schneller ausgeführt wird (da Sie die Ausgabe nicht verketten, sondern separat senden). Bei Problemen mit dem Schreiben des schnellsten Codes kann dies ein winziges bisschen helfen.echo
, aber nicht mitprint
(was Sie benötigen, wenn Sie es in einen Ausdruck einfügen :echo
ist ein reines Konstrukt ohne Rückgabewert,print
kann aber als Funktion fungieren: es erfordert keine Klammern, gibt aber immer zurückint(1)
.print
.Verwenden Sie Zeichenfolgen mit Bedacht aus.
Diese Antwort ist zweifach. Der erste Teil ist, dass Sie beim Deklarieren von Strings die implizite PHP-Konvertierung von unbekannten Konstanten in Strings verwenden können, um Platz zu sparen, zB:
Das
@
ist notwendig , um die Warnungen außer Kraft zu setzen diese produzieren. Insgesamt ergibt sich eine Reduzierung um ein Zeichen.Manchmal kann es platzsparend sein, eine Variable auf den Namen einer häufig verwendeten Funktion zu setzen. Normalerweise haben Sie möglicherweise:
Beim Golfen kann dies jedoch leicht verkürzt werden, um:
Mit nur zwei Instanzen von "preg_match" speichern Sie nur ein einzelnes Zeichen. Je mehr Sie jedoch eine Funktion verwenden, desto mehr Platz sparen Sie.
quelle
E_DEPRECATED
) sind akzeptabelphp.ini
Datei unterdrückenSie müssen nicht immer bedingte Schecks ausschreiben. Beispielsweise verwenden einige Frameworks dies oben in ihren Dateien, um den Zugriff zu blockieren:
Oder in normalen Funktionen
anstatt
quelle
Verwenden Sie kurze Array-Syntax
Seit PHP 5.4 können Arrays mit eckigen Klammern (genau wie JavaScript) anstelle der folgenden
array()
Funktion deklariert werden :Es werden fünf Bytes gespart.
Es kann jedoch Byte kosten, wenn Sie "Löcher" in einem assoziativen Array haben:
Der Nachteil tritt etwas später auf, wenn Sie die Löcher mit "leeren" Werten füllen können:
quelle
[,$a,$b,$c]=$argv;
.Verwenden Sie $ {0}, $ {1}, $ {2}, ... anstelle von $ a [0], $ a [1], $ a [2], ...
Sofern Sie keine Array-Manipulation durchführen, können die meisten Verweise auf einen Array-Index
$a[$i]
einfach durch ersetzt werden$$i
. Dies gilt sogar, wenn der Index eine Ganzzahl ist, da Ganzzahlen in PHP gültige Variablennamen sind (obwohl Literale z${0}
. B. Klammern erfordern ).Betrachten Sie die folgende Implementierung des Rabonowitz Wagon-Zapfens:
Dies kann um 6 Byte verbessert werden, indem einfach beide Array-Referenzen
$a[$g]
durch$$g
Folgendes ersetzt werden:quelle
Lernen Sie einen großen Teil der Bibliotheksfunktionen kennen .
Die Bibliothek von PHP ist ziemlich umfangreich und bietet eine Menge praktischer Funktionen, mit denen sich verschiedene Aufgaben erheblich verkürzen lassen. Sie könnten einfach jedes Mal suchen, wenn Sie versuchen, etwas zu tun, aber über die Zeitverschwendung hinaus könnten Sie möglicherweise nichts finden, das Ihrer bestimmten Suche entspricht. Der beste Weg ist, sich mit der Bibliothek vertraut zu machen und Funktionsnamen und deren Funktion auswendig zu lernen.
quelle
Ausführen von Funktionen in Zeichenfolgen.
Versuche dies:
Oder versuchen Sie dies:
Dies funktioniert nur mit Strings unter Verwendung von
""
und Heredocs (Verwechseln Sie nicht mit Nowdocs).Die Verwendung verschachtelter Funktionen ist nur in verschachtelten Heredocs möglich (oder es treten Analysefehler auf)!
quelle
you will run into parse errors
Ich kann es nicht selbst lesen? Wie fügt der nervige Zend-Motor das zusammenspaß mit typecasts
!!$foo
verwandelt einen Wahrheitswert intrue
(oder1
in eine Ausgabe), einen falschen Wert (0, eine leere Zeichenfolge, ein leeres Array) infalse
(oder eine leere Ausgabe).Dies wird im Codegolf selten benötigt, da es in den meisten Fällen einen Booleschen Wert gibt eine implizite Besetzung sowieso.
(int)$foo
kann als$foo|0
oder geschrieben werdenfoo^0
, benötigt aber möglicherweise Klammern.Für Boolesche Werte und Zeichenfolgen
$foo*1
oder zum Umwandeln+$foo
in int verwendet werden.10
, können Sie eine Null anhängen:*10
->.0
. In diesem Fall nimmt PHP den Punkt als Dezimalpunkt und beschwert sich. (Es ist jedoch anders, wenn Sie eine variable Anzahl von Nullen in einer Zeichenfolge haben.)join
anstelle von, um ein Array in einen String zu verwandelnimplode
.Wenn Sie kein Trennzeichen benötigen, verwenden Sie es
join($a)
nichtjoin('',$a)
$s=a;$s++;
produziert$s=b;
. Dies funktioniert mit Groß- und Kleinbuchstaben.$s=Z;$s++;
Ergebnisse in$s=AA;
.Dies funktioniert auch in gemischten Fällen:
aZ
zubA
,A1
zuA2
,A9
zuB0
undz99Z
zuaa00A
.Die Dekrementierung funktioniert nicht für Zeichenfolgen. (Und es geht nicht an
NULL
).Zurück in PHP 3,
$n="001";$n++;
produziert$n="002";
. Ich bin ein bisschen traurig, dass sie das entfernt haben.Was auch immer Sie Golf spielen: Halten Sie immer die Rangliste des Bedieners bereit .
quelle
Verwenden Sie Shorttags
Im normalen Code, ist es empfehlenswert , zu verwenden
<?php
und?>
. Dies ist jedoch kein normaler Code - Sie schreiben einen Code Golf Code. Statt<?php
schreiben<?
. Statt<?php echo
schreiben<?=
. Geben Sie nicht?>
am Ende ein - es ist völlig optional. Wenn Sie?>
aus irgendeinem Grund Text ausgeben müssen (z. B. um Text auszugeben, der irgendwie kürzer ist oder so), setzen Sie kein Semikolon davor - dies ist nicht erforderlich, wie?>
dies ein Semikolon impliziert.Falsch (definitiv zu lang):
Richtig:
quelle
-r
Flagge ( die kostenlos mitgeliefert wird) haben Sie überhaupt keine Tags (und Sie dürfen keine verwenden).Saiten durchschleifen
kann mit 26 Bytes oder mit 24 bis 18 gemacht werden:
$a&$b
Führt ein bitweises UND auf den (ASCII-Codes von) den Zeichen in$a
und aus$b
und führt zu einer Zeichenfolge, die dieselbe Länge wie die kürzere von
$a
und hat$b
.quelle
ord($s[$p++])
als Alternativefor(;$s+=ord($argv[++$i])%32?:die($s==100););
gegenfor(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;
in dieser Frage hinzufügen codegolf.stackexchange.com/questions/116933/…~
für Fälle, in denen Sie nur mit Ziffern arbeiten~$c
Ansatz ausgibt.Verwenden Sie ternäre Operatoren
kann wie folgt abgekürzt werden:
Kürzer, nicht wahr?
quelle
a?aa:ab?aba:abb:b
wertet dazu(a?aa:ab)?(aba):(abb)
oder so ähnlich aus.$a?:$b
ist der gleiche wie$a?$a:$b
.||
in PHP in boolesche Werte um.durch einen anderen Namen ... Funktions-Aliase
verwenden ...
join
anstattimplode
chop
stattrtrim
(chop
in PERL ist das anders!)die
anstattexit
fputs
anstattfwrite
is_int
anstelle vonis_integer
oderis_long
is_real
anstelle vonis_float
oderis_double
key_exists
anstattarray_key_exists
mysql
anstattmysql_db_query
... um die wichtigsten Aliase zu nennen. Weitere Informationen finden Sie unter http://php.net/aliases .
quelle
die
das mit und ohne Parameter funktioniert?die(1)
beendet das Programm mit einem Fehlercode1
(nicht ganz sicher; muss getestet werden);die
wird mit Code beendet0
unddie("Hello")
wird0
nach dem Drucken mit Code beendetHello
.Assoziative Arrays können mit dem
+
Operator zusammengeführt werden.Anstatt:
Verwenden:
Beachten Sie, dass der
+
Operator auch mit indizierten Arrays arbeitet, aber wahrscheinlich nicht das tut, was Sie wollen.quelle
+
, sofern die Indizes unterschiedlich sind. Ist dies nicht der Fall, werden die Werte des ersten Arrays mit denen des zweiten Arrays überschrieben (genau wie array_merge). Der Unterschied:+
ordnet Indizes nicht neu.array_flip vs array_search
verwenden
anstatt
Speichern von 1 Byte in Arrays, in denen das Auftreten jedes Werts eindeutig ist
quelle
Einige interessante Fakten zu variablen Variablen
Ich musste sie nur teilen (noch bevor ich bestätigte, dass mindestens einer von ihnen beim Golfen hilft):
$x=a;$$x=1;$x++;$$x=2;echo"$a,$b";
Druckt,1,2
aber andere arithmetische Operationen funktionieren nicht mit Buchstaben.
$a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};
prints543
.[0-9a-zA-Z_]
Variablennamen verwenden, sondern JEDE Zeichenfolge: wird$x="Hello!";$$x="Goodbye.";echo${"Hello!"};
gedrucktGoodbye.
.[a-zA-Z_][a-zA-Z_0-9]*
als Variablennamen erfordert geschweifte Klammern für den wörtlichen Gebrauch.$$x=1
Sätze${NULL}
, die die gleiche ist wie${false}
und${""}
.$a=1;$$a=5;
setzt nicht nur${1}
, sondern auch${true}
.eine weitere, die seltsamste, die ich bisher gefunden habe: Try
$a=[];$$a=3;echo${[]};
. Ja, es wird gedruckt3
!Der Grund für das Meiste: Variablennamen werden immer als Zeichenfolgen ausgewertet.
(Danke @Christoph für den Hinweis.)
Also, was auch immer Sie bekommen, wenn Sie
print
oderecho
der Ausdruck, das ist, was Sie als Variablennamen bekommen.quelle
[]
konvertiert zuArray
:${[]} = 5;echo $Array;
druckt5
. Ich bin mir ziemlich sicher, dass Sie das wissen, aber es könnte nicht für alle offensichtlich sein :)Zeilenumbrüche
Wenn für die Ausgabe Zeilenumbrüche erforderlich sind, verwenden Sie stattdessen einen physischen Zeilenumbruch (1 Byte).
"\n"
Dies bietet Ihnen auch die Möglichkeit, zwischen einfachen und doppelten Anführungszeichen zu wählen.
quelle
Vermeiden Sie Anführungszeichen, wenn möglich
PHP wandelt implizit unbekannte Wörter in wörtliche Zeichenfolgen um.
$foo=foo;
ist dasselbe wie$foo='foo';
(vorausgesetzt, esfoo
handelt sich weder um ein Schlüsselwort noch um eine definierte Konstante):$foo=echo;
funktioniert nicht.ABER:
$p=str_pad;
tut; und$p(ab,3,c)
bewertet zuabc
.Wenn Sie String-Literale ohne Anführungszeichen verwenden, erhalten Sie einen Hinweis für
Use of undefined constant
; Dies wird jedoch nicht angezeigt, wenn Sie den Standardwert fürerror_reporting
(CLI-Parameter-n
) verwenden.quelle
-n
Flag unterdrücken können ); 7.2 ergibt Warnungen; spätere Versionen werfen Fehler!Pfeilfunktionen in PHP 7.4
PHP 7.4 ist jetzt in der RC2-Version und wird hoffentlich in ca. 2 Monaten veröffentlicht. Eine Liste der neuen Funktionen finden Sie hier (diese Seite kann bei Veröffentlichung von 7.4 aktualisiert werden). In 7.4 hat PHP endlich die Pfeilfunktionen, so dass nicht nur die Funktionsantworten jetzt kürzer sein können, sondern auch das Übergeben von Closures an andere Funktionen viel kürzer sein kann. Hier einige Beispiele:
Rückgabe + 1:
Anonyme Funktion (Schließung) - 25 Bytes - Probieren Sie es online!
Pfeilfunktion - 12 Bytes - Online testen!
Multiplizieren Sie Elemente der ersten Eingabe (Array von Ints) mit der zweiten Eingabe (Int):
Anonyme Funktion (Schließung) - 72 Bytes - Probieren Sie es online!
Pfeilfunktion - 38 Bytes - Online testen!
Ist Ihnen aufgefallen, dass
$n
in der inneren Funktion ohneuse $n
Aussage zugegriffen werden kann? Ja, das ist eine der Pfeilfunktionen.Als Randnotiz konnte ich Pfeilfunktionen nicht dazu bringen, rekursiv zu arbeiten (rufen Sie dieselbe Pfeilfunktion in sich auf), weil wir ihnen keinen Namen geben und sie als Abschluß in einer Variablen speichern können, die
$f
es nicht ermöglicht, sich selbst$f
zugänglich zu machen (traurig) ). Dieses Beispiel funktioniert also nicht und die Verwendung$f
in der ersten Zeile verursacht einen schwerwiegenden Fehler:Aber das Aufrufen einer Pfeilfunktion mit einer anderen Pfeilfunktion funktioniert:
quelle
$f=fn($n)=>$n?$f($n-1):0;
Sie es tun$f=$F=fn($n)=>$n?$F($n-1):0;
? Funktioniert das? Und dann rufst du$(5)
wie gewohnt an.In Bezug auf Datei-E / A:
Verlinkung auf eine andere verwandte Frage , deren Antworten hier passen.
quelle
Von Funktionen zurückgegebene Arrays werden direkt dereferenziert.
ZB stattdessen:
Du kannst tun:
Dies funktioniert auch mit Methoden:
Sie können Array-Deklarationen auch direkt dereferenzieren:
quelle
Verwenden Sie
end()
anstelle vonarray_pop()
Die
end()
Funktion bewegt nicht nur den internen Zeiger an das Ende des Arrays, sondern gibt auch den letzten Wert zurück. Beachten Sie natürlich, dass dieser Wert nicht entfernt wird. Wenn Sie sich also nicht darum kümmern, was das Array anschließend enthält, können Sie ihn stattdessen verwendenarray_pop()
.quelle
double array_flip vs in_array vs array_unique
In diesem speziellen Fall spart ein double array_flip 10 Bytes
($f=array_flip)($k=$f($c)))
Entfernen Sie alle doppelten Werte im Array , und ich habe diese fallen gelassen$c=[],
,|in_array($o,$c)
und ersetzenarray_keys($c)
mit$k
Online Version
gegen
Online Version
Bei array_unique werden 2 Bytes gespart
Online Version
Nach der Suche nach einem Fehler in diesem Programm und den Ersatz
$x[$i]==$o?:$c[$x[$i]]=$o
zu($p=$x[$i])==$o?:$k[$c[$p]=$o]=$p
war das Doppel array_flip nicht mehr notwendigquelle
array_unique
. Yay!sich kreuzende Saiten
Haben Sie jemals
join("DELIMITER",str_split($s))
(31 Bytes) oder sogarpreg_replace(".","DELIMITER",$s)
(32 Bytes) verwendet?
Dafür gibt es ein eingebautes:
Try
chunk_split($s,1,"DELIMITER")
(29 Bytes).Wenn Sie den dritten Parameter weglassen,
chunk_split
verwenden Sie\r\n
; das kann Ihnen 7 oder 8 Bytes sparen.Aber Vorsicht:
chunk_split
Hängt das Trennzeichen auch an den String an,sodass Sie möglicherweise nicht genau das bekommen, was Sie wollen.
(Wenn Sie die Blocklänge nicht angeben, wird 76 verwendet. Eher ungewöhnlich für Code-Golf, aber wer weiß.)
quelle
strtr
ich liebe diese Idee.unset () vs INF
Suchen Sie in einem Fall nach einem Minimum in einem Array, das Sie anstelle von verwenden können
um 3 Bytes zu sparen
quelle
str_repeat
In einigen Fällen haben Sie eine Eingabe von Zeichen und Sie sollten sie wiederholt mit einer Eingabe größer Null für jedes Zeichen ausgeben.
(52 Bytes) ist kürzer als
oder
(Jeweils 54 Bytes)
So funktioniert es zum Beispiel bei der Eingabe
a1b2c1
$z
ist nicht gesetzt (implizitNULL
),--$z
tut also nichts und ist falsch;$c="a"
,$z="1"
und$i=2
->$c.$z="a1"
ist wahr -> Ausgabe"a"
--$z=0
; so setzen wir$c="b"
,$z="2"
(und$i=4
) ->$c.$z="b2"
ist truthy -> Ausgang"ab"
--$z=1
-> Ausgabe"abb"
--$z=0
; so setzen wir$c="c"
und$z=1
$c.$z="c1"
ist wahre Ausgabe"abbc"
--$z=0
so$c=""
und$z=""
->$c.$z=""
ist falsch -> schleifenbrüchequelle
for
Schleifen kombinierenAngenommen, Sie haben Code der folgenden Form:
Dies kann in der Regel in der folgenden Form erneut gerollt werden:
Dabei handelt es sich
•
um einen generischen Kombinationsoperator. Dies führt normalerweise zu einer Verringerung der Bytezahl, erfordert jedoch wahrscheinlich etwas Kreativität.$cond2
muss so geschrieben werden, dass es beim ersten Mal durchfällt.$post1
sollte auch nicht beim ersten Mal ausgeführt werden, obwohl es möglicherweise einfacher ist, vorher eine Umgestaltung vorzunehmen, damit diese$post1
nicht vorhanden ist.Wenn Sie mit drei oder mehr verschachtelten Schleifen arbeiten, können Sie auch zuerst zwei Schleifen kombinieren und diese dann zu einer anderen kombinieren, und so weiter. Ich finde, dass es im Allgemeinen einfacher war, von innen nach außen zu kombinieren.
Betrachten Sie als Beispiel die folgende Lösung für das H-Teppich-Fraktal ( 97 Byte ):
Dies kann folgendermaßen umformuliert werden:
$e&&print
verhindertprint
bei der ersten Iteration und erhöht sich auch nicht$i
.und schließlich ( 93 Bytes ):
$H>$e*=3
schlägt das erste Mal fehl, da beide Variablen undefiniert sind.quelle
Zeichen in einer Zeichenfolge entfernen
Speichert 1 Zeichen im Vergleich zu
quelle
""
und ist sowieso nicht sehr nützlich.)
. Undstrtr($string,[" "=>""])
ist noch kürzer.array_merge vs array_push
ist ein Byte kürzer als
Funktioniert nicht gleichermaßen mit assoziativen Arrays
variable-arg-list PHP> 5.6
quelle
Verwenden Sie Boolesche Operatoren anstelle von
strtoupper()
undstrtolower()
Wenn Sie ausschließlich mit Zeichenfolgen arbeiten, die aus Buchstaben bestehen, können Sie Boolesche Operatoren verwenden, um diese mit weniger Tastenanschlägen in Groß- oder Kleinbuchstaben zu ändern als mit den in PHP integrierten Funktionen.
Beispiel:
Die Dinge sind ein wenig schwieriger für Strings beliebiger Länge, aber die
&
und die^
Betreiber das Ergebnis an die Länge des kürzeren Eingabestring gestutzt. So zum Beispiel, wenn$W
eine Reihe von Räumen zumindest so lange , wie jede Eingabe ist$s
, dann~$W&$s
entsprichtstrtoupper($s)
, und$s|$W^$s
ist äquivalent zustrtolower($s)
(während$s|$W
selbst eine Zeichenkette mit zusätzlichen Bereichen nur erzeugen wird$s
und$W
von gleicher Länge ist ).quelle
verwenden veraltete Funktionen
Wenn Sie POSIX statt PERL regex ohne verschwenden mehr als 5 Bytes auf dem Ausdruck, verwenden können
ereg
odereregi
anstelle vonpreg_match
,split
oderspliti
statt preg_split.split
Kann auch als Synonymexplode
für die meisten Begrenzer verwendet werden.Diese Funktionen sind als veraltet markiert und werfen
E_DEPRECATED
Hinweise, aber ich glaube, ich habe gelesen, dass Warnungen und Hinweise in Ordnung sind.quelle