Tipps zum Golfen in PHP


37

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.


Warten Sie, mache ich es richtig? ... Wie auch immer, ich bin wirklich neugierig auf diese. PHP wird von vielen Leuten und Golfern verwendet, aber ich habe fast keine Ahnung, wie man einen PHP-Code spielt.
20.

Verwenden Sie kurze Tags <??> Es können ein paar Bytes gespart werden.
Mob

Antworten:


22

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 ebenso return$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:

foreach($a AS$b){}

Da ASein Sprachkonstrukt ist ein Raum nicht vor den Variablen erforderlich $b, aber wenn man den Raum auszulassen ist , bevor sie , was $aASwürde dies als Variablennamen und führt zu einem Syntaxfehler analysiert werden.


3
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.
Titus

1
Ein weiteres Beispiel für die Verwendung von Leerzeichen ist die Verkettung von Zeichenfolgen. Zum Beispiel echo $a+5." text"wird nicht funktionieren, weil PHP denkt, das .ist ein Dezimalpunkt für die 5. Damit es funktioniert, müssten Sie ein Leerzeichen wie das folgende echo $a+5 ." text"
Business Cat

@BasicSunset Diese Anweisung kann als geschrieben werden echo$a+5," text";. Mit dem echoKonstrukt können Sie mehrere Parameter übergeben. wo man schreiben müsste echo"result: ".($a+5)."!";, kann man schreiben echo"result: ",$a+5,"!";. In der Tat ist die Übergabe mehrerer Parameter an eine echoeine 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.
Ismael Miguel

@IsmaelMiguel Es funktioniert mit echo, aber nicht mit print(was Sie benötigen, wenn Sie es in einen Ausdruck einfügen : echoist ein reines Konstrukt ohne Rückgabewert, print kann aber als Funktion fungieren: es erfordert keine Klammern, gibt aber immer zurück int(1).
Titus

@Titus Ich habe nichts darüber gesagt print.
Ismael Miguel

22

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:

@$s=string;

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:

preg_match(..);preg_match(..);

Beim Golfen kann dies jedoch leicht verkürzt werden, um:

@$p=preg_match;$p(..);$p(..);

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.


10
@ wird im Codegolf nicht benötigt; Mitteilungen und Warnungen (einschließlich E_DEPRECATED) sind akzeptabel
Titus

3
@Titus In PHP werden die Warnungen jedoch in die Standarddatei ausgegeben, sodass sie benötigt werden.
brianush1

1
@ Titus Ich glaube, Sie können sie in der php.iniDatei unterdrücken
Stan Strum

12

Sie müssen nicht immer bedingte Schecks ausschreiben. Beispielsweise verwenden einige Frameworks dies oben in ihren Dateien, um den Zugriff zu blockieren:

<?php defined('BASE_PATH')||die('not allowed');

Oder in normalen Funktionen

$value && run_this();

anstatt

if($value) { run_this(); }

Es funktioniert auch in JS
Евгений Новиков

8

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 :

$arr=['foo','bar','baz'];
// instead of
$arr=array('foo','bar','baz');

Es werden fünf Bytes gespart.


Es kann jedoch Byte kosten, wenn Sie "Löcher" in einem assoziativen Array haben:

$arr=array(,1,,3,,5);
// is one byte shorter than
$arr=[1=>1,3=>3,5=>5];

Der Nachteil tritt etwas später auf, wenn Sie die Löcher mit "leeren" Werten füllen können:

$arr=[0,1,0,3,0,5,0,7,0,9,10,11];
// costs two byte more than
$arr=array(,1,,3,,5,,7,,9,,11);

2
PHP 7.1 auch kurze Liste Zuordnung eingeführt: [,$a,$b,$c]=$argv;.
Titus

7

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:

3.<?for(;$g?$d=0|($a[$g]=$d*$g--/2+($a[$g]?:2)%$g*1e4)/$g--:238<<printf($e?'%04d':'',$e+$d/$g=1e4)^$e=$d%$g;);

Dies kann um 6 Byte verbessert werden, indem einfach beide Array-Referenzen $a[$g]durch $$gFolgendes ersetzt werden:

3.<?for(;$g?$d=0|($$g=$d*$g--/2+($$g?:2)%$g*1e4)/$g--:238<<printf($e?'%04d':'',$e+$d/$g=1e4)^$e=$d%$g;);

1
Damit habe ich gerade 3 Bytes gespart: showcase .
Titus

6

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.


6
Das ist eine Menge Auswendiglernen, vor allem angesichts der eher inkonsistenten Benennung vieler Funktionen ;-)
Joey,

