Consejos para jugar al golf en Perl 6

16

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

Tenga en cuenta que Perl 6 no es Perl 5, por lo que esta pregunta no es un duplicado. La mayoría de los consejos para jugar golf en Perl 5 simplemente no se aplican a Perl 6.

Konrad Borowski
fuente

Respuestas:

9

Evita los subliterales. En muchos casos, simplemente puede usar {}para bloques de código. Por ejemplo, no escriba el siguiente código.

sub ($a){$a*2}

En su lugar, use bloques de sintaxis. Esto también le permite usar $_, @_y las %_variables de marcador de posición, si solo necesita una sola variable. Si necesita más, puede utilizar $^a, $^blas variables, y así sucesivamente.

{$_*2}

Además, en ciertos casos raros, es posible usar cualquier código (especialmente cuando tiene expresiones simples). El *reemplaza el argumento del marcador de posición.

* *2
Konrad Borowski
fuente
8

Perl 6 tiene una característica realmente extraña donde permite que todos los caracteres Unicode en las categorías Nd , NlNo se usen como literales de números racionales. Algunos de estos son más cortos que escribir sus valores numéricos en ASCII:

  • ¼(2 bytes) es más corto que .25o 1/4(3 bytes).
  • ¾(2 bytes) es más corto que .75o 3/4(3 bytes).
  • (3 bytes) es más corto que 1/16(4 bytes).
  • 𐦼(4 bytes) es más corto que 11/12(5 bytes).
  • 𒐲(4 bytes) es más corto que 216e3(5 bytes).
  • 𒐳(4 bytes) es más corto que 432e3(5 bytes).
Lynn
fuente
Como seguimiento de esto, también puede usar exponentes Unicode, incluso con varios dígitos y / o un signo menos: say (3² + 4², 2²⁰, 5⁻²)==> (25 1048576 0.04). La lista completa de Unicode que puede abusar de esta manera está aquí: docs.perl6.org/language/unicode_texas .
Ramillies
8

Aprenda las funciones para leer la entrada. Perl 6 tiene muchas funciones interesantes que pueden leer fácilmente la entrada de ARGV o STDIN (si no se especificó nada en ARGV), lo que puede acortar su código si se usa correctamente. Si los llama como métodos de manejo de archivos, puede obligarlos a trabajar en un manejo de archivos en particular (útil si, por ejemplo, lee STDIN, pero tiene que leer argumentos en ARGV).

get

Esta función obtiene una sola línea y la corta automáticamente para que no tenga que hacerlo. Esto es útil si necesita leer solo una línea.

lines

Esta función obtiene todas las líneas del archivo o STDIN. Es una lista perezosa, por lo que si la usa for, solo leerá lo que necesita. Por ejemplo.

say "<$_>"for lines

slurp

Esto leerá el archivo completo o STDIN, y devolverá el resultado como una sola cadena.

Konrad Borowski
fuente
Ese error se corrigió - no sé cuándo, pero say "<$_>" for linesfunciona ahora
gato
5

Advertencia : Muro de texto acercándose. Son muchos pequeños trucos que reuní con el tiempo.

Escribe tus soluciones como bloques anónimos

Esto ya se mencionó pero me gustaría reiterarlo. En TIO, puede escribir my $f =en el encabezado, el bloque en el código propiamente dicho, y comenzar el pie de página con un ;. Esta parece ser, con mucho, la forma más corta de hacer el trabajo (ya que no necesita preocuparse por leer ninguna entrada, se le da en los argumentos).

Otra buena manera es usar el -no el -pinterruptor, pero no encontré una manera de hacerlo funcionar en TIO.

Use la sintaxis de dos puntos para pasar argumentos

Es decir, en lugar de thing.method(foo,bar), puedes hacer thing.method:foo,bary guardar 1 personaje. Desafortunadamente, no puede llamar a otro método en el resultado por razones obvias, por lo que tiene sentido usar solo el último método en un bloque.

Usa $_todo lo que puedas

A veces es mejor tomar un solo argumento de lista que varios argumentos separados debido a esto. Al acceder $_, puede llamar a los métodos simplemente comenzando con un punto: por ejemplo, .sortes igual a $_.sort.

Sin embargo, tenga en cuenta que cada bloque tiene el suyo propio $_, por lo que los parámetros del bloque externo no se propagarán a los internos. Si necesita acceder a los parámetros de la función principal desde un bloque interno, ...

Usa las ^variables si no puedes usar$_

Insertar una ^entre el sello y el nombre de la variable, así: $^a. Estos funcionan solo dentro de un bloque. El compilador primero cuenta cuántos de estos tiene en el bloque, los ordena lexicográficamente y luego asigna el primer argumento al primero, el segundo al segundo y así sucesivamente. Las ^necesidades para ser utilizado sólo en la primera aparición de la variable. Entonces {$^a - $^b}toma 2 escalares y los resta. Lo único que importa es el orden alfabético, también {-$^b + $^a}lo mismo.

Si alguna vez tiene ganas de usar la sintaxis del bloque puntiagudo (like ->$a,$b {$a.map:{$_+$b}}), es mucho mejor escribir una declaración falsa al comienzo del bloque usando ^para cada argumento que no va a usar en el bloque principal (like {$^b;$^a.map:{$_+$b}}) (Nota esa es la mejor manera de jugar golf {$^a.map(*+$^b)}. Solo quería mostrar el concepto).

Lea atentamente los documentos del operador

Los operadores son muy poderosos y, a menudo, son la forma más corta de hacer las cosas. Especialmente los meta-operadores (operadores que tienen los operadores como un argumento) [], [\], X, <</ >>y Zson dignas de su atención. No olvides que una meta-op puede tomar otra meta-op como argumento (como una XZ%%que logré usar aquí ). También puede usarlo >>para una llamada al método, que puede ser mucho más barato que un mapa (en @list>>.methodlugar de @list.map(*.method), pero tenga cuidado, ¡no son lo mismo! ). Y, finalmente, antes de usar un binario << >>, tenga en cuenta que Za menudo hará lo mismo en muchos menos caracteres.

Si acumula muchas operaciones meta entre sí, puede especificar la precedencia usando corchetes []. Eso le ahorrará cuando acumule tantos operadores que confunda al compilador. (Eso no sucede muy a menudo).

Finalmente, si necesita forzar las cosas a Bool, Int o Str, no use los métodos .Bool, .Inty .Str, sino los operadores ?, +y ~. O incluso mejor, simplemente póngalos en una expresión aritmética para forzarlos a Int y así sucesivamente. La forma más corta de obtener la longitud de una lista es +@list. Si desea calcular 2 a la potencia de la longitud de una lista, simplemente diga 2**@listy hará lo correcto.

Use las variables de estado libre $, @y%

En cada bloque, cada aparición de $(o @o %) se refiere a una nueva variable de estado escalar (o matriz o hash) brillante (una variable cuyo valor persiste a través de las llamadas al bloque). Si necesita una variable de estado a la que solo se debe hacer referencia una vez en el código fuente, estos tres son sus grandes amigos. (La mayoría de las veces $.) Por ejemplo, en el desafío Reverse Math Cycles , podría usarse para elegir los operadores cíclicamente de una matriz, que fue indexada por $++%6.

Usa los sub formularios de map, grepet al.

Eso significa: hacer en lugar map {my block},listde list.map({my block}). Incluso si logra usar list.map:{my block}, estos dos enfoques salen en el mismo número de bytes. Y a menudo, necesitaría poner entre paréntesis la lista cuando se llama a un método, pero no cuando se llama a un sub. Por lo tanto, el subenfoque sale siempre mejor o al menos igual que el método uno.

La única excepción aquí es cuando el objeto que debe ser mapped, grepped , etc., está dentro $_. Entonces .map:{}obviamente late map {},$_.

Use uniones ( &y |) en lugar de &&y ||.

Obviamente, son 1 byte más cortos. Por otro lado, deben colapsarse al ser forzados a un contexto booleano. Esto siempre se puede hacer con un ?. Aquí debe tener en cuenta una meta-operación !opque fuerza el contexto de bool, usa opy niega el resultado.

Si tiene una lista y desea convertirla en un cruce, no use [&]y [|]. En su lugar, use .anyy .all. También hay una .noneque no puede ser tan fácilmente imitada por las operaciones de unión.

Ramillies
fuente
1
Creo &&y ||sigo siendo útil para cortocircuitos?
Solo ASCII
@ Solo ASCII: Sí, ciertamente lo son.
Ramillies
4

Reducir el espacio utilizado para las variables.

Hay algunas partes en esto.

Eliminar espacios en blanco

Las variables declaradas usando mygeneralmente se pueden declarar sin el espacio entre myy el nombre de la variable. my @aes equivalente a my@a.

Usar variables sin sigilo

Puede declarar variables utilizando una barra diagonal inversa para eliminar el sigilo antes del nombre de la variable, de esta manera:

my \a=1;

(desafortunadamente no puedes eliminar el espacio :()

Esto es útil ya que luego puede referirse a ellos como el nombre de la variable desnuda más adelante.

 a=5;
 a.say

Básicamente, esto ahorra bytes si usa la variable más de una vez en otra parte de su código. La desventaja es que la variable necesita ser inicializada.

Uso $!y$/

Estas variables previamente declaradas generalmente se usan para excepciones y coincidencias de expresiones regulares respectivamente, pero no es necesario definirlas usando my.

$!=1;
$/=5;

Especialmente útil es usarlo $/como una matriz y usar los atajos $seguidos de un número para acceder a ese elemento de la $/matriz;

$/=100..200;
say $5;  #105
say $99; #199
Jo King
fuente
2

Usar en ...lugar defirst

Por lo general, si desea encontrar el primer número que coincide con alguna condición &f, puede representarlo como:

first &f,1..*

Sin embargo, en su lugar, puede usar el ...operador:

+(1...&f)

Si tiene que comenzar 0, puede tener -1después en lugar de +.

Si desea el índice del primer elemento en una lista @aque tiene condición &f, normalmente lo hace:

first &f,@a,:k

En lugar:

(@a...&f)-1

(o viceversa si quieres 0 indexado). Del mismo modo, puede obtener todos los elementos hasta el primero que pase la condición.

Lo malo de esto es que la lista tiene que pasar la condición en algún momento, de lo contrario, el ...operador intentará extrapolar al final de la lista y lo más probable es que arroje un error. Tampoco puede usar el código Cualquiera en el lado izquierdo, ya que se interpretaría como parte de la secuencia.

Jo King
fuente