¿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
AS
es una construcción de lenguaje, no se requiere un espacio antes de la variable$b
, pero si se omitiera el espacio anterior ,$aAS
se 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";
. Laecho
construcció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 unaecho
es 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:echo
es una construcción pura sin valor de retorno, mientras queprint
puede 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.ini
archivoNo 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 errors
No puedo leerlo yo mismo? ¿Cómo funciona el molesto motor Zend?diversión con tipos de letra
!!$foo
convertirá cualquier valor verdadero atrue
(o1
en 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)$foo
puede escribirse como$foo|0
ofoo^0
, pero puede necesitar paréntesis.Para booleanos y cadenas,
$foo*1
o+$foo
puede 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).join
lugar 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:
aZ
tobA
,A1
toA2
,A9
toB0
yz99Z
toaa00A
.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
<?php
y?>
. Sin embargo, este no es un código normal: está escribiendo un código de código de golf. En lugar de<?php
escribir<?
. En lugar de<?php echo
escribir<?=
. 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
-r
bandera ( 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&$b
hace un AND bit a bit en los (códigos ascii de) los caracteres en$a
y$b
y da como resultado una cadena que tiene la misma longitud que la más corta de
$a
y$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~$c
enfoque.Usar operadores ternarios
se puede abreviar a esto:
Más corto, ¿eh?
fuente
a?aa:ab?aba:abb:b
evalúa(a?aa:ab)?(aba):(abb)
o algo así.$a?:$b
es lo mismo que$a?$a:$b
.||
en booleano en PHP.por cualquier otro nombre ... alias de funciones
utilizar ...
join
en lugar deimplode
chop
en lugar dertrim
(chop
en PERL es diferente!)die
en lugar deexit
fputs
en lugar defwrite
is_int
en lugar deis_integer
ois_long
is_real
en lugar deis_float
ois_double
key_exists
en lugar dearray_key_exists
mysql
en lugar demysql_db_query
... para nombrar los alias más importantes. Echa un vistazo a http://php.net/aliases para más.
fuente
die
funciona con y sin parámetros?die(1)
saldrá del programa con un código de error1
(no estoy completamente seguro de esto; necesita pruebas);die
saldrá con código0
ydie("Hello")
saldrá con código0
despué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,2
pero 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=1
establece${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ú
print
oecho
la 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 quefoo
no 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
-n
bandera); 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?
$n
es accesible en la función interna sin unause $n
declaració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
$f
no hace$f
accesible dentro de sí mismo (triste ) Entonces este ejemplo no funciona y usar$f
en 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$k
Versió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]]=$o
de($p=$x[$i])==$o?:$k[$c[$p]=$o]=$p
la 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_split
usará\r\n
; eso puede ahorrarle 7 u 8 bytes.Pero cuidado:
chunk_split
tambié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
strtr
Me 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
$z
no está establecido (implícitoNULL
), entonces--$z
que 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=0
entonces$c=""
y$z=""
->$c.$z=""
es falso -> el bucle se rompefuente
Combinando
for
buclesSupongamos 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.$cond2
deberá escribirse para que falle la primera vez.$post1
también debe fallar la ejecución la primera vez, aunque puede ser más fácil refactorizar de antemano para que$post1
no 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&&print
previeneprint
en la primera iteración y tampoco aumenta$i
.y finalmente ( 93 bytes ):
$H>$e*=3
fallará 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$W
es una cadena de espacios al menos tan larga como cualquier entrada$s
, a continuación,~$W&$s
es equivalente astrtoupper($s)
, y$s|$W^$s
es equivalente astrtolower($s)
(mientras que$s|$W
por sí misma producirá una cadena con espacios adicionales a menos$s
y$W
son 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
ereg
oeregi
en lugar depreg_match
,split
ospliti
en lugar de preg_split.split
También se puede usar como sinónimo deexplode
de la mayoría de los delimitadores.Estas funciones están marcadas como obsoletas y arrojarán
E_DEPRECATED
avisos, pero (no puedo encontrar la fuente ahora) Creo que he leído que las advertencias y avisos están bien.fuente