Conseils pour jouer au golf en PHP


37

Quels conseils généraux avez-vous pour jouer au golf en PHP? Je recherche des idées pouvant être appliquées aux problèmes de code de golf en général, qui sont au moins quelque peu spécifiques à PHP (par exemple, "supprimer les commentaires" n'est pas une réponse). Merci de poster un pourboire par réponse.


Attends, est-ce que je le fais bien? ... Quoi qu'il en soit, je suis vraiment curieux à propos de celui-ci. PHP est utilisé par beaucoup de gens et les golfeurs, mais je ne sais presque pas comment jouer au golf avec un code PHP.
JiminP

Utilisez des balises courtes <??> Il peut économiser quelques octets.
Mob

Réponses:


22

Comprenez comment les variables et les espaces interagissent avec les constructions de langage PHP.

Durant ma période de golf (certes courte), j'ai constaté que les constructions de langage de PHP (telles que echo, return, for, while, etc.) se comportaient de manière moins qu'intuitive lors de l'interaction avec des variables et des espaces.

echo$v;, par exemple, est parfaitement valide, comme le sont d’ return$v;autres constructions similaires. Ces petites réductions d'espaces peuvent entraîner une diminution cumulative significative de la longueur.

Gardez toutefois à l'esprit que les variables avant les constructions de langage nécessitent un espace après, comme dans l'exemple suivant:

foreach($a AS$b){}

Parce que ASest une construction linguistique, un espace n'est pas nécessaire avant la variable $b, mais si l'on devait omettre l'espace avant qu'il , ce qui $aAS, ce serait analysé comme un nom de variable et conduire à une erreur de syntaxe.


3
foreach($a[1]as$b)n'a besoin d'aucun espace blanc. Ce ne sont pas des constructions de langage et des variables, mais des espaces entre les mots-caractères de mots différents.
Titus

1
Une autre instance où vous avez besoin d’espace est la concaténation de chaînes. Par exemple, echo $a+5." text"cela ne fonctionnera pas car PHP pense que le .est un point décimal pour le 5. Pour que cela fonctionne, vous devez ajouter un espace comme celui-ci:echo $a+5 ." text"
Business Cat

@BasicSunset Cette instruction peut être écrite en tant que echo$a+5," text";. La echoconstruction vous permet de transmettre plusieurs paramètres. là où il faudrait écrire echo"result: ".($a+5)."!";, vous pouvez écrire echo"result: ",$a+5,"!";. En fait, transmettre plusieurs paramètres à un echoest une micro-optimisation, car le code sera un peu plus rapide (puisque vous ne concaténez pas la sortie, mais l'envoyez séparément). Pour les difficultés liées à l’écriture du code le plus rapide, cela peut aider un tout petit peu.
Ismael Miguel

@IsmaelMiguel Cela fonctionne avec echo, mais pas avec print(ce dont vous avez besoin si vous le mettez dans une expression: echoest une construction pure sans valeur de retour, alors qu'il print peut agir en tant que fonction: il ne nécessite aucune parenthèse, mais il retourne toujours int(1).
Titus

@ Titus je n'ai rien dit print.
Ismael Miguel

22

Utilisez les cordes à bon escient.

Cette réponse est double. La première partie est que lors de la déclaration de chaînes, vous pouvez utiliser la conversion implicite de PHP de constantes inconnues en chaînes pour économiser de l'espace, par exemple:

@$s=string;

Le @est nécessaire pour ignorer les avertissements que cela produira. Globalement, vous vous retrouvez avec une réduction d'un caractère.

est-ce que parfois, il peut être efficace pour l'espace de définir une variable sur le nom d'une fonction souvent utilisée. Normalement, vous pourriez avoir:

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

Mais lorsque vous jouez au golf, cela peut être facilement réduit à:

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

Avec seulement deux instances de "preg_match", vous ne sauvegardez qu'un seul caractère, mais plus vous utilisez une fonction, plus vous économiserez d'espace.


10
@ n'est pas nécessaire dans codegolf; les avis et les avertissements (y compris E_DEPRECATED) sont acceptables
Titus

3
@ Titus Mais en PHP, les avertissements sont générés dans le fichier standard, ils sont donc nécessaires.
brianush1

1
@Titus Je pense que vous pouvez les supprimer dans le php.inifichier
Stan Strum

12

Vous n'avez pas toujours besoin d'écrire des contrôles conditionnels. Par exemple, certains frameworks utilisent ceci en haut de leurs fichiers pour bloquer l'accès:

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

Ou dans des fonctions normales

$value && run_this();

au lieu de

if($value) { run_this(); }

Cela fonctionne aussi dans JS
вгений Новиков le

8

Utiliser une syntaxe de tableau courte

Depuis PHP 5.4, les tableaux peuvent être déclarés en utilisant des crochets (tout comme JavaScript) au lieu de la array()fonction:

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

Cela économisera cinq octets.


Mais cela peut coûter des octets si vous avez des "trous" dans un tableau associatif:

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

l'inconvénient frappe un peu plus tard si vous pouvez combler les trous avec des valeurs "vides":

$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 a également introduit l' affectation courte liste: [,$a,$b,$c]=$argv;.
Titus

7

Utilisez $ {0}, $ {1}, $ {2}, ... au lieu de $ a [0], $ a [1], $ a [2], ...

Sauf si vous effectuez une manipulation de tableau, la plupart des références à un index de tableau $a[$i]peuvent être remplacées simplement $$i. Ceci est même vrai si l'index est un entier, car les entiers sont des noms de variables valides en PHP (bien que les littéraux nécessitent des crochets, par exemple ${0}).

Considérez l’implémentation suivante de l’embout Rabonowitz Wagon:

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

Cela peut être amélioré de 6 octets, simplement en remplaçant les deux références de tableau $a[$g]par $$g:

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
Je viens d'économiser 3 octets avec ça: vitrine .
Titus

6

Apprenez un grand sous-ensemble des fonctions de la bibliothèque .

La bibliothèque de PHP est assez énorme et fournit une tonne de fonctions pratiques qui peuvent grandement raccourcir diverses tâches. Vous pouvez effectuer une recherche chaque fois que vous essayez de faire quelque chose, mais au-delà du temps perdu, vous risquez de ne rien trouver qui corresponde à votre recherche. Le meilleur moyen est simplement de se familiariser avec la bibliothèque et de mémoriser les noms de fonctions et leurs tâches.


6
C'est beaucoup de mémorisation, surtout en raison de la dénomination plutôt incohérente de nombreuses fonctions ;-)
Joey

@ Joey d'accord. Semblable à la mémorisation de la bibliothèque Java, sauf que cela serait sans doute moins utile car plus bavard.
Matthew Lu

3
Je trouve que les fonctions les plus importantes pour les défis que j'ai rencontrés jusqu'ici sont les fonctions de manipulation de chaînes et de tableaux. L'utilisation créative de ceux-ci peut vraiment réduire le code.
migimaru

6

Exécuter des fonctions à l'intérieur de chaînes.

Essaye ça:

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

Ou essayez ceci:

//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

Cela ne fonctionne qu'avec des chaînes utilisant ""et heredocs (NE FAITES PAS confusion avec nowdocs).

L'utilisation de fonctions imbriquées n'est possible que dans heredocs imbriqué (sinon vous rencontrerez des erreurs d'analyse)!


you will run into parse errorsJe ne peux pas le lire moi-même? Comment le moteur Zend est-il à l'origine de cette situation?
Stan Strum

La prochaine fois que je serai dans l' argument "PHP est un bon langage de programmation" , je vais l'utiliser comme contre-point. Sensationnel.
primo

@primo Est-ce si mauvais? : O
Ismael Miguel

5

amusement avec les typecasts

  • !!$footransformera toute valeur de vérité en true(ou 1en sortie), les valeurs de fausseté (0, chaîne vide, tableau vide) en false(ou sortie vide)
    Ceci sera rarement nécessaire en code golf, car dans la plupart des cas, vous avez besoin un casting implicite quand même.

  • (int)$foopeut être écrit comme $foo|0ou foo^0, mais peut avoir besoin de parenthèses.
    Pour les booléens et les chaînes, $foo*1ou +$foopeut être utilisé pour lancer int.

  • Contrairement à la plupart des autres langages, PHP traite les chaînes avec des valeurs numériques sous forme de nombres. Donc, si vous avez une chaîne contenant un nombre avec lequel vous devez calculer, calculez simplement.
  • L’autre méthode ne fonctionne pas : pour multiplier un nombre dans une variable 10, vous pouvez ajouter un zéro: *10-> .0. Mais dans ce cas, PHP prendra le point comme point décimal et se plaindra. (Il en va différemment si vous avez une quantité variable de zéros dans une chaîne.)
  • Pour transformer un tableau en chaîne, utilisez joinplutôt que implode.
    Si vous n’avez pas besoin de délimiteur, ne l'utilisez pas: join($a)fait la même chose quejoin('',$a)
  • Incrémentation de chaînes: La fonctionnalité la plus étonnante est celle qui $s=a;$s++;produit $s=b;. Cela fonctionne avec les caractères majuscules et minuscules. $s=Z;$s++;résultats en $s=AA;.
    Cela fonctionne aussi avec des cas mixtes: aZto bA, A1to A2, A9to B0et z99Zto aa00A.
    La décrémentation ne fonctionne pas sur les chaînes. (Et ça ne marche pas NULL).
    Retour en PHP 3, $n="001";$n++;produit $n="002";. Je suis un peu triste, ils ont enlevé ça.

Quoi que vous fassiez au golf: ayez toujours le tableau de priorité des opérateurs à portée de main.


4

Utilisez des étiquettes courtes

En code normal, c'est une bonne pratique d'utiliser <?phpet ?>. Cependant, ce n'est pas un code normal - vous écrivez un code de golf. Au lieu de <?php, écrivez <?. Au lieu de <?php echo, écrivez <?=. Ne tapez pas ?>à la fin - c'est complètement facultatif. Si vous avez besoin ?>pour une raison quelconque (par exemple, pour produire du texte qui est plus court, ne mettez pas de point-virgule avant, cela n'est pas nécessaire, ce qui ?>implique un point-virgule.

Mauvais (définitivement trop long):

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

Correct:

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

Avec le -rdrapeau ( qui est gratuit ), vous n’avez même pas de balises (et vous n’êtes pas autorisé à en utiliser).
Titus

4

en boucle à travers des chaînes

peut être fait avec 26 octets ou avec 24 jusqu'à 18:

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&$bfait un bitwise ET sur (les codes ascii de) des caractères dans $aet $b
et donne une chaîne de même longueur que le plus court de $aet $b.


pouvez - vous s'il vous plaît ajouter ord($s[$p++])comme une alternative for(;$s+=ord($argv[++$i])%32?:die($s==100););contre for(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;dans cette question codegolf.stackexchange.com/questions/116933/...
Jörg Hülsermann

Veuillez ajouter ~pour les cas où vous travaillez uniquement avec des chiffres
Jörg Hülsermann

Notez que PHP 7.2 génère des avertissements pour l’ ~$capproche.
Titus

4

Utiliser des opérateurs ternaires

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

peut être abrégé en ceci:

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

Plus court, hein?


"Sténographie conditionnelle"? Mieux vaut dire son vrai nom pour que ceux qui s'intéressent à plus de détails puissent le trouver dans la documentation: opérateur ternaire .
Manatwork

3
La question demande des astuces qui sont quelque peu spécifiques à PHP. Ceci est inclus dans les conseils pour toutes les langues .
Peter Taylor

3
L'opérateur ternaire a un comportement étrange en PHP, si vous l'imbriquiez. a?aa:ab?aba:abb:bévalue (a?aa:ab)?(aba):(abb)ou quelque chose comme ça.
Titus

1
Et à partir de PHP 5.3, vous pouvez omettre le deuxième opérateur: $a?:$best le même que $a?$a:$b.
Titus

1
@Cyoce ||lance un booléen en PHP.
Titus

3

sous un autre nom ... alias de fonction

utilisation ...

  • join au lieu de implode
  • chopau lieu de rtrim(chop PERL est différent!)
  • die au lieu de exit
  • fputs au lieu de fwrite
  • is_intau lieu de is_integerouis_long
  • is_realau lieu de is_floatouis_double
  • key_exists au lieu de array_key_exists
  • mysql au lieu de mysql_db_query

... pour nommer les alias les plus importants. Jetez un coup d'œil à http://php.net/aliases pour plus d'informations.


Oh ... et saviez-vous que cela diefonctionne avec et sans paramètres? die(1)quittera le programme avec un code d'erreur 1(pas tout à fait sûr à ce sujet; nécessite des tests); diesortira avec le code 0et die("Hello")sortira avec le code 0après impression Hello.
Titus

3

Les tableaux associatifs peuvent être fusionnés avec l' +opérateur.

Au lieu de:

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

Utilisation:

$merged = $a + $b;

Notez que l' +opérateur fonctionne également avec les tableaux indexés, mais ne fait probablement pas ce que vous voulez.


En effet, souvent un bon remplaçant, mais pas exactement le même: pastebin.com/seYeaP38
manatwork

Ah ouais, ça y était, j'avais à l'origine le titre "Tableaux associatifs ..." puis je l'avais enlevé. Je vais clarifier, merci.
Alex Howansky

Les tableaux numériques peuvent également être fusionnés à l'aide de +, tant que les index sont distincts. S'ils ne le sont pas, les valeurs du premier tableau seront écrasées par celles du second (comme array_merge). La différence: +ne pas réorganiser les index.
Titus

3

array_flip vs array_search

utilisation

array_flip($array)[$value]

au lieu de

array_search($value,$array)

pour enregistrer 1 octet dans des tableaux où l'occurrence de chaque valeur est unique


3

quelques faits intéressants sur les variables variables

Je devais juste les partager (avant même de vérifier qu'au moins un d'entre eux aide au golf):

  • Utiliser des lettres: les $x=a;$$x=1;$x++;$$x=2;echo"$a,$b";impressions, 1,2
    mais les autres opérations arithmétiques ne fonctionnent pas avec les lettres.
  • Comme mentionné plus haut , vous pouvez utiliser des nombres purs en tant que noms de variables:
    $a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};empreintes 543.
  • Vous pouvez utiliser non seulement [0-9a-zA-Z_]pour les noms de variables, mais pour CHAQUE chaîne:
    $x="Hello!";$$x="Goodbye.";echo${"Hello!"};empreintes Goodbye..
  • Mais: Tout sauf [a-zA-Z_][a-zA-Z_0-9]*les noms de variables nécessite des accolades pour une utilisation littérale.
  • Sans variables définies, $$x=1ensembles ${NULL}identiques à ${false}et ${""}.
  • $a=1;$$a=5;ne définit pas seulement ${1}, mais aussi ${true}.

  • un de plus, le plus étrange que j’ai trouvé jusqu’à présent: Essayez $a=[];$$a=3;echo${[]};. Oui, ça imprime 3!

La raison principale de ceci: les noms de variables sont toujours évalués en chaînes.
(Merci @Christoph pour cette remarque.)
Ainsi, quoi que vous obteniez lorsque vous printou echol'expression, c'est ce que vous obtenez comme nom de variable.


1
Les noms de variables sont convertis en chaînes expliquant les trois derniers points de votre liste. []convertit en Array: ${[]} = 5;echo $Array;empreintes 5. Je suis sûr que vous savez cela , mais il pourrait ne pas être évident pour tout le monde :)
Christoph

@ Jeff j'ai corrigé la faute de frappe. Merci d'avoir remarqué.
Titus

2

sauts de ligne
si la sortie nécessite des sauts de ligne, utilisez un saut de ligne physique (1 octet) au lieu de. "\n"
Cela vous permet également de choisir entre guillemets simples et doubles.


2

éviter les guillemets si possible

PHP jette implicitement des mots inconnus dans des chaînes littérales.

$foo=foo;est identique à $foo='foo';(en supposant qu'il foone s'agisse ni d'un mot clé ni d'une constante définie):$foo=echo; ne fonctionne pas.

MAIS: $p=str_pad;fait; et $p(ab,3,c)évalue àabc .

L'utilisation de littéraux de chaîne sans guillemets donnera un Avis pour Use of undefined constant; mais cela ne se verra pas si vous utilisez la valeur par défaut pour error_reporting(paramètre CLI -n).


Je viens de remarquer: cette réponse est une copie un peu plus longue / mise à jour de codegolf.stackexchange.com/a/2916/55735 .
Titus

Note: PHP avant la 7.2 avait donné des avis (que vous pouvez utiliser avec le -ndrapeau); 7.2 rendements Avertissements; les versions ultérieures vont jeter des erreurs!
Titus

2

Fonctions Arrow en PHP 7.4

PHP 7.4 est en version RC2 et devrait être publié dans environ 2 mois. La liste des nouvelles fonctionnalités est ici (cette page peut en fait être mise à jour lorsque la version 7.4 sera disponible). Enfin, dans la version 7.4, PHP a les fonctions de flèche. Ainsi, non seulement les réponses de fonction peuvent être plus courtes, mais il est également possible de passer des commandes à d’autres fonctions. Voici quelques exemples:

Retour entrée + 1:

Fonction anonyme (fermeture) - 25 octets - Essayez-le en ligne!

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

Fonction Arrow - 12 octets - Essayez-le en ligne!

fn($n)=>$n+1

Multipliez les éléments de la première entrée (tableau d'ints) par la deuxième entrée (int):

Fonction anonyme (fermeture) - 72 octets - Essayez-le en ligne!

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

Fonction Arrow - 38 octets - Essayez-le en ligne!

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

Avez-vous remarqué qu'il $nest accessible dans la fonction interne sans use $ndéclaration? Oui, c’est l’une des fonctions de la flèche.


En remarque, je ne pouvais pas faire fonctionner les fonctions de flèches de manière récursive (appeler la même fonction de flèches en elle-même), car nous ne pouvons pas leur donner un nom et les stocker comme fermeture dans une variable comme $f ne le rend pas $faccessible à lui-même ) Ainsi , cet exemple ne fonctionne pas et l' utilisation $fen première ligne provoque une erreur fatale:

$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"

Mais appeler une fonction de flèche avec une autre fonction de flèche fonctionne:

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

Et si au lieu de $f=fn($n)=>$n?$f($n-1):0;vous $f=$F=fn($n)=>$n?$F($n-1):0;? Cela fonctionnerait-il? Et puis tu appelles $(5)comme d'habitude.
Ismael Miguel

@IsmaelMiguel semble toujours avoir la même erreur. Vous pouvez réellement essayer tio.run # php vous-même car Dennis a mis à jour son PHP à 7.4 RC2 il y a quelque temps.
Night2

Je ne peux pas le faire fonctionner. Il semble que seules les variables définies auparavant soient disponibles.
Ismael Miguel


1

Directement des tableaux de déréférence renvoyés par des fonctions.

Par exemple, au lieu de cela:

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

Tu peux faire:

echo foo()[$n];

Cela fonctionne aussi avec les méthodes:

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

Vous pouvez également déréférencer directement les déclarations de tableau:

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

1

Utiliser end()au lieu dearray_pop()

La end()fonction ne déplace pas simplement le pointeur interne à la fin du tableau, elle renvoie également la dernière valeur. Notez bien sûr qu'il ne supprime pas cette valeur, donc si vous ne vous souciez pas de ce que le tableau contient après, vous pouvez l'utiliser à la place de array_pop().


1

double array_flip vs in_array vs array_unique

dans ce cas particulier, un double array_flip enregistre 10 octets

($f=array_flip)($k=$f($c)))supprimer toutes les valeurs doubles dans le tableau et j'ai laissé tomber cela $c=[],, |in_array($o,$c)et remplacer array_keys($c)par$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

Version en ligne

contre

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

Version en ligne

contre array_unique il enregistre 2 octets

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

Version en ligne

Après avoir trouvé un bogue dans ce programme et que le remplacement $x[$i]==$o?:$c[$x[$i]]=$opar ($p=$x[$i])==$o?:$k[$c[$p]=$o]=$ple double array_flip n’était plus nécessaire


coffre-fort associatif array_unique. Yay!
Titus

@Titus J'ai ajouté votre suggestion
Jörg Hülsermann le

1

cordes qui se croisent

Avez-vous déjà utilisé
join("DELIMITER",str_split($s))(31 octets) ou même
preg_replace(".","DELIMITER",$s)(32 octets)
?

Il y a une construction pour ça:

Essayez chunk_split($s,1,"DELIMITER")(29 octets).


Si vous omettez le troisième paramètre, chunk_splitutilisera\r\n ; cela peut vous sauver 7 ou 8 octets.

Mais méfiez-vous: chunk_splitajoute également le délimiteur à la chaîne,
sorte que vous n'obtenez peut-être pas exactement ce que vous voulez.

(Si vous ne fournissez pas la longueur du morceau, il utilisera 76. Plutôt inhabituel pour le golf de code, mais qui sait.)


Peut-être devriez-vous ajouter un exemple en combinaison avec strtrJ'aime cette idée.
Jörg Hülsermann

1

unset () vs INF

Dans un cas, recherchez un minimum dans un tableau que vous pouvez utiliser à la place de

unset($var[$k]);

$var[$k]=INF;

économiser 3 octets


1

str_repeat

Dans certains cas, vous avez une entrée de caractères et vous devez les sortir répétée avec une valeur plus grande à zéro pour chaque caractère.

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

(52 octets) est plus court que

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

ou

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

(54 octets chacun)

Comment ça marche par exemple l'entrée a1b2c1

$zn'est pas défini (implicite NULL), ainsi --$zne fait rien et est fausseté;

$c="a", $z="1"et $i=2-> $c.$z="a1"est la vérité -> sortie"a"

--$z=0; donc nous avons mis $c="b", $z="2"(et $i=4) -> $c.$z="b2"est la vérité -> sortie"ab"

--$z=1 -> sortie "abb"

--$z=0; donc nous définissons $c="c"et $z=1 $c.$z="c1"est vraie sortie"abbc"

--$z=0so $c=""and $z=""-> $c.$z=""is falsy -> boucles de boucle


1

Combinaison de forboucles

Supposons que vous ayez un code de la forme suivante:

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

cela peut généralement être relancé sous la forme suivante:

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

représente un opérateur de combinaison générique. Cela se traduit généralement par une réduction du nombre d'octets, mais nécessitera probablement un peu de créativité. $cond2devra être écrit pour qu'il échoue la première fois. $post1devrait également échouer lors de la première exécution, bien qu’il soit peut-être plus facile de refactoriser au préalable pour que$post1 ne soit pas présent.

Si vous travaillez avec trois boucles imbriquées ou plus, vous pouvez également en combiner deux en premier, puis combiner cela à une autre, etc. Je trouve qu'il a généralement été plus facile de combiner de l'intérieur vers l'extérieur.


A titre d'exemple, considérons la solution suivante à la fractale de tapis en H ( 97 octets ):

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;

Ceci peut être reformulé de la manière suivante:

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&&printempêche printà la première itération, et n'incrémente pas non plus $i.

et enfin ( 93 octets ):

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 échouera la première fois car les deux variables ne sont pas définies.


1

Supprimer des caractères dans une chaîne

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

enregistre 1 caractère par rapport à

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

Notez que cela fonctionne pour toutes les chaînes (non vides), pas seulement pour les caractères.
CalculatriceFeline

@CalculatorFeline Pourquoi cela ne fonctionnerait-il pas pour les chaînes vides? Cela n'a aucun sens ou ce cas.
Jörg Hülsermann

La première version ne fonctionne pas avec ""et ce n’est pas très utile de toute façon.
CalculatriceFeline

1
@CalculatorFeline Et dans ce cas, une solution de zéro octet est bien meilleure. Cela n'a aucun sens de le faire de cette façon.
Jörg Hülsermann

3
Votre exemple de jointure manque un ). Et strtr($string,[" "=>""])est encore plus court.
Titus


1

Utilisez des opérateurs booléens au lieu de strtoupper()etstrtolower()

Si vous travaillez exclusivement avec des chaînes composées de caractères alphabétiques, vous pouvez utiliser des opérateurs booléens pour les changer en majuscules ou en minuscules avec moins de frappes au clavier que les fonctions intégrées de PHP.

Exemple:

// 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

Les choses sont un peu plus délicates pour les chaînes de longueur arbitraire, mais les opérateurs &et ^vont tronquer le résultat à la longueur de la chaîne d'entrée la plus courte. Donc, par exemple, si$W une chaîne d'espaces est au moins aussi longue que n'importe quelle entrée $s, alors ~$W&$séquivaut à strtoupper($s), et $s|$W^$séquivaut à strtolower($s)(alors que $s|$Wlui-même produira une chaîne avec des espaces supplémentaires à moins que $set ne $Wsoient de même longueur).


0

utiliser les fonctions dépréciées
Si vous pouvez utiliser au lieu de Posix PERL regex sans perdre plus de 5 octets sur l'expression, l' utilisation eregou au eregilieu depreg_match , splitou au splitilieu de preg_split.
splitPeut aussi être utilisé comme synonyme explodepour la plupart des délimiteurs.

Ces fonctions sont marquées obsolètes et jetteront E_DEPRECATED avis, mais (je ne trouve pas la source maintenant). Je pense avoir lu que les avertissements et les avis sont acceptables.


2
Fais attention! Ceux-ci ont été supprimés dans PHP 7.0.
Umbrella
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.