@ Joey Einverstanden. Ähnlich wie das Auswendiglernen der Java-Bibliothek, außer dass dies weniger nützlich wäre, da es ausführlicher ist.
Matthew Read

3
Ich finde, dass die wichtigsten Funktionen für die Herausforderungen, denen ich bisher begegnet bin, die Funktionen zur Manipulation von Strings und Arrays sind. Der kreative Einsatz dieser kann den Code wirklich reduzieren.
Migimaru

6

Ausführen von Funktionen in Zeichenfolgen.

Versuche dies:

$a='strlen';
echo "This text has {$a('15')} chars";

Oder versuchen Sie dies:

//only php>=5.3
$if=function($c,$t,$f){return$c?$t:$f;};
echo <<<HEREDOCS
    Heredocs can{$if(true,' be','not be')} used too and can{$if(<<<BE
{$if(true,1,0)}
BE
,'','not')} be nested
HEREDOCS;
//Expected output: Heredocs can be used too and can be nested

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)!


you will run into parse errorsIch kann es nicht selbst lesen? Wie fügt der nervige Zend-Motor das zusammen
Stan Strum

Wenn ich das nächste Mal in einem Argument "PHP ist eine gute Programmiersprache" bin, werde ich dies als Kontrapunkt verwenden. Wow.
Primo

@primo Ist es so schlimm? : O
Ismael Miguel

5

spaß mit typecasts

  • !!$fooverwandelt einen Wahrheitswert in true(oder 1in eine Ausgabe), einen falschen Wert (0, eine leere Zeichenfolge, ein leeres Array) in false(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)$fookann als $foo|0oder geschrieben werden foo^0, benötigt aber möglicherweise Klammern.
    Für Boolesche Werte und Zeichenfolgen $foo*1oder zum Umwandeln +$fooin int verwendet werden.

  • Im Gegensatz zu den meisten anderen Sprachen behandelt PHP Zeichenfolgen mit numerischen Werten als Zahlen. Wenn Sie also einen String haben, der eine Zahl enthält, mit der Sie rechnen müssen, rechnen Sie einfach.
  • Der andere Weg funktioniert nicht : Um eine beliebige Zahl in einer Variablen mit zu multiplizieren 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.)
  • Verwenden Sie joinanstelle von, um ein Array in einen String zu verwandeln implode.
    Wenn Sie kein Trennzeichen benötigen, verwenden Sie es join($a)nichtjoin('',$a)
  • Inkrementieren Strings: Die erstaunliche Eigenschaft imo ist , dass $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: aZzu bA, A1zu A2, A9zu B0und z99Zzu aa00A.
    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 .


4

Verwenden Sie Shorttags

Im normalen Code, ist es empfehlenswert , zu verwenden <?phpund ?>. Dies ist jedoch kein normaler Code - Sie schreiben einen Code Golf Code. Statt <?phpschreiben <?. Statt <?php echoschreiben <?=. 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):

<?php echo ucfirst(trim(fgets(STDIN)));?>s!

Richtig:

<?=ucfirst(trim(fgets(STDIN)))?>s!

Mit der -rFlagge ( die kostenlos mitgeliefert wird) haben Sie überhaupt keine Tags (und Sie dürfen keine verwenden).
Titus

4

Saiten durchschleifen

kann mit 26 Bytes oder mit 24 bis 18 gemacht werden:

foreach(str_split($s)as$c)  # A) 26 - general
for($p=0;a&$c=$s[$p++];)    # B) 24 - general
for($p=0;$c=$s[$p++];)      # C) 22 - if $s has no `0` character
for(;a&$c=$s[$p++];)        # D) 20 - if $p is already NULL or 0 (does NOT work for false)
for(;$c=$s[$p++];)          # E) 18 - both C and D

for(;$o=ord($s[$p++]);)     # F) 23 - work on ASCII codes, if $s has no NULL byte and D
for(;~$c=$s[$p++];)         # G) 19 - if $s has no chr(207) and D

$a&$bFührt ein bitweises UND auf den (ASCII-Codes von) den Zeichen in $aund aus $b
und führt zu einer Zeichenfolge, die dieselbe Länge wie die kürzere von $aund hat $b.


