TMTOWTDI
Ese es el consejo de golf Perl más importante que necesita saber. Siempre que esté viendo una secuencia de caracteres demasiado larga que tiene que tener para cumplir su tarea, pregúntese si no hay otra forma de obtener el mismo efecto con una función diferente. Por lo general hay. Aquí hay solo un puñado:
~~
aplica un contexto escalar y es 4 caracteres más corto que scalar
.
y///c
es un char más corto que length
al obtener la longitud de $_
.
¿Necesita iterar sobre los caracteres en $_
? Reemplazar split//
con /./gs
. (O /./g
úselo si también desea omitir nuevas líneas). Esto funciona con otras variables: reemplazar split//,$x
con $x=~/./gs
.
Cada Perl incorporado devuelve algo. print
devuelve 1, por ejemplo, para indicar E / S exitosa. Si necesita inicializar $_
a un valor verdadero, por ejemplo, le $_=print$foo
permite matar dos pájaros de un tiro.
Casi todas las declaraciones en Perl se pueden escribir como una expresión, lo que permite su uso en una variedad más amplia de contextos. Las declaraciones múltiples pueden convertirse en múltiples expresiones encadenadas junto con comas. Las pruebas se pueden realizar con operadores de cortocircuito ?:
&&
||
, y también con and
y or
, que hacen lo mismo pero con una prioridad inferior a la de todos los demás operadores (incluida la asignación). Los bucles se pueden hacer a través de map
o grep
. Incluso palabras claves como next
, last
y return
puede ser utilizado en un contexto de expresión, a pesar de que no vuelvan! Tener en cuenta este tipo de transformaciones le brinda la oportunidad de reemplazar los bloques de código con expresiones que pueden integrarse en una variedad más amplia de contextos.
$_=print""
es más corto que$_=print$foo
.$foo
. De lo contrario,$_=1
es mucho más corto$_=print""
y tiene el mismo efecto.$x
? De lo contrario, podrías hacer/./gs
y/./g
.¡Abusa de las variables especiales de Perl!
Como se señaló en una respuesta anterior
$/
y$"
se inicializan por defecto en"\n"
y" "
, respectivamente.$,
y$\
están configuradosundef
por defecto, y son 3 caracteres más cortos.Establecer
$\
un valor hará que se agregue a todosprint
. Por ejemplo:perl -ple '$\="=".hex.$/'
es un práctico convertidor hexadecimal a decimal.Si no está leyendo archivos desde la línea de comandos, puede usar el
-i
interruptor de la línea de comandos como un canal adicional para ingresar una cadena. Su valor se almacenará en$^I
.$=
obliga a lo que se le asigna a ser un número entero. Intenta correrperl -ple '$_=$==$_'
y darle varias entradas. Del mismo modo,$-
obliga a su valor a ser un número entero no negativo (es decir, un guión inicial se trata como un carácter no numérico).Puede usarlo
$.
como un indicador booleano que se restablece automáticamente a un valor verdadero (distinto de cero) en cada iteración de unwhile(<>)
bucle.fuente
-n
y brackets rizados inigualablesEs bien sabido que el interruptor de línea de comando
-n
se puede utilizar para ejecutar el script una vez por cada línea.perl --help
dice:Lo que no dice explícitamente es que Perl no solo asume un ciclo alrededor del programa; que , literalmente, se envuelve
while (<>) { ... }
alrededor de ella.De esta manera, los siguientes comandos son equivalentes entre sí:
-p
y brackets rizados inigualablesDe manera similar a lo anterior, el
-p
interruptor se envuelvewhile (<>) { ... ; print }
alrededor del programa.Al usar llaves sin igual,
perl -p 'code}{morecode'
solo se imprimirá una vez después de la ejecucióncode
para todas las líneas de entrada, seguido demorecode
.Como
$_
no se define cuandomorecode;print
se ejecuta,$\
se puede abusar del separador de registros de salida para imprimir la salida real.Por ejemplo
lee un número por línea de STDIN e imprime su suma.
fuente
#!perl -n
en la primera línea, ¿verdad?-p
y$\
) por primera vez en una de las respuestas de Perl de @primo . Leer sus respuestas es un buen consejo de Perl por sí solo.}for(...){
paréntesis entre los aparatos también suele ser bastante útil, por ejemplo, codegolf.stackexchange.com/a/25632Se usa
$_
para eliminar referencias escalares. Es la variable especial que se usa por defecto en la mayoría de las funciones, y dejar de lado los parámetros es un atajo para hacer referencia a esta variable.Al cambiar
$n
a$_
, puede cambiar$n=<>;chop$n;print$n
a$_=<>;chop;print
Aquí, la
print
función imprime el contenido de$_
forma predeterminada ychop
también funciona$_
.fuente
$_=<>;
obligatorio, ¿no<>;
lee la línea$_
automáticamente?$_=<>;print
y<>;print
. El primero me repite lo que escribo, mientras que el otro no.print while(<>)
. No estoy seguro si se trata de un caso especial o si hay una lógica coherente detrás de él, ni<>
parteperlop
niwhile
parte deperlsyn
parece mencionar este comportamiento.while(<>)
es un caso especial, documentado en perlsyn, Operadores de E / S: 'Si y solo si el símbolo de entrada es lo único dentro del condicional de una declaración "while" (incluso si se disfraza como "for (;;)" loop), el valor se asigna automáticamente a la variable global $ _, destruyendo lo que estaba allí anteriormente. "Utilice las variables especiales de Perl siempre que pueda, por ejemplo:
$"
lugar de" "
$/
lugar de"\n"
Tienen el beneficio adicional de ser un identificador largo garantizado de un carácter, con la ayuda del lexer. Esto permite pegarlo a la palabra clave que lo sigue, como en:
print$.for@_
La lista de todas las variables especiales está disponible aquí: Variables especiales
fuente
No utilice
qw
. Esto es un desperdicio de dos personajes que podrían usarse de una mejor manera. Por ejemplo, no escriba lo siguiente.En su lugar, use palabras vacías.
O si no puede usar palabras simples, use la
glob
sintaxis.glob
La sintaxis también se puede utilizar para efectos interesantes.fuente
Utilice modificadores de declaración en lugar de declaraciones compuestas.
Las declaraciones compuestas tienden a requerir paréntesis para el argumento y llaves para el bloque, mientras que los modificadores de declaraciones no necesitan ninguna.
Comparar:
$a++,$b++while$n--
vswhile($n--){$a++;$b++}
chop$,if$c
vsif($c){chop$,}
Tenga en cuenta que el último ejemplo se vincula con
$c&&chop$,
, pero comienza a brillar realmente para la mayoría de las operaciones de múltiples declaraciones. Básicamente todo lo que pierde la prioridad del operador&&
.fuente
No hacerlo
use strict
. (no me cite sobre esto, el contexto PCG.SE es importante) Y, lo que es más importante, no codifique como si fuera estricto. Los sospechosos de siempre:my
declare variables si puede evitarlo. Las únicas variables que realmente necesitanmy
son aquellas que desea tener un alcance léxico. Eso es apenas uno de ellos cuando se juega al golf, donde no necesita protección de alcance y tiende a controlar completamente la recursividad.fuente
print hello
no funciona En realidad significaprint hello $_
(imprimir$_
en el controlador de archivohello
).print
, y ahora no puedo encontrar un buen y breve ejemplo)Estoy seguro de que algunos de estos tienen nombres formales y simplemente no estoy al tanto de ellos.
print $n++ while ($n < 10)
$var = join('',<>)
print ('X'*10) . "\n";
es más largo queprint ('X'*10) . $/;
say
función de Perl es más corta queprint
, pero tendrá que ejecutar el código en-E
lugar de-e
a..z
o inclusoaa..zz
. Si es necesario como una cadena, usejoin
.$z = 'z'; print ++$z;
se mostraráaa
Eso es todo lo que puedo pensar en este momento. Puedo agregar algo más más tarde.
fuente
print ('X'*10) . $/;
supone que debe hacer? Para mí se imprime0
y no hay línea nueva. Por un lado, los paréntesis se convierten en un argumento de llamada de estilo de funciónprint
, que se une más fuerte que.
. ¿Y quiso decir enx
lugar de*
o algo así?while
,join'',<>;
también funciona sin ellos.Use caracteres que no sean palabras como nombres de variables
Utilizando
$%
en lugar de$a
se permitirá colocar el nombre de la variable justo al lado de unaif
,for
owhile
construir como en:@r=(1,2,3,4,5);$%=4;
print$_*$%for@r
Se pueden usar muchos, pero revisa los documentos y la respuesta de @ BreadBox para saber cuáles tienen efectos mágicos.
Use el mapa cuando no pueda usar modificadores de instrucciones
Si no puede usar modfiers de declaración según la respuesta de @ JB , el mapa puede guardar un byte:
for(@c){}
vs.map{}@c;
y es útil si desea hacer iteraciones anidadas, ya que puede colocar
for
bucles postfix dentro demap
.Usa todas las variables mágicas de Expresión Regular
Perl tiene variables mágicas para 'texto antes del partido' y 'texto después del partido', por lo que es posible dividirlo en grupos de dos con potencialmente menos caracteres:
Esto también podría funcionar bien como un reemplazo para
substr
:Si necesita el contenido del partido,
$&
se puede utilizar, por ejemplo:Reemplazar subs por nombres largos con un nombre más corto
Si llama por ejemplo
print
cuatro o más veces en su código (esto obviamente varía con la duración de la rutina que está llamando), reemplácelo con un subnombre más corto:vs.
Reemplazar incrementos / decrementadores condicionales
Si tienes un código como:
puedes usar:
en cambio para guardar algunos bytes.
Convertir a entero
Si no está asignando a una variable y no puede usar la sugerencia de breadbox , puede usar la expresión
0|
:Sin embargo, vale la pena señalar que no necesita usar un número entero para acceder a un índice de matriz:
fuente
redo
agrega comportamiento de bucle a un bloque sinfor
owhile
.{redo}
Es un bucle infinito.fuente
No haga paréntesis de llamadas a funciones.
Perl le permite llamar a una función conocida (núcleo o predeclarada) utilizando la
NAME LIST
sintaxis. Esto le permite soltar el&
sigilo (si todavía lo estaba usando), así como los paréntesis.Por ejemplo:
$v=join'',<>
Documentación completa
fuente
Intente usar el valor de una expresión de asignación, así:
Esto funciona porque
$n
hay 2 caracteres en Perl. Puede cambiar$n
a()
sin costo y guardar 1 punto y coma moviendo la asignación entre paréntesis.fuente
Puede ejecutar varias declaraciones diferentes dentro de la lógica ternaria anidada.
Suponga que tiene un gran
if
-elsif
comunicado. Esto podría ser cualquier lógica y cualquier número de declaraciones.Puede usar
(cmd1, cmd2, cmd3)
dentro del operador ternario para ejecutar todos los comandos.Aquí hay un ejemplo ficticio:
fuente
Usar en
select(undef,undef,undef,$timeout)
lugar deTime::HiRes
(Tomado de https://stackoverflow.com/a/896928/4739548 )
Muchos desafíos requieren que duermas con mayor precisión que los enteros.
select()
El argumento del tiempo de espera puede hacer exactamente eso.es mucho más eficiente que:
El primero tiene solo 20 bytes, mientras que el último ocupa 39. Sin embargo, el primero requiere que no lo esté utilizando
$u
y nunca lo haya definido.Si lo va a usar mucho, la importación
Time::HiRes
vale la pena, pero si solo lo necesita una vez, el usoselect($u,$u,$u,0.1)
ahorra 19 bytes, lo que definitivamente es una mejora en la mayoría de los casos.fuente
Acorte sus declaraciones impresas
A menos que el desafío especifique lo contrario, no necesita líneas nuevas.
Nuestro 'desafío' dice 'generar un número aleatorio de 0 a 9 a STDOUT'. Podemos tomar este código (28 bytes):
Y acortarlo a esto (25 bytes):
simplemente imprimiendo la variable. Este último solo se aplica específicamente a este desafío (19 bytes):
pero eso solo funciona cuando no tiene que hacer nada a la variable entre la asignación y la impresión.
fuente
Use globos como literales de cadena
Ocasionalmente (a menudo cuando se trata de desafíos de quine o de fuente restringida ) se beneficia enormemente de la capacidad de anidar literales de cadena. Normalmente, harías esto con
q(…)
. Sin embargo, dependiendo de los caracteres que necesite dentro de la cadena, puede guardar un byte y usar<…>
el operador global. (Tenga en cuenta que lo que está dentro de los corchetes angulares no puede verse como un identificador de archivo, y no puede parecer que está destinado a expandirse en una lista de nombres de archivo, lo que significa que muchos caracteres no funcionarán correctamente).fuente
Usa la expresión regexe.
Una buena ilustración de esto es el siguiente código que da forma a la entrada en onda sinusoidal:
Como puede ver, es una forma bastante compacta de iterar sobre los caracteres en la entrada estándar. Podría usar otra expresión regular para cambiar la forma en que se combinan las cosas.
fuente