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.
37
Réponses:
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:
Parce que
AS
est 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.la source
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.echo $a+5." text"
cela ne fonctionnera pas car PHP pense que le.
est un point décimal pour le5
. Pour que cela fonctionne, vous devez ajouter un espace comme celui-ci:echo $a+5 ." text"
echo$a+5," text";
. Laecho
construction vous permet de transmettre plusieurs paramètres. là où il faudrait écrireecho"result: ".($a+5)."!";
, vous pouvez écrireecho"result: ",$a+5,"!";
. En fait, transmettre plusieurs paramètres à unecho
est 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.echo
, mais pas avecprint
(ce dont vous avez besoin si vous le mettez dans une expression:echo
est une construction pure sans valeur de retour, alors qu'ilprint
peut agir en tant que fonction: il ne nécessite aucune parenthèse, mais il retourne toujoursint(1)
.print
.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:
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:
Mais lorsque vous jouez au golf, cela peut être facilement réduit à:
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.
la source
E_DEPRECATED
) sont acceptablesphp.ini
fichierVous 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:
Ou dans des fonctions normales
au lieu de
la source
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:Cela économisera cinq octets.
Mais cela peut coûter des octets si vous avez des "trous" dans un tableau associatif:
l'inconvénient frappe un peu plus tard si vous pouvez combler les trous avec des valeurs "vides":
la source
[,$a,$b,$c]=$argv;
.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:
Cela peut être amélioré de 6 octets, simplement en remplaçant les deux références de tableau
$a[$g]
par$$g
:la source
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.
la source
Exécuter des fonctions à l'intérieur de chaînes.
Essaye ça:
Ou essayez ceci:
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)!
la source
you will run into parse errors
Je ne peux pas le lire moi-même? Comment le moteur Zend est-il à l'origine de cette situation?amusement avec les typecasts
!!$foo
transformera toute valeur de vérité entrue
(ou1
en sortie), les valeurs de fausseté (0, chaîne vide, tableau vide) enfalse
(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)$foo
peut être écrit comme$foo|0
oufoo^0
, mais peut avoir besoin de parenthèses.Pour les booléens et les chaînes,
$foo*1
ou+$foo
peut être utilisé pour lancer int.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.)join
plutôt queimplode
.Si vous n’avez pas besoin de délimiteur, ne l'utilisez pas:
join($a)
fait la même chose quejoin('',$a)
$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:
aZ
tobA
,A1
toA2
,A9
toB0
etz99Z
toaa00A
.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.
la source
Utilisez des étiquettes courtes
En code normal, c'est une bonne pratique d'utiliser
<?php
et?>
. 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):
Correct:
la source
-r
drapeau ( qui est gratuit ), vous n’avez même pas de balises (et vous n’êtes pas autorisé à en utiliser).en boucle à travers des chaînes
peut être fait avec 26 octets ou avec 24 jusqu'à 18:
$a&$b
fait un bitwise ET sur (les codes ascii de) des caractères dans$a
et$b
et donne une chaîne de même longueur que le plus court de
$a
et$b
.la source
ord($s[$p++])
comme une alternativefor(;$s+=ord($argv[++$i])%32?:die($s==100););
contrefor(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;
dans cette question codegolf.stackexchange.com/questions/116933/...~
pour les cas où vous travaillez uniquement avec des chiffres~$c
approche.Utiliser des opérateurs ternaires
peut être abrégé en ceci:
Plus court, hein?
la source
a?aa:ab?aba:abb:b
évalue(a?aa:ab)?(aba):(abb)
ou quelque chose comme ça.$a?:$b
est le même que$a?$a:$b
.||
lance un booléen en PHP.sous un autre nom ... alias de fonction
utilisation ...
join
au lieu deimplode
chop
au lieu dertrim
(chop
PERL est différent!)die
au lieu deexit
fputs
au lieu defwrite
is_int
au lieu deis_integer
ouis_long
is_real
au lieu deis_float
ouis_double
key_exists
au lieu dearray_key_exists
mysql
au lieu demysql_db_query
... pour nommer les alias les plus importants. Jetez un coup d'œil à http://php.net/aliases pour plus d'informations.
la source
die
fonctionne avec et sans paramètres?die(1)
quittera le programme avec un code d'erreur1
(pas tout à fait sûr à ce sujet; nécessite des tests);die
sortira avec le code0
etdie("Hello")
sortira avec le code0
après impressionHello
.Les tableaux associatifs peuvent être fusionnés avec l'
+
opérateur.Au lieu de:
Utilisation:
Notez que l'
+
opérateur fonctionne également avec les tableaux indexés, mais ne fait probablement pas ce que vous voulez.la source
+
, 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.array_flip vs array_search
utilisation
au lieu de
pour enregistrer 1 octet dans des tableaux où l'occurrence de chaque valeur est unique
la source
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):
$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.
$a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};
empreintes543
.[0-9a-zA-Z_]
pour les noms de variables, mais pour CHAQUE chaîne:$x="Hello!";$$x="Goodbye.";echo${"Hello!"};
empreintesGoodbye.
.[a-zA-Z_][a-zA-Z_0-9]*
les noms de variables nécessite des accolades pour une utilisation littérale.$$x=1
ensembles${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 imprime3
!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
print
ouecho
l'expression, c'est ce que vous obtenez comme nom de variable.la source
[]
convertit enArray
:${[]} = 5;echo $Array;
empreintes5
. Je suis sûr que vous savez cela , mais il pourrait ne pas être évident pour tout le monde :)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.
la source
é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'ilfoo
ne 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 pourerror_reporting
(paramètre CLI-n
).la source
-n
drapeau); 7.2 rendements Avertissements; les versions ultérieures vont jeter des erreurs!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!
Fonction Arrow - 12 octets - Essayez-le en ligne!
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!
Fonction Arrow - 38 octets - Essayez-le en ligne!
Avez-vous remarqué qu'il
$n
est accessible dans la fonction interne sansuse $n
dé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$f
accessible à lui-même ) Ainsi , cet exemple ne fonctionne pas et l' utilisation$f
en première ligne provoque une erreur fatale:Mais appeler une fonction de flèche avec une autre fonction de flèche fonctionne:
la source
$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.Concernant le fichier I / O:
Lien vers une autre question connexe , dont les réponses conviennent ici.
la source
Directement des tableaux de déréférence renvoyés par des fonctions.
Par exemple, au lieu de cela:
Tu peux faire:
Cela fonctionne aussi avec les méthodes:
Vous pouvez également déréférencer directement les déclarations de tableau:
la source
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 dearray_pop()
.la source
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 remplacerarray_keys($c)
par$k
Version en ligne
contre
Version en ligne
contre array_unique il enregistre 2 octets
Version en ligne
Après avoir trouvé un bogue dans ce programme et que le remplacement
$x[$i]==$o?:$c[$x[$i]]=$o
par($p=$x[$i])==$o?:$k[$c[$p]=$o]=$p
le double array_flip n’était plus nécessairela source
array_unique
. Yay!cordes qui se croisent
Avez-vous déjà utilisé
join("DELIMITER",str_split($s))
(31 octets) ou mêmepreg_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_split
utilisera\r\n
; cela peut vous sauver 7 ou 8 octets.Mais méfiez-vous:
chunk_split
ajoute é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.)
la source
strtr
J'aime cette idée.unset () vs INF
Dans un cas, recherchez un minimum dans un tableau que vous pouvez utiliser à la place de
économiser 3 octets
la source
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.
(52 octets) est plus court que
ou
(54 octets chacun)
Comment ça marche par exemple l'entrée
a1b2c1
$z
n'est pas défini (impliciteNULL
), ainsi--$z
ne 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=0
so$c=""
and$z=""
->$c.$z=""
is falsy -> boucles de bouclela source
Combinaison de
for
bouclesSupposons que vous ayez un code de la forme suivante:
cela peut généralement être relancé sous la forme suivante:
où
•
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é.$cond2
devra être écrit pour qu'il échoue la première fois.$post1
devrait é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 ):
Ceci peut être reformulé de la manière suivante:
$e&&print
empêcheprint
à la première itération, et n'incrémente pas non plus$i
.et enfin ( 93 octets ):
$H>$e*=3
échouera la première fois car les deux variables ne sont pas définies.la source
Supprimer des caractères dans une chaîne
enregistre 1 caractère par rapport à
la source
""
et ce n’est pas très utile de toute façon.)
. Etstrtr($string,[" "=>""])
est encore plus court.array_merge vs array_push
est un octet plus court que
Ne fonctionne pas de la même manière avec les tableaux associatifs
variable-arg-list PHP> 5.6
la source
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:
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|$W
lui-même produira une chaîne avec des espaces supplémentaires à moins que$s
et ne$W
soient de même longueur).la source
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
ereg
ou aueregi
lieu depreg_match
,split
ou auspliti
lieu de preg_split.split
Peut aussi être utilisé comme synonymeexplode
pour 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.la source