können Sie bitte ord($s[$p++])als Alternative for(;$s+=ord($argv[++$i])%32?:die($s==100););gegen for(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;in dieser Frage hinzufügen codegolf.stackexchange.com/questions/116933/…
Jörg

Bitte ergänzen Sie ~für Fälle, in denen Sie nur mit Ziffern arbeiten
Jörg Hülsermann 30.

Beachten Sie, dass PHP 7.2 Warnungen für den ~$cAnsatz ausgibt.
Titus

4

Verwenden Sie ternäre Operatoren

if(a==2){some code;}else{some other code;}

kann wie folgt abgekürzt werden:

(a==2?some code:some other code);

Kürzer, nicht wahr?


"Bedingte Kürzel"? Sagen Sie besser den richtigen Namen, damit alle, die sich für weitere Details interessieren, ihn in der Dokumentation finden: ternärer Operator .
Manatwork

3
Die Frage fragt nach Tipps, die etwas spezifisch für PHP sind. Dies ist in den Tipps für alle Sprachen enthalten .
Peter Taylor

3
Der ternäre Operator hat in PHP ein seltsames Verhalten, wenn Sie ihn verschachteln. a?aa:ab?aba:abb:bwertet dazu (a?aa:ab)?(aba):(abb)oder so ähnlich aus.
Titus

1
Und ab PHP 5.3 können Sie den zweiten Operator weglassen: $a?:$bist der gleiche wie $a?$a:$b.
Titus

1
@Cyoce wandelt ||in PHP in boolesche Werte um.
Titus

3

durch einen anderen Namen ... Funktions-Aliase

verwenden ...

  • join anstatt implode
  • chopstatt rtrim( chopin PERL ist das anders!)
  • die anstatt exit
  • fputs anstatt fwrite
  • is_intanstelle von is_integeroderis_long
  • is_realanstelle von is_floatoderis_double
  • key_exists anstatt array_key_exists
  • mysql anstatt mysql_db_query

... um die wichtigsten Aliase zu nennen. Weitere Informationen finden Sie unter http://php.net/aliases .


Oh ... und wussten Sie, dass diedas mit und ohne Parameter funktioniert? die(1)beendet das Programm mit einem Fehlercode 1(nicht ganz sicher; muss getestet werden); diewird mit Code beendet 0und die("Hello")wird 0nach dem Drucken mit Code beendet Hello.
Titus

3

Assoziative Arrays können mit dem +Operator zusammengeführt werden.

Anstatt:

$merged = array_merge($a, $b);

Verwenden:

$merged = $a + $b;

Beachten Sie, dass der +Operator auch mit indizierten Arrays arbeitet, aber wahrscheinlich nicht das tut, was Sie wollen.


Tatsächlich häufig ein guter Ersatz, wenn auch nicht genau das gleiche: pastebin.com/seYeaP38
Manatwork

Ah ja, verdammt, ich hatte ursprünglich den Titel "assoziative Arrays ..." und entfernte ihn dann. Ich werde klarstellen, danke.
Alex Howansky

numerische Arrays können auch mit zusammengeführt werden +, 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.
Titus

3

array_flip vs array_search

verwenden

array_flip($array)[$value]

anstatt

array_search($value,$array)

Speichern von 1 Byte in Arrays, in denen das Auftreten jedes Werts eindeutig ist


3

Einige interessante Fakten zu variablen Variablen

Ich musste sie nur teilen (noch bevor ich bestätigte, dass mindestens einer von ihnen beim Golfen hilft):

  • Buchstaben verwenden: $x=a;$$x=1;$x++;$$x=2;echo"$a,$b";Druckt, 1,2
    aber andere arithmetische Operationen funktionieren nicht mit Buchstaben.
  • Wie bereits erwähnt , können Sie reine Zahlen als Variablennamen verwenden:
    $a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};prints 543.
  • Sie können nicht nur [0-9a-zA-Z_]Variablennamen verwenden, sondern JEDE Zeichenfolge: wird
    $x="Hello!";$$x="Goodbye.";echo${"Hello!"};gedruckt Goodbye..
  • Aber: Alles außer [a-zA-Z_][a-zA-Z_0-9]*als Variablennamen erfordert geschweifte Klammern für den wörtlichen Gebrauch.
  • Ohne Variablen definiert, $$x=1Sä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 gedruckt 3!

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 printoder echoder Ausdruck, das ist, was Sie als Variablennamen bekommen.


1
Variablennamen werden in Zeichenfolgen konvertiert, die die letzten drei Punkte Ihrer Liste erklären. []konvertiert zu Array: ${[]} = 5;echo $Array;druckt 5. Ich bin mir ziemlich sicher, dass Sie das wissen, aber es könnte nicht für alle offensichtlich sein :)
Christoph

@ Jeff Ich habe den Tippfehler behoben. Danke fürs bemerken.
Titus

2

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.


2

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, es foohandelt 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 zu abc.

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ür error_reporting(CLI-Parameter -n) verwenden.


Ich habe gerade bemerkt: Diese Antwort ist ein etwas erweitertes / aktualisiertes Duplikat von codegolf.stackexchange.com/a/2916/55735 .
Titus

Hinweis: PHP vor 7.2 lieferte Hinweise (die Sie mit dem -nFlag unterdrücken können ); 7.2 ergibt Warnungen; spätere Versionen werfen Fehler!
Titus

2

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!

function($n){return$n+1;}

Pfeilfunktion - 12 Bytes - Online testen!

fn($n)=>$n+1

Multiplizieren Sie Elemente der ersten Eingabe (Array von Ints) mit der zweiten Eingabe (Int):

Anonyme Funktion (Schließung) - 72 Bytes - Probieren Sie es online!

function($a,$n){return array_map(function($b)use($n){return$b*$n;},$a);}

Pfeilfunktion - 38 Bytes - Online testen!

fn($a,$n)=>array_map(fn($b)=>$b*$n,$a)

Ist Ihnen aufgefallen, dass $nin der inneren Funktion ohne use $nAussage 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 $fes nicht ermöglicht, sich selbst $fzugänglich zu machen (traurig) ). Dieses Beispiel funktioniert also nicht und die Verwendung $fin der ersten Zeile verursacht einen schwerwiegenden Fehler:

$f=fn($n)=>$n?$f($n-1):0;
$f(5); // Causes error: "PHP Notice: Undefined variable: f" + "PHP Fatal error: Uncaught Error: Function name must be a string"

Aber das Aufrufen einer Pfeilfunktion mit einer anderen Pfeilfunktion funktioniert:

$f1=fn($n)=>$n+1;
$f2=fn($n)=>$f1($n-1);
$f1(2) // Returns 3
$f2(2) // Returns 2

Was ist, wenn $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.
Ismael Miguel

@IsmaelMiguel es scheint immer noch den gleichen Fehler zu werfen. Sie können tio.run # php auch selbst ausprobieren, da Dennis sein PHP vor einiger Zeit auf 7.4 RC2 aktualisiert hat.
Night2

Ich kann es nicht zum Laufen bringen. Anscheinend sind nur die zuvor definierten Variablen verfügbar.
Ismael Miguel


1

Von Funktionen zurückgegebene Arrays werden direkt dereferenziert.

ZB stattdessen:

$a = foo();
echo $a[$n];

Du kannst tun:

echo foo()[$n];

Dies funktioniert auch mit Methoden:

echo $obj->foo()[$n];

Sie können Array-Deklarationen auch direkt dereferenzieren:

echo [1, 2, 3, 4, 5][$n];

1

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 verwenden array_pop().


1

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 ersetzen array_keys($c)mit$k

for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
$x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,($f=array_flip)($k=$f($c)))==$y # boolean replacement string 1 equal to string 2
    ?join($k)." ".join($c) # output for true cases
:0; #Output false cases

Online Version

gegen

for($c=[],[,$x,$y]=$argv;a&$o=$y[$i];$i++)
  $x[$i]==$o|in_array($o,$c)?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,$c)==$y # boolean replacement string 1 equal to string 2
  ?join(array_keys($c))." ".join($c) # output for true cases
  :0; #Output false cases

Online Version

Bei array_unique werden 2 Bytes gespart

for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
  $x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,array_unique($c))==$y # boolean replacement string 1 equal to string 2
  ?join(array_keys($c))." ".join($c) # output for true cases
  :0; #Output false cases

Online Version

Nach der Suche nach einem Fehler in diesem Programm und den Ersatz $x[$i]==$o?:$c[$x[$i]]=$ozu ($p=$x[$i])==$o?:$k[$c[$p]=$o]=$pwar das Doppel array_flip nicht mehr notwendig


assoziativ sicher array_unique. Yay!
Titus

@ Titus Ich habe Ihren Vorschlag hinzufügen
Jörg Hülsermann

1

sich kreuzende Saiten

Haben Sie jemals
join("DELIMITER",str_split($s))(31 Bytes) oder sogar
preg_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_splitverwenden Sie \r\n; das kann Ihnen 7 oder 8 Bytes sparen.

Aber Vorsicht: chunk_splitHä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ß.)


Vielleicht sollten Sie ein Beispiel in Kombination mit hinzufügen, strtrich liebe diese Idee.
Jörg Hülsermann

1

unset () vs INF

Suchen Sie in einem Fall nach einem Minimum in einem Array, das Sie anstelle von verwenden können

unset($var[$k]);

$var[$k]=INF;

um 3 Bytes zu sparen


1

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.

for(;--$z?:($c=$argn[$i++]).$z=$argn[$i++];)echo$c;

(52 Bytes) ist kürzer als

for(;~$c=$argn[$i++];)echo str_repeat($c,$argn[$i++]);

oder

for(;~$c=$argn[$i++];)echo str_pad($c,$argn[$i++],$c);

(Jeweils 54 Bytes)

So funktioniert es zum Beispiel bei der Eingabe a1b2c1

$zist nicht gesetzt (implizit NULL), --$ztut 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=0so $c=""und $z=""-> $c.$z=""ist falsch -> schleifenbrüche


1

forSchleifen kombinieren

Angenommen, Sie haben Code der folgenden Form:

for($pre1; $cond1; $post1) for($pre2; $cond2; $post2) $code;

Dies kann in der Regel in der folgenden Form erneut gerollt werden:

for($pre1; $cond2  $post2 || $cond1  $pre2  $post1; ) $code;

Dabei handelt es sich um einen generischen Kombinationsoperator. Dies führt normalerweise zu einer Verringerung der Bytezahl, erfordert jedoch wahrscheinlich etwas Kreativität. $cond2muss so geschrieben werden, dass es beim ersten Mal durchfällt. $post1sollte auch nicht beim ersten Mal ausgeführt werden, obwohl es möglicherweise einfacher ist, vorher eine Umgestaltung vorzunehmen, damit diese $post1nicht 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 ):

for(;$i<$n=3**$argn;$i+=print"$s\n")for($s=H,$e=1;$e<$n;$e*=3)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;

Dies kann folgendermaßen umformuliert werden:

for(;($i+=$e&&print"$s\n")<$n=3**$argn;)for($s=H,$e=1;$e<$n;$e*=3)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;

$e&&printverhindert printbei der ersten Iteration und erhöht sich auch nicht $i.

und schließlich ( 93 Bytes ):

for(;$H>$e*=3or$e=($i+=$e&&print"$s\n")<${$s=H}=3**$argn;)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;

$H>$e*=3 schlägt das erste Mal fehl, da beide Variablen undefiniert sind.


1

Zeichen in einer Zeichenfolge entfernen

join(explode(" ",$string));

Speichert 1 Zeichen im Vergleich zu

str_replace(" ","",$string);

Beachten Sie, dass dies für alle (nicht leeren) Zeichenfolgen funktioniert, nicht nur für Zeichen.
CalculatorFeline

@CalculatorFeline Warum sollte es nicht für leere Zeichenfolgen funktionieren? Es ergibt keinen Sinn oder diesen Fall.
Jörg Hülsermann

Nun, die erste Version funktioniert nicht ""und ist sowieso nicht sehr nützlich.
CalculatorFeline

1
@CalculatorFeline Und in diesem Fall ist eine Null-Byte-Lösung viel besser. Es macht keinen Sinn, dies auf diese Weise zu tun.
Jörg Hülsermann

3
In Ihrem Join-Beispiel fehlt ein ). Und strtr($string,[" "=>""])ist noch kürzer.
Titus


1

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:

// Convert lowercase to uppercase
$s = "g";
echo strtoupper($s);  // Outputs 'G', uses 20 characters
echo~" "&$s;          // Outputs 'G', uses 12 characters

// Convert uppercase to lowercase
$s = "G";
echo strtolower($s);  // Outputs 'g', uses 20 characters
echo$s^" ";           // Outputs 'g', uses 11 characters

// Switch case of each character
$s = "Gg";
echo$s^"  ";          // Outputs 'gG', uses 12 characters

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 $Weine Reihe von Räumen zumindest so lange , wie jede Eingabe ist $s, dann ~$W&$sentspricht strtoupper($s), und $s|$W^$sist äquivalent zu strtolower($s)(während $s|$Wselbst eine Zeichenkette mit zusätzlichen Bereichen nur erzeugen wird $sund $Wvon gleicher Länge ist ).


0

verwenden veraltete Funktionen
Wenn Sie POSIX statt PERL regex ohne verschwenden mehr als 5 Bytes auf dem Ausdruck, verwenden können eregoder eregianstelle von preg_match, splitoder splitistatt preg_split.
splitKann auch als Synonym explodefür die meisten Begrenzer verwendet werden.

Diese Funktionen sind als veraltet markiert und werfen E_DEPRECATEDHinweise, aber ich glaube, ich habe gelesen, dass Warnungen und Hinweise in Ordnung sind.


2
Achtung! Diese wurden in PHP 7.0 entfernt.
Umbrella
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.