¿Qué consejos generales tienes para jugar al golf en PHP? Estoy buscando ideas que puedan aplicarse a los problemas de código de golf en general que sean al menos algo específicos de PHP (por ejemplo, "eliminar comentarios" no es una respuesta). Por favor, publique un consejo por respuesta.
37

Respuestas:
Comprenda cómo las variables y los espacios en blanco interactúan con las construcciones del lenguaje PHP.
En mi tiempo (ciertamente corto) jugando golf, descubrí que las construcciones del lenguaje PHP (por ejemplo, echo, return, for, while, etc.) se comportan de una manera menos que intuitiva cuando interactúan con variables y espacios en blanco.
echo$v;, por ejemplo, es perfectamente válido, como sonreturn$v;y otras construcciones similares. Estas pequeñas reducciones en el espacio en blanco pueden conducir a una disminución acumulativa significativa en la longitud.Sin embargo, tenga en cuenta que las variables antes de las construcciones del lenguaje requieren un espacio después, como en el siguiente ejemplo:
Debido a que
ASes una construcción de lenguaje, no se requiere un espacio antes de la variable$b, pero si se omitiera el espacio anterior ,$aASse analizaría como un nombre de variable y se produciría un error de sintaxis.fuente
foreach($a[1]as$b)No necesita espacios en blanco. No se trata de construcciones y variables del lenguaje, sino de espacios entre caracteres de palabras de diferentes palabras.echo $a+5." text"no funcionará porque PHP piensa que.es un punto decimal para5. Para que funcione, necesitará agregar un espacio como este:echo $a+5 ." text"echo$a+5," text";. Laechoconstrucción le permite pasar múltiples parámetros. donde uno tendría que escribirecho"result: ".($a+5)."!";, puedes escribirecho"result: ",$a+5,"!";. De hecho, pasar múltiples parámetros a unaechoes una microoptimización, ya que el código se ejecutará un poco más rápido (ya que no concatena la salida, sino que la envía por separado). Para los desafíos sobre cómo escribir el código más rápido, esto puede ayudar un poquito minúsculoecho, pero no conprint(lo que necesita si lo coloca dentro de una expresión:echoes una construcción pura sin valor de retorno, mientras queprintpuede actuar como una función: no requiere paréntesis, pero siempre regresaint(1).print.Use cuerdas sabiamente.
Esta respuesta es doble. La primera parte es que al declarar cadenas, puede utilizar la conversión implícita de PHP de constantes desconocidas a cadenas para ahorrar espacio, por ejemplo:
El
@es necesario ignorar las advertencias Esto producirá. En general, terminas con una reducción de un personaje.es que a veces puede ser efectivo desde el espacio establecer una variable con el nombre de una función de uso frecuente. Normalmente, podrías tener:
Pero al jugar al golf, esto se puede acortar fácilmente para:
Con solo dos instancias de "preg_match", solo está guardando un solo carácter, pero cuanto más use una función, más espacio ahorrará.
fuente
E_DEPRECATED) son aceptablesphp.iniarchivoNo siempre necesita escribir cheques condicionales. Por ejemplo, algunos marcos usan esto en la parte superior de sus archivos para bloquear el acceso:
O en funciones normales
en lugar de
fuente
Usar sintaxis de matriz corta
Desde PHP 5.4, las matrices se pueden declarar utilizando corchetes (como JavaScript) en lugar de la
array()función:Ahorrará cinco bytes.
Pero puede costar bytes si tiene "agujeros" en una matriz asociativa:
la desventaja llega un poco más tarde si puede llenar los agujeros con valores "vacíos":
fuente
[,$a,$b,$c]=$argv;.Use $ {0}, $ {1}, $ {2}, ... en lugar de $ a [0], $ a [1], $ a [2], ...
A menos que esté realizando una manipulación de matriz, la mayoría de las referencias a un índice de matriz
$a[$i]se pueden reemplazar simplemente$$i. Esto es incluso cierto si el índice es un entero, ya que los enteros son nombres de variables válidos en PHP (aunque los literales requerirán corchetes, por ejemplo${0}).Considere la siguiente implementación de la espita Rabonowitz Wagon:
Esto se puede mejorar en 6 bytes, simplemente reemplazando ambas referencias de matriz
$a[$g]con$$g:fuente
Aprenda un gran subconjunto de las funciones de la biblioteca .
La biblioteca de PHP es bastante grande y proporciona un montón de funciones convenientes que pueden acortar en gran medida varias tareas. Podrías buscar cada vez que intentes hacer algo, pero más allá de perder el tiempo, es posible que no encuentres nada que coincida con tu búsqueda en particular. La mejor manera es familiarizarse con la biblioteca y memorizar los nombres de las funciones y lo que hacen.
fuente
Ejecutando funciones dentro de cadenas.
Prueba esto:
O prueba esto:
Esto solo funciona con cadenas que usan
""y heredocs (NO confunda con nowdocs).¡El uso de funciones anidadas solo es posible dentro de heredocs anidados (o se encontrará con errores de análisis)!
fuente
you will run into parse errorsNo puedo leerlo yo mismo? ¿Cómo funciona el molesto motor Zend?diversión con tipos de letra
!!$fooconvertirá cualquier valor verdadero atrue(o1en la salida), valores falsos (0, cadena vacía, matriz vacía) afalse(o salida vacía)Esto rara vez se necesitará en el código de golf, ya que en la mayoría de los casos donde necesita un valor booleano, hay un elenco implícito de todos modos.
(int)$foopuede escribirse como$foo|0ofoo^0, pero puede necesitar paréntesis.Para booleanos y cadenas,
$foo*1o+$foopuede usarse para convertir a int.10, puede agregar un cero:*10->.0. Pero en este caso, PHP tomará el punto como punto decimal y se quejará. (Sin embargo, es diferente si tiene una cantidad variable de ceros en una cadena).joinlugar deimplode.Si no necesita un delimitador, no lo use:
join($a)hace lo mismo quejoin('',$a)$s=a;$s++;produce$s=b;. Esto funciona con mayúsculas y minúsculas.$s=Z;$s++;resultados en$s=AA;.Esto también funciona con mayúsculas y minúsculas:
aZtobA,A1toA2,A9toB0yz99Ztoaa00A.La disminución no funciona en cadenas. (Y no está encendido
NULL).De vuelta en PHP 3,
$n="001";$n++;producido$n="002";. Estoy un poco triste porque lo quitaron.Lo que sea que juegue golf: siempre tenga a mano la tabla de precedencia de operadores .
fuente
Use etiquetas cortas
En código normal, es una buena práctica usar
<?phpy?>. Sin embargo, este no es un código normal: está escribiendo un código de código de golf. En lugar de<?phpescribir<?. En lugar de<?php echoescribir<?=. No escriba?>al final, es completamente opcional. Si lo necesita?>por algún motivo (por ejemplo, para generar texto, y de alguna manera es más corto, o algo así, no ponga un punto y coma antes, no es necesario, como?>implica el punto y coma.Incorrecto (definitivamente demasiado largo):
Correcto:
fuente
-rbandera ( que viene gratis ), ni siquiera tienes etiquetas (y no puedes usar ninguna).bucle a través de cadenas
se puede hacer con 26 bytes o con 24 hasta 18:
$a&$bhace un AND bit a bit en los (códigos ascii de) los caracteres en$ay$by da como resultado una cadena que tiene la misma longitud que la más corta de
$ay$b.fuente
ord($s[$p++])como alternativafor(;$s+=ord($argv[++$i])%32?:die($s==100););frentefor(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;a esta pregunta codegolf.stackexchange.com/questions/116933/...~para casos en los que está trabajando solo con dígitos~$cenfoque.Usar operadores ternarios
se puede abreviar a esto:
Más corto, ¿eh?
fuente
a?aa:ab?aba:abb:bevalúa(a?aa:ab)?(aba):(abb)o algo así.$a?:$bes lo mismo que$a?$a:$b.||en booleano en PHP.por cualquier otro nombre ... alias de funciones
utilizar ...
joinen lugar deimplodechopen lugar dertrim(chopen PERL es diferente!)dieen lugar deexitfputsen lugar defwriteis_inten lugar deis_integerois_longis_realen lugar deis_floatois_doublekey_existsen lugar dearray_key_existsmysqlen lugar demysql_db_query... para nombrar los alias más importantes. Echa un vistazo a http://php.net/aliases para más.
fuente
diefunciona con y sin parámetros?die(1)saldrá del programa con un código de error1(no estoy completamente seguro de esto; necesita pruebas);diesaldrá con código0ydie("Hello")saldrá con código0después de imprimirHello.Las matrices asociativas se pueden fusionar con el
+operador.En lugar de:
Utilizar:
Tenga en cuenta que el
+operador también funciona con matrices indexadas, pero probablemente no hace lo que desea.fuente
+, siempre que los índices sean distintos. Si no lo están, los valores de la primera matriz se sobrescribirán con los de la segunda (al igual que array_merge). La diferencia:+no reordena los índices.array_flip vs array_search
utilizar
en lugar de
para guardar 1 byte en matrices donde la aparición de cada valor es única
fuente
algunos datos interesantes sobre variables variables
Solo tenía que compartirlos (incluso antes de verificar que al menos uno de ellos ayuda al golf):
$x=a;$$x=1;$x++;$$x=2;echo"$a,$b";imprime1,2pero otras operaciones aritméticas no funcionan con letras.
$a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};impresiones543.[0-9a-zA-Z_]para nombres de variables, sino CADA cadena: se$x="Hello!";$$x="Goodbye.";echo${"Hello!"};imprimeGoodbye..[a-zA-Z_][a-zA-Z_0-9]*como nombres de variables requiere llaves para uso literal.$$x=1establece${NULL}, que es lo mismo que${false}y${""}.$a=1;$$a=5;no solo establece${1}, sino también${true}.uno más, el más extraño que he encontrado hasta ahora: Inténtalo
$a=[];$$a=3;echo${[]};. Sí, se imprime3!La razón de la mayor parte de esto: los nombres de las variables siempre se evalúan en cadenas.
(Gracias @Christoph por señalar.)
Entonces, lo que obtienes cuando tú
printoechola expresión, eso es lo que obtienes como nombre de variable.fuente
[]se convierte enArray:${[]} = 5;echo $Array;impresiones5. Estoy bastante seguro de que lo sabes, pero puede que no sea obvio para todos :)saltos de línea
si la salida requiere saltos de línea, use un salto de línea físico (1 byte) en lugar de
"\n"Esto también le brinda un posible beneficio para elegir entre comillas simples y dobles.
fuente
evitar comillas siempre que sea posible
PHP arroja implícitamente palabras desconocidas a cadenas literales.
$foo=foo;es lo mismo que$foo='foo';(suponiendo quefoono sea una palabra clave o una constante definida):$foo=echo;no funciona.PERO:
$p=str_pad;hace; y$p(ab,3,c)evalúa aabc.El uso de literales de cadena sin comillas generará un Aviso para
Use of undefined constant; pero eso no se mostrará si usa el valor predeterminado paraerror_reporting(parámetro CLI-n).fuente
-nbandera); 7.2 produce advertencias; versiones posteriores arrojarán errores!Funciones de flecha en PHP 7.4
PHP 7.4 está en la versión RC2 ahora y esperamos que sea lanzado en aproximadamente 2 meses. La lista de nuevas características está aquí (esta página puede actualizarse cuando se lanza 7.4). En 7.4, finalmente PHP tiene las funciones de flecha, por lo que no solo las respuestas de las funciones pueden ser más cortas ahora, sino que también pasar los cierres a otras funciones también puede ser mucho más corto. Aquí están algunos ejemplos:
Entrada de retorno + 1:
Función anónima (cierre) - 25 bytes - ¡ Pruébelo en línea!
Función de flecha - 12 bytes - ¡ Pruébelo en línea!
Multiplique los elementos de la primera entrada (matriz de entradas) por la segunda entrada (int):
Función anónima (cierre) - 72 bytes - ¡ Pruébelo en línea!
Función de flecha - 38 bytes - ¡ Pruébelo en línea!
¿Notaste eso?
$nes accesible en la función interna sin unause $ndeclaración? Sí, esa es una de las características de la función de flecha.Como nota al margen, no pude hacer que las funciones de flecha funcionen recursivamente (llame a la misma función de flecha dentro de sí misma), porque no podemos darles un nombre y almacenarlas como un cierre en una variable como
$fno hace$faccesible dentro de sí mismo (triste ) Entonces este ejemplo no funciona y usar$fen la primera línea causa un error fatal:Pero llamar a una función de flecha dentro de una función de flecha diferente funciona:
fuente
$f=fn($n)=>$n?$f($n-1):0;ti$f=$F=fn($n)=>$n?$F($n-1):0;? Funcionaría eso? Y luego llamas$(5)como siempre.Con respecto a la E / S de archivo:
Vinculación a otra pregunta relacionada , cuyas respuestas encajan aquí.
fuente
Directamente desreferencia de matrices devueltas de funciones.
Por ejemplo, en lugar de esto:
Tu puedes hacer:
Esto también funciona con métodos:
También puede desreferenciar directamente las declaraciones de matriz:
fuente
Usar en
end()lugar dearray_pop()La
end()función no solo mueve el puntero interno al final de la matriz, sino que también devuelve el último valor. Tenga en cuenta, por supuesto, que no elimina ese valor, por lo que si no le importa lo que contiene la matriz después, puede usarlo en lugar dearray_pop().fuente
doble array_flip vs in_array vs array_unique
en este caso especial, un doble array_flip ahorra 10 bytes
($f=array_flip)($k=$f($c)))elimino todos los valores dobles en la matriz y he eliminado esto$c=[],,|in_array($o,$c)y reemplazararray_keys($c)con$kVersión en línea
en contra
Versión en línea
contra array_unique ahorra 2 bytes
Versión en línea
Después de encontrar un error en este programa y la sustitución
$x[$i]==$o?:$c[$x[$i]]=$ode($p=$x[$i])==$o?:$k[$c[$p]=$o]=$pla doble array_flip no era necesario yafuente
array_unique. ¡Hurra!cadenas de intersección
¿Alguna vez ha usado
join("DELIMITER",str_split($s))(31 bytes) o inclusopreg_replace(".","DELIMITER",$s)(32 bytes)?
Hay algo para eso:
Prueba
chunk_split($s,1,"DELIMITER")(29 bytes).Si omite el tercer parámetro,
chunk_splitusará\r\n; eso puede ahorrarle 7 u 8 bytes.Pero cuidado:
chunk_splittambién agrega el delimitador a la cadena,por lo que es posible que no obtenga exactamente lo que desea.
(Si no proporciona la longitud del fragmento, usará 76. Más bien inusual para el golf de código, pero quién sabe).
fuente
strtrMe encanta esta idea.unset () vs INF
En un caso, busque un mínimo en una matriz que pueda usar en lugar de
para guardar 3 bytes
fuente
str_repeat
En algunos casos, tiene una entrada de caracteres y debe generarlos repetidos con una entrada mayor a cero para cada carácter.
(52 bytes) es más corto que
o
(54 bytes cada uno)
Cómo funciona, por ejemplo, entrada
a1b2c1$zno está establecido (implícitoNULL), entonces--$zque no hace nada y es falso;$c="a",$z="1"y$i=2->$c.$z="a1"es verdad -> salida"a"--$z=0; así que establecemos$c="b",$z="2"(y$i=4) ->$c.$z="b2"es veraz -> salida"ab"--$z=1-> salida"abb"--$z=0; así que establecemos$c="c"y$z=1$c.$z="c1"es salida verdadera"abbc"--$z=0entonces$c=""y$z=""->$c.$z=""es falso -> el bucle se rompefuente
Combinando
forbuclesSupongamos que tiene un código de la siguiente forma:
esto generalmente se puede volver a enrollar de la siguiente forma:
donde
•representa un operador de combinación genérico. Esto generalmente resulta en una reducción en el conteo de bytes, pero probablemente requerirá algo de creatividad.$cond2deberá escribirse para que falle la primera vez.$post1también debe fallar la ejecución la primera vez, aunque puede ser más fácil refactorizar de antemano para que$post1no esté presente.Si está trabajando con tres o más bucles anidados, también puede combinar dos primero, y luego combinar eso con otro, y así sucesivamente. Encuentro que en general ha sido más fácil combinar desde adentro hacia afuera.
Como ejemplo, considere la siguiente solución para el fractal de la alfombra H ( 97 bytes ):
Esto puede reformularse de la siguiente manera:
$e&&printprevieneprinten la primera iteración y tampoco aumenta$i.y finalmente ( 93 bytes ):
$H>$e*=3fallará la primera vez ya que ambas variables no están definidas.fuente
Eliminar caracteres en una cadena
ahorra 1 personaje en comparación con
fuente
""y no es muy útil de todos modos.). Ystrtr($string,[" "=>""])es aún más corto.array_merge vs array_push
es un byte más corto que
No funciona igual con matrices asociativas
variable-arg-list PHP> 5.6
fuente
Utilice operadores booleanos en lugar de
strtoupper()ystrtolower()Si está trabajando exclusivamente con cadenas que consisten en caracteres alfabéticos, puede usar operadores booleanos para cambiarlos a mayúsculas o minúsculas con menos pulsaciones de teclas que las funciones integradas de PHP.
Ejemplo:
Las cosas son un poco más difícil para las cadenas de longitud arbitraria, pero las
&y^los operadores se trunque el resultado a la longitud de la cadena de entrada más corto. Así por ejemplo, si$Wes una cadena de espacios al menos tan larga como cualquier entrada$s, a continuación,~$W&$ses equivalente astrtoupper($s), y$s|$W^$ses equivalente astrtolower($s)(mientras que$s|$Wpor sí misma producirá una cadena con espacios adicionales a menos$sy$Wson de igual longitud).fuente
utilizar funciones obsoletas
Si puede utilizar en lugar de Perl POSIX expresiones regulares sin perder más de 5 bytes en la expresión, el uso
eregoeregien lugar depreg_match,splitosplitien lugar de preg_split.splitTambién se puede usar como sinónimo deexplodede la mayoría de los delimitadores.Estas funciones están marcadas como obsoletas y arrojarán
E_DEPRECATEDavisos, pero (no puedo encontrar la fuente ahora) Creo que he leído que las advertencias y avisos están bien.fuente