¿Qué consejos generales puedes dar para jugar al golf en Ruby?
Estoy buscando ideas que se puedan aplicar a los problemas de código de golf en general que sean específicos de Ruby. (Por ejemplo, "Eliminar comentarios" no sería una respuesta).
Por favor, publique un consejo por respuesta.
Respuestas:
?d
a?~
en 1.8.$><<"string"
es más corta queprint"string"
.$<.map{|l|...}
es más corto quewhile l=gets;...;end
. También puedes usarlo$<.read
para leerlo todo de una vez.$<
ygets
leerá desde un archivo en lugar de stdin si el nombre de archivo está enARGV
. Así que la forma golfiest volver a implementarcat
sería:$><<$<.read
.fuente
cat
es dejar el archivo ruby completamente vacío (0 bytes) e insistir en que se ejecute desde la línea de comando con la-p
bandera.puts *$<
☺
o♫
, o si estás lo suficientemente loco:?﷽.ord=65021
Use el operador splat para obtener la cola y la cabeza de una matriz:
Esto también funciona a la inversa:
Use el
*
método con una cadena en una matriz para unir elementos:fuente
abort
para terminar el programa e imprimir una cadena en STDERR, más corta que laputs
seguida porexit
gets
, puede usarla~/$/
para encontrar su longitud (esto no cuenta una nueva línea final si existe)[]
para verificar si una cadena contiene otra:'foo'['f'] #=> 'f'
tr
lugar degsub
sustituciones de carácter sabio:'01011'.tr('01','AB') #=> 'ABABB'
chop
lugar dechomp
fuente
abort
y~/$/
~/$/
gets
, su resultado se almacena en la$_
variable./regex/ ~= string
Devuelve el índice del primer partido. Llamar~
a una expresión regular es equivalente a/regex/ ~= $_
. Entonces sería algo asís=gets;l= ~/$/
Termina tu
end
.Intenta eliminarlo
end
de tu código.No lo use
def...end
para definir funciones. Haga una lambda con el nuevo operador -> en Ruby 1.9. (El operador -> es un "stada lambda", o "cohete guión" ). Esto ahorra 5 caracteres por función.Las llamadas al método son
c n
oc(n)
. Las llamadas de Lambda sonc[n]
. Cambiando cadac n
ac[n]
los costos de 1 carácter, por lo que si se puede usarc n
más de 5 veces, a continuación, seguir el método.Todos los métodos que toman
do...end
bloques pueden tomar{...}
bloques en su lugar. Esto ahorra de 3 a 5 caracteres. Si la precedencia de{...}
es demasiado alta, utilice paréntesis para solucionarlo.Reemplace
if...else...end
con el operador ternario?:
. Si una rama tiene dos o más declaraciones, envuélvalas entre paréntesis.Probablemente no tenga
while
niuntil
bucles, pero si los tiene, escríbalos en forma de modificador.fuente
puts'statement 3'
necesarios los paréntesis ?Adición a w0lf
Combinado con el anterior -> puede hacerlo aún más corto
-[p]
para guardar otros 2 caracteres.fuente
Utilice las variables predefinidas cortas siempre que sea posible, por ejemplo, en
$*
lugar deARGV
. Hay una buena lista de ellos aquí , junto con una gran cantidad de otra información útil.fuente
Cuando utiliza la interpolación de cadenas (como debería hacer con la publicación de Martin Büttner ), no necesita los corchetes si su objeto tiene un sigilo (
$
,@
) delante. Útil para las variables mágicos como$_
,$&
,$1
etc:Por lo tanto, si necesita imprimir una variable más de lo que usa, de lo contrario, puede guardar algunos bytes.
fuente
Si necesita encontrar si un elemento en particular
e
está dentro de un rangor
, puede usaren lugar del más largo:
o
o
fuente
r===e
siquiera es más corto?===
implementado todo lo que se puede usar en una declaración de cambio .$_
es la última línea leída.print
- si no hay argumento dado el contenido impreso de$_
~/regexp/
- corto para$_=~/regexp/
En Ruby 1.8, tiene cuatro métodos
Kernel
que operan en$_
:chop
chomp
sub
gsub
En Ruby 1.9, estos cuatro métodos existen solo si su script usa
-n
o-p
.Si desea imprimir alguna variable con frecuencia, use
trace_var(:var_name){|a|p a}
fuente
-p
o-n
. Referencia.trace_var
solo funciona con variables globales $¡Usa la interpolación de cuerdas!
Para reemplazar
to_s
. Si necesita paréntesis alrededor de lo que quiera convertir en una cadena,to_s
es dos bytes más largo que la interpolación de cadenas:Para reemplazar la concatenación. Si concatena algo rodeado por otras dos cadenas, la interpolación puede ahorrarle un byte:
También funciona si la cosa del medio está concatenada, si solo mueve la concatenación dentro de la interpolación (en lugar de usar interpolaciones múltiples):
fuente
Evitar
length
enif a.length<n
length
es de 6 bytes, un poco costoso en el código de golf. en muchas situaciones, puede verificar si la matriz tiene algo en un punto dado. si pasas el último índice que obtendrásnil
, un valor falsey.Para que pueda cambiar:
if a.length<5
aif !a[4]
de -5 byteso
if a.length>5
aif a[5]
de -6 byteso
if a.length<n
aif !a[n-1]
para -3 byteso
if a.length>n
aif a[n]
de -6 bytesNota : solo funcionará con una matriz de todos los valores de verdad. tener
nil
ofalse
dentro de la matriz puede causar problemas.fuente
size
... Pero esto definitivamente es mejor. Por cierto, también funciona paraString
.No use las palabras clave
true
yfalse
.Utilizar:
!p
portrue
(gracias, histocrat!)!0
parafalse
. Si todo lo que necesita es un valor falso, simplemente puede usarp
(que devuelvenil
).para guardar algunos caracteres
fuente
true
(es decir, si un valor verdadero es suficiente, como en una condición if), ni siquiera lo necesita!!
.p
(que se evalúa comonil
) es un valor de falsey más corto. Lo que significa que la forma más corta de llegartrue
es!p
.Construya matrices usando
a=i,*a
para obtenerlas en orden inverso. Ni siquiera necesita inicializara
, y si lo hace, no tiene que ser una matriz .fuente
Si alguna vez necesita obtener un número de
ARGV
,get
o algo similar para hacer algo que muchas veces, en lugar de invocarloto_i
, puede usar?1.upto x{do something x times}
donde x es una cadena.Por lo tanto, usar en
?1.upto(a){}
lugar dex.to_i.times{}
le ahorrará 2 caracteres.También puedes volver a escribir cosas como
p 1 while 1
op 1 if 1
comop 1while 1
op 1if 1
Ese ejemplo no es muy útil, pero podría usarse para otras cosas.
Además, si necesita asignar el primer elemento de una matriz a una variable,
a,=c
guardará dos caracteres en lugar dea=c[0]
fuente
Nuevas características en Ruby 2.3 y 2.4
Es bueno estar al tanto de las nuevas características del lenguaje que ayudarán a su juego de golf. Hay algunos geniales en los últimos Rubies.
Ruby 2.3
El operador de navegación segura:
&.
Cuando llama a un método que puede regresar
nil
pero desea encadenar llamadas de método adicionales si no es así, desperdicia bytes manejando elnil
caso:El "operador de navegación segura" detiene la cadena de llamadas a métodos si uno regresa
nil
y regresanil
para la expresión completa:Array#dig
YHash#dig
Acceso profundo a elementos anidados, con un bonito nombre corto:
Devuelve
nil
si llega a un callejón sin salida:Enumerable#grep_v
El inverso de:
Enumerable#grep
devuelve todos los elementos que no coinciden con el argumento dado (en comparación con===
). Por ejemplogrep
, si se da un bloque, se devuelve su resultado.Hash#to_proc
Devuelve un Proc que produce el valor de la clave dada, que puede ser bastante útil:
Ruby 2.4
Ruby 2.4 aún no está disponible, pero lo estará pronto y tiene algunas características excelentes. (Cuando se publique, actualizaré esta publicación con algunos enlaces a los documentos). Aprendí sobre la mayoría de estos en esta gran publicación de blog .
Enumerable#sum
No más
arr.reduce(:+)
. Ahora solo puedes hacerarr.sum
. Toma un argumento opcional de valor inicial, que por defecto es 0 para elementos numéricos ([].sum == 0
). Para otros tipos, deberá proporcionar un valor inicial. También acepta un bloque que se aplicará a cada elemento antes de la adición:Integer#digits
Esto devuelve una matriz de dígitos de un número en orden de importancia menor a mayor:
Comparado con, digamos
123.to_s.chars.map(&:to_i).reverse
, esto es bastante bueno.Como beneficio adicional, se necesita un argumento de raíz opcional:
Comparable#clamp
Hace lo que dice en la lata:
Como está en Comparable, puede usarlo con cualquier clase que incluya Comparable, por ejemplo:
String#unpack1
Un ahorro de 2 bytes sobre
.unpack(...)[0]
:Argumento de precisión para
Numeric#ceil
,floor
ytruncate
Asignación múltiple en condicionales
Esto genera un error en versiones anteriores de Ruby, pero está permitido en 2.4.
fuente
Math::E.ceil(1)
aMath::E.ceil 1
, y también parafloor
ytruncate
.Enumerable#sum
,.flatten.sum
es 2 bytes más corto que.sum{|a,b|a+b}
(-Math::E).truncate(1)
es equivalente a-Math::E.truncate(1)
que es 1 byte más corto&.
se puede usar con subíndice como estea&.[]i
(1 byte más corto quea&.at i
). Aunque, si se requieren paréntesis,a||a[i]
es 1 byte más corto quea&.[](i)
oa&.at(i)
La notación científica a menudo se puede usar para afeitarse un char o dos:
fuente
1e2
mejor es mejor que100.0
cuando se necesita un porcentaje.1.0*
es 1 char más corto que.to_f
Use métodos de operador en lugar de paréntesis
Digamos que quieres expresar
a*(b+c)
. Debido a la precedencia,a*b+c
no funcionará (obviamente). ¡La forma genial de Ruby de tener operadores como métodos viene al rescate! Puede usara.*b+c
para hacer que la precedencia sea*
menor que la de+
.Esto también puede funcionar con los operadores
!
y~
(cosas como unary+
o unary-
no funcionan porque sus métodos son-@
y+@
, guardando()
pero agregando.@
)fuente
Use en su
||
lugaror
y&&
en su lugarand
.Al lado del único personaje de
and
usted puede guardar los espacios (y quizás el corchete) alrededor del operador.Si realiza un bucle en una matriz que normalmente usa
each
. Peromap
también recorre una matriz y es un carácter más corto.fuente
Acabo de intentar un desafío de código de golf TDD, es decir, escribir el código más corto para hacer pasar las especificaciones. Las especificaciones eran algo así como
Por el bien del código-golf, uno no necesita crear un módulo o clase.
En lugar de
uno puede hacer
¡Salva a 13 personajes!
fuente
PigLatin
, sino también para@pig_latin
,$pig_latin
y'pig'['latin']
.translate
se ha definido ennil
.Kernel # p es un método divertido.
Usar en
p var
lugar deputs var
. Esto funciona perfectamente con enteros y flotantes, pero no con todos los tipos. Imprime comillas alrededor de las cadenas, lo que probablemente no sea lo que desea.Utilizado con un solo argumento,
p
devuelve el argumento después de imprimirlo.Utilizado con múltiples argumentos,
p
devuelve los argumentos en una matriz.Use
p
(sin argumentos) en lugar denil
.fuente
p 'some string'
imprime"some string"
y no solo losome string
que a menudo es criticado por otros.p s
es lo mismoputs s.inspect
, pero regresas
No uses #each. Puede recorrer todos los elementos perfectamente con #map. Entonces en lugar de
Puedes hacer lo mismo en menos bytes.
Por supuesto, en este caso
puts $*
sería aún más corto.Hay literales para números racionales y complejos:
Puede usar la mayoría de los bytes dentro de las cadenas.
"\x01"
(6 bytes) se puede acortar a""
(3 bytes). Si solo necesita este byte, puede acortarlo aún más?
(2 bytes).Del mismo modo, puede obtener nuevas líneas más cortas como esta:
Puede usar
?\n
y?\t
también, que es un byte más corto que"\n"
y"\t"
. Para la ofuscación, también hay? \ S, un espacio.Use constantes en lugar de pasar argumentos, incluso si necesita cambiarlos. El intérprete dará advertencias a stderr , pero a quién le importa. Si necesita definir más variables relacionadas entre sí, puede encadenarlas así:
Esto es más corto que
C=9;B=16;A=17
oC=0;B=C+7;A=C+B
.Si necesita un bucle infinito, use
loop{...}
. Los bucles de longitud desconocida pueden ser más cortos con otros bucles:Algunos trucos más gsub / regexp. Use los
'\1'
caracteres de escape especiales en lugar de un bloque:Y las variables especiales,
$1
etc., si necesita realizar operaciones. Tenga en cuenta que se definen no solo dentro del bloque:Deshágase de espacios, líneas nuevas y paréntesis. Puedes omitir bastante en ruby. En caso de duda, intente siempre si funciona sin él, y tenga en cuenta que esto podría romper el resaltado de sintaxis del editor ...
fuente
?\n
es agradable, pero no es realmente más corto que poner un carácter de nueva línea entre comillas. (lo mismo para la pestaña)puts$*
es aún más corto.x+=1;$*<<A
Otra forma más de utilizar el operador splat: si desea asignar un único literal de matriz, un
*
en el lado izquierdo es más corto que los corchetes en el lado derecho:Con múltiples valores, ni siquiera necesita el operador splat (gracias a histocrat por corregirme al respecto):
fuente
Cuando un desafío requiere que varias líneas de salida, que no tienen que bucle a través de sus resultados con el fin de imprimir cada línea de, por ejemplo una matriz. El
puts
método aplanará una matriz e imprimirá cada elemento en una línea separada.La combinación del operador splat con
#p
usted puede hacerlo aún más corto:El operador splat (técnicamente el
*@
método, creo) también lanza sus enumerables que no son matrices a las matrices:vs
fuente
*@
no es un método, splat es azúcar sintácticoGuarde algunos bytes al eliminar elementos repetidos de una matriz
Si va a utilizar una matriz vacía
[]
en una variable, puede guardar aún más bytes:fuente
a&a
es 1 byte más cortoUse Goruby en lugar de Ruby, que es algo así como una versión abreviada de Ruby. Puede instalarlo con rvm a través de
Goruby le permite escribir la mayor parte de su código como si estuviera escribiendo Ruby, pero tiene abreviaturas adicionales incorporadas. Para encontrar la abreviatura más corta disponible para algo, puede usar el método auxiliar
shortest_abbreviation
, por ejemplo:También es muy útil el alias
say
para elputs
cual se puede abreviars
. Entonces en lugar deahora puedes escribir
imprimir el alfabeto en mayúsculas (que no es un muy buen ejemplo). Esta publicación de blog explica más cosas y algunos de los funcionamientos internos si está interesado en leer más.
PD: no te pierdas el
h
método ;-)fuente
Para unir una matriz, en lugar de esto
hacer esto
que ahorra 2 bytes. Para unirse con un separador use
fuente
Números de suscripción!
Acabo de descubrir esto ayer.
n[i]
devuelven
el bit en lai
posición -th. Ejemplo:fuente
n[0..3]
Es posible que pueda guardar 2 caracteres y usar
en lugar de
Por ejemplo, supongamos que tenemos un rango que queremos como matriz:
Solo hazlo así:
Y ahora tienes tu rango como una matriz.
fuente
[*1..2000]
funciona?<< truco
se puede acortar a:
para -4 bytes.
fuente
String
sArray#assoc
/ /rassoc
Cuando tenga una matriz de matrices y desee encontrar la sub-matriz que comienza con un valor particular, no use
Enumerable#find
, useArray#assoc
:Este también es un buen reemplazo para
Enumerable#any?
en algunas situaciones.Array#rassoc
hace lo mismo, pero comprueba el último elemento de las submatrices:fuente
a.any?
línea delrassoc
ejemplo, ¿qué hace|x,|
? ¿Cómo es diferente de|x|
?x=[1,2]
vsx,=[1,2]
. Usando mi ejemplo anterior, con|x|
, en la primera iteraciónx
será[0,"foo"]
. Con|x,y|
,x
será0
yy
será"foo"
. Del mismo modo, con|x,|
,x
será0
. En otras palabras, dice "pon el primer elementox
y tira el resto."|,y|
es un SyntaxError, ergo|_,y|
. Pero ahora me he dado cuenta de que|*,y|
funciona, que es más limpio que usar una variable llamada_
(pero no más corta).