Conseils pour jouer au Ruby

62

Quels conseils généraux pouvez-vous donner au golf en Ruby?

Je recherche des idées pouvant être appliquées aux problèmes de golf liés au code en général, qui sont spécifiques à Ruby. (Par exemple, "Supprimer les commentaires" ne constituerait pas une réponse.)

Merci de poster un pourboire par réponse.

grokus
la source
Quelqu'un a besoin d'écrire une langue appelée Rub, qui utilise un caractère Unicode unique pour chaque jeton Ruby, un peu comme Jelly et Pyth :)
Mark Thomas

Réponses:

46
  • Les numéros 100-126 peut être écrit comme ?dà ?~en 1.8.
  • Sur une note similaire, si vous avez besoin d’une chaîne à caractère unique dans 1.9? X est plus court que "x".
  • Si vous devez imprimer une chaîne sans ajouter de nouvelle ligne, $><<"string"est plus court que print"string".
  • Si vous avez besoin de lire plusieurs lignes d'entrée $<.map{|l|...}est plus courte que while l=gets;...;end. Aussi, vous pouvez utiliser $<.readpour lire tout cela à la fois.
  • Si vous êtes censé lire un fichier, $<et getssera lu à partir d' un fichier au lieu de stdin si le nom de fichier est ARGV. Ainsi , la façon de golfiest réimplémentez catserait: $><<$<.read.
sepp2k
la source
1
? x donne le code ascii en général, vous pouvez donc obtenir tous les éléments imprimables en chiffres de deux caractères. 1.9 est différent, 'a'.ord renvoie le nombre ascii, mais est quatre octets plus long que la version décimale.
Hiato
8
Une méthode encore plus simple à mettre en œuvre catconsiste à laisser le fichier ruby ​​complètement vide (0 octet) et à insister pour qu'il soit exécuté à partir de la ligne de commande avec le -pdrapeau.
daniero
1
ou, de la propre réponse de @ daniero ,puts *$<
Pas que Charles
1
Donc en 1.8, tout ce que je dois faire est de partir? ~ Et il retournera 126?
Simply Beautiful Art,
5
Vous pouvez aller au-delà de 126 en utilisant think ou , ou si vous êtes assez fou:?﷽.ord=65021
Simply Beautiful Art
32

Utilisez l'opérateur splat pour obtenir la queue et la tête d'un tableau:

head, *tail = [1,2,3]
head => 1
tail => [2,3]

Cela fonctionne aussi dans l'autre sens:

*head, tail = [1,2,3]
head => [1,2]
tail => 3

Utilisez la *méthode avec une chaîne sur un tableau pour joindre des éléments:

[1,2,3]*?,
=> "1,2,3"
Arnaud Le Blanc
la source
27
  • Utilisez abortpour terminer le programme et imprimer une chaîne sur STDERR - plus courte que putssuivie deexit
  • Si vous lisez une ligne avec gets, vous pouvez alors utiliser ~/$/pour trouver sa longueur (cela ne compte pas une fin de ligne s'il existe)
  • Utilisez []pour vérifier si une chaîne en contient une autre:'foo'['f'] #=> 'f'
  • Utilisez trau lieu de gsubpour les substitutions par caractère:'01011'.tr('01','AB') #=> 'ABABB'
  • Si vous devez supprimer les retours à la ligne, utilisez chopplutôt quechomp
Lowjacker
la source
2
+1 pour abortet~/$/
J -_- L
S'il vous plaît expliquer comment utiliser~/$/
Mathieu CAROFF
@MathieuCAROFF chaque fois que vous appelez gets, son résultat est stocké dans la $_variable. /regex/ ~= stringrenvoie l'index de la première correspondance. Appeler ~sur une expression régulière est équivalent à /regex/ ~= $_. Donc, ce serait quelque chose commes=gets;l= ~/$/
Cyoce
20

Terminez votre end.

Essayez de supprimer endde votre code.

Ne pas utiliser def...endpour définir des fonctions. Créez un lambda avec le nouvel opérateur -> de Ruby 1.9. (L'opérateur -> est un "stabby lambda" ou une "roquette" .) Ceci enregistre 5 caractères par fonction.

# 28 characters
def c n
/(\d)\1/=~n.to_s
end

# 23 characters, saves 5
c=->n{/(\d)\1/=~n.to_s}

Les appels de méthode sont c nou c(n). Les appels Lambda sont c[n]. Changer chacun c nen c[n]coûtant 1 caractère, donc si vous pouvez utiliser c nplus de 5 fois, gardez la méthode.

Toutes les méthodes qui prennent des do...endblocs peuvent prendre des {...}blocs à la place. Cela enregistre 3 à 5 caractères. Si la priorité de {...}est trop élevée, utilisez des parenthèses pour la résoudre.

# 48 characters
(?a..?m).zip (1..5).cycle do|a|puts a.join','end

# WRONG: passes block to cycle, not zip
(?a..?m).zip (1..5).cycle{|a|puts a.join','}

# 45 characters, saves 3
(?a..?m).zip((1..5).cycle){|a|puts a.join','}

Remplacez-le if...else...endpar l' opérateur ternaire ?: . Si une branche a deux ou plusieurs instructions, placez-les entre parenthèses.

# 67 characters
if a<b
puts'statement 1'
puts'statement 2'else
puts'statement 3'end

# 62 characters, saves 5
a<b ?(puts'statement 1'
puts'statement 2'):(puts'statement 3')

Vous n'avez probablement whileni untilboucles ni boucles, mais si c'est le cas, écrivez-les sous forme de modificateur.

(a+=1
b-=1)while a<b
Kernigh
la source
Les parenthèses sont-elles puts'statement 3'nécessaires?
Cyoce
15

Ajout à w0lf

Lorsque vous travaillez avec des tableaux, vous .compactpouvez les remplacer par -[nil]pour enregistrer 2 caractères.

Combiné avec ce qui précède -> vous pouvez le rendre encore plus court -[p]en enregistrant 2 caractères supplémentaires.

villu164
la source
14

Utilisez les variables prédéfinies courtes autant que possible, par exemple à la $*place de ARGV. Il y a une bonne liste d'entre eux ici , ainsi que beaucoup d'autres informations utiles.

Nemo157
la source
12

Lorsque vous utilisez une interpolation de chaîne (comme vous devriez le post du pr. Martin Büttner ), vous n'avez pas besoin des accolades si votre objet est précédé d'un sigil ( $, @). Utile pour les variables magiques comme $_, $&, $1etc:

puts "this program has read #$. lines of input"

Donc aussi si vous avez besoin d’imprimer une variable plus que vous ne l’utilisez, vous pouvez économiser des octets.

a=42; puts "here is a: #{a}"; puts "here is a again: #{a}"
$b=43; puts "here is b: #$b"; puts "here is b again: #$b"
Daniero
la source
11

Si vous avez besoin de savoir si un élément particulier se etrouve dans une plage r, vous pouvez utiliser

r===e

au lieu du plus long:

r.cover?(e) # only works if `r.exclude_end?` is false

ou

r.member?(e)

ou

r.include?(e)
Cristian Lupascu
la source
3
N'est-ce pas r===eencore plus court?
akuhn
@akuhn Oui, c'est ça. Plus court. Merci de me l'avoir signalé, cela m'a aidé à raccourcir mon code de 10 caractères, ce qui est énorme: codegolf.stackexchange.com/a/6125/3527
Cristian Lupascu
1
Je vous en prie. Tout ce qui peut être utilisé dans une instruction switch a été ===implémenté.
Akuhn le
10

$_ est la dernière ligne lue.

  • print - si aucun argument n'est donné, imprimer le contenu de $_
  • ~/regexp/ - court pour $_=~/regexp/

Dans Ruby 1.8, vous avez quatre méthodes Kernelqui fonctionnent $_:

  • chop
  • chomp
  • sub
  • gsub

En Ruby 1.9, ces quatre méthodes n'existent que si votre script utilise -nou -p.

Si vous voulez imprimer une variable souvent, utilisez trace_var(:var_name){|a|p a}

Hauleth
la source
2
Celles-ci ne sont disponibles que lorsque vous exécutez Ruby avec l' option -pou -n. Référence.
Darren Stone
1
Il semble que trace_varne fonctionne qu'avec les variables $ globales
daniero
10

Utilisez l'interpolation de chaîne!

  1. À remplacer to_s. Si vous avez besoin de parenthèses autour de ce que vous voulez transformer en chaîne, l' to_sinterpolation de la chaîne est de deux octets plus longue:

    (n+10**i).to_s
    "#{n+10**i}"
    
  2. Pour remplacer la concaténation. Si vous concaténez quelque chose entouré de deux autres chaînes, l'interpolation peut vous faire économiser un octet:

    "foo"+c+"bar"
    "foo#{c}bar"
    

    Cela fonctionne aussi si le milieu est lui-même concaténé, si vous déplacez simplement la concaténation à l'intérieur de l'interpolation (au lieu d'utiliser plusieurs interpolations):

    "foo"+c+d+e+"bar"
    "foo#{c+d+e}bar"
    
Martin Ender
la source
10

Éviter lengthdansif a.length<n

lengthest de 6 octets, un peu coûteux en code golf. dans de nombreuses situations, vous pouvez plutôt vérifier si le tableau a quelque chose à un moment donné. si vous dépassez le dernier indice que vous obtiendrez nil, une valeur de falsey.

Pour que vous puissiez changer:

if a.length<5to if !a[4]pour -5 octets

ou

if a.length>5to if a[5]pour -6 octets

ou

if a.length<nto if !a[n-1]pour -3 octets

ou

if a.length>nto if a[n]pour -6 octets

Remarque : fonctionnera uniquement avec un tableau de toutes les valeurs de vérité. avoir nilou falsedans le tableau peut causer des problèmes.

MegaTom
la source
4
J'utilise toujours size… Mais c'est vraiment mieux. BTW, travaille pour Stringaussi.
Manatwork
10

N'utilisez pas les mots clés trueet false.

Utilisation:

  • !ppour true(merci, histocrate!)
  • !0pour false. Si tout ce dont vous avez besoin est une valeur de fausseté, vous pouvez simplement utiliser p(qui retourne nil).

pour sauver des caractères.

Cristian Lupascu
la source
1
Sauf si vous en avez réellement besoin true(c'est-à-dire si une valeur de vérité est suffisante, comme dans un état si), vous n'en avez même pas besoin !!.
Martin Ender
4
Et de même, p(qui évalue à nil) est une valeur de Falsey plus courte. Ce qui signifie que le moyen le plus court d’obtenir trueest !p.
histocrat
@histocrate bon point! J'ai édité ma réponse.
Cristian Lupascu
9

Si vous avez besoin d’obtenir un nombre de ARGV, getou quelque chose de similaire, pour faire quelque chose qui ne soit pas appelé to_i, vous pouvez simplement utiliser ?1.upto x{do something x times}où x est une chaîne.

Donc, utiliser ?1.upto(a){}au lieu de x.to_i.times{}vous sauvera 2 caractères.

Vous pouvez également réécrire des choses comme p 1 while 1ou p 1 if 1comme p 1while 1oup 1if 1

Cet exemple n'est pas très utile, mais il pourrait être utilisé pour autre chose.

De même, si vous devez affecter le premier élément d’un tableau à une variable, vous a,=cenregistrez deux caractères au lieu dea=c[0]

addison
la source
9

Nouvelles fonctionnalités de Ruby 2.3 et 2.4

Il est bon de rester au courant des nouvelles fonctionnalités linguistiques qui aideront votre jeu de golf. Il y a quelques grands dans les derniers rubis.

Ruby 2.3

L'opérateur de navigation sécurisé: &.

Lorsque vous appelez une méthode susceptible de renvoyer, nilmais que vous souhaitez enchaîner des appels de méthode supplémentaires, vous perdez des octets qui gèrent le nilcas:

arr = ["zero", "one", "two"]
x = arr[5].size
# => NoMethodError: undefined method `size' for nil:NilClass

x = arr[5].size rescue 0
# => 0

"L'opérateur de navigation sûr" arrête la chaîne d'appels de méthode si on retourne nilet retourne nilpour toute l'expression:

x = arr[5]&.size || 0
# => 0

Array#dig Et Hash#dig

Accès profond aux éléments imbriqués, avec un joli nom court:

o = { foo: [{ bar: ["baz", "qux"] }] }
o.dig(:foo, 0, :bar, 1) # => "qux"

Renvoie nils'il frappe dans une impasse:

o.dig(:foo, 99, :bar, 1) # => nil

Enumerable#grep_v

L'inverse de - Enumerable#greprenvoie tous les éléments qui ne correspondent pas à l'argument donné (par rapport à ===). Comme grepsi un bloc est donné, le résultat est retourné à la place.

(1..10).grep_v 2..5 # => [1, 6, 7, 8, 9, 10]
(1..10).grep_v(2..5){|v|v*2} # => [2, 12, 14, 16, 18, 20]

Hash#to_proc

Retourne un Proc qui donne la valeur de la clé donnée, ce qui peut être très pratique:

h = { N: 0, E: 1, S: 2, W: 3 }
%i[N N E S E S W].map(&h)
# => [0, 0, 1, 2, 1, 2, 3]

Ruby 2.4

Ruby 2.4 n'est pas encore sorti, mais il le sera bientôt et a quelques fonctionnalités intéressantes. (Quand il sera publié, je mettrai à jour ce billet avec quelques liens vers la documentation.) J'ai découvert la plupart de ces informations dans ce blog .

Enumerable#sum

Pas plus arr.reduce(:+). Vous pouvez maintenant faire juste arr.sum. Il prend un argument optionnel de valeur initiale, dont la valeur par défaut est 0 pour Numeric elements ( [].sum == 0). Pour les autres types, vous devez fournir une valeur initiale. Il accepte également un bloc qui sera appliqué à chaque élément avant addition:

[[1, 10], [2, 20], [3, 30]].sum {|a,b| a + b }
# => 66

Integer#digits

Ceci retourne un tableau de chiffres d'un nombre dans l'ordre d'importance le moins élevé:

123.digits # => [3, 2, 1]

Par rapport à, disons, 123.to_s.chars.map(&:to_i).reversec'est plutôt sympa.

En prime, il faut un argument optionnel radix:

a = 0x7b.digits(16) # => [11, 7]
a.map{|d|"%x"%d} # => ["b", "7"]

Comparable#clamp

Fait ce qu'il dit sur la boîte:

v = 15
v.clamp(10, 20) # => 15
v.clamp(0, 10) # => 10
v.clamp(20, 30) # => 20

Comme il est dans Comparable, vous pouvez l’utiliser avec n’importe quelle classe incluant Comparable, par exemple:

?~.clamp(?A, ?Z) # => "Z"

String#unpack1

Une économie de 2 octets sur .unpack(...)[0]:

"👻💩".unpack(?U)    # => [128123]
"👻💩".unpack(?U)[0] # => 128123
"👻💩".unpack1(?U)   # => 128123

Argument de précision pour Numeric#ceil, floorettruncate

Math::E.ceil(1) # => 2.8
Math::E.floor(1) # => 2.7
(-Math::E).truncate(1) # => -2.7

Affectation multiple dans les conditions

Cela soulève une erreur dans les versions précédentes de Ruby, mais est autorisé dans la version 2.4.

(a,b=1,2) ? "yes" : "no" # => "yes"
(a,b=nil) ? "yes" : "no" # => "no"
Jordan
la source
Golf Math::E.ceil(1)à Math::E.ceil 1, et même pour flooret truncate.
Simply Beautiful Art
1
@SimplyBeautifulArt Je m'attends à ce que quelqu'un jouant au golf à Ruby puisse faire ce saut lui-même.
Jordanie
Pour Enumerable#sum, .flatten.sumest-ce que 2 octets sont plus courts que.sum{|a,b|a+b}
Asone Tuhid le
(-Math::E).truncate(1)est équivalent à -Math::E.truncate(1)1 octet de moins
Asone Tuhid
1
&.peut être utilisé avec un indice comme celui-ci a&.[]i(1 octet plus court que a&.at i). Bien que, si des crochets sont requis, a||a[i]1 octet est plus court que a&.[](i)oua&.at(i)
Asone Tuhid
7

La notation scientifique peut souvent être utilisée pour éliminer un ou deux caractères:

x=1000
#versus
x=1e3
lâche anonyme
la source
9
Remarque: Ceci renverra une valeur Float (1000.0) au lieu d'un Integer, ce qui peut entraîner des résultats inexacts avec des nombres élevés.
Dogbert
4
Ah, 1e2mieux vaut mieux que 100.0lorsqu'un pourcentage est nécessaire.
Phrogz
Semblable à ce principe, un caractère 1.0*est-il plus court que celui-ci.to_f
Unihedron
7

Utiliser des méthodes d'opérateur au lieu de parenthèses

Disons que vous voulez exprimer a*(b+c). En raison de la priorité, a*b+cne fonctionnera pas (évidemment). La façon cool de Ruby d'avoir des opérateurs comme méthodes vient à la rescousse! Vous pouvez utiliser a.*b+cpour rendre la précédence de *inférieure à celle de +.

a*(b+c) # too long
a*b+c   # wrong
a.*b+c  # 1 byte saved!

Cela peut également fonctionner avec les opérateurs !et ~(les choses comme unary +ou unary -ne fonctionnent pas parce que leurs méthodes sont -@et +@, en enregistrant ()mais en ajoutant .@)

(~x).to_s # too long
~x.to_s   # error
x.~.to_s  # 1 byte saved!
Cyoce
la source
6

Utilisez à la ||place oret à la &&place and.

À côté du caractère que andvous avez choisi, vous pouvez enregistrer les espaces (et peut-être le crochet) autour de l'opérateur.

p true and false ? 'yes' :'no'   #-> true (wrong result)
p (true and false) ? 'yes' :'no' #-> 'no'
p true&&false ? 'yes' :'no'      #-> 'no', saved 5 characters


p true or false ? 'yes' :'no'   #-> true (wrong result)
p (true or false) ? 'yes' :'no' #-> 'yes'
p true||false ? 'yes' :'no'      #-> 'yes', saved 4 characters

Si vous bouclez sur un tableau que vous utilisez normalement each. Mais les mapboucles aussi sur un tableau et c'est un caractère plus court.

noué
la source
6

Je viens de tenter un défi code-golf TDD, c'est-à-dire écrire le code le plus court pour faire passer les spécifications. Les spécifications étaient quelque chose comme

describe PigLatin do
  describe '.translate' do
    it 'translates "cat" to "atcay"' do
      expect(PigLatin.translate('cat')).to eq('atcay')
    end
    # And similar examples for .translate
  end
end

Par souci de code-golf, il n'est pas nécessaire de créer un module ou une classe.

Au lieu de

module PigLatin def self.translate s;'some code'end;end

on peut faire

def(PigLatin=p).translate s;'some code'end

Enregistre 13 caractères!

S Shah
la source
7
Ha, très complet. Non seulement avez - vous ajouté le comportement nécessaire PigLatin, mais aussi @pig_latin, $pig_latinet 'pig'['latin'].
Histocrat
@histocrat: Maintenant je comprends. C'est parce que translatea été défini sur nil.
Eric Duminil
6

Le noyau # p est une méthode amusante.

Utilisez p varau lieu de puts var. Cela fonctionne parfaitement avec les entiers et les flottants, mais pas avec tous les types. Il imprime des guillemets autour des chaînes, ce qui n’est probablement pas ce que vous voulez.

Utilisé avec un seul argument, pretourne l'argument après l'avoir imprimé.

Utilisé avec plusieurs arguments, pretourne les arguments dans un tableau.

Utilisez p(sans argument) au lieu de nil.

Fábio Perez
la source
10
Malheureusement, les p 'some string'impressions "some string"et pas seulement some stringqui est souvent critiqué par d'autres.
Patrick Oscity
1
C'est fondamentalement p sla même chose que puts s.inspect, mais ça revients
Cyoce
6

N'utilisez pas #each. Vous pouvez très bien parcourir tous les éléments avec #map. Donc au lieu de

ARGV.each{|x|puts x}

vous pouvez faire la même chose en moins d'octets.

ARGV.map{|x|puts x}

Bien sûr, dans ce cas puts $*serait encore plus court.


Il existe des littéraux pour les nombres rationnels et complexes:

puts 3/11r == Rational(3,11)
puts 3.3r == Rational(66,20)
puts 1-1.i == Complex(1,-1)

=> true
true
true

Vous pouvez utiliser la plupart des octets dans les chaînes. "\x01"(6 octets) peut être raccourci à ""(3 octets). Si vous n'avez besoin que de cet octet, vous pouvez le réduire encore ?(2 octets).

De même, vous pouvez raccourcir les nouvelles lignes comme ceci:

(0..10).to_a.join'
'

 => "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10"

Vous pouvez utiliser ?\net ?\taussi, qui est un octet plus court que "\n"et "\t". Pour l’obscurcissement, il y a aussi un espace.


Utilisez des constantes au lieu de passer des arguments, même si vous devez les changer. L'interprète donnera des avertissements à stderr , mais peu importe. Si vous devez définir plusieurs variables liées les unes aux autres, vous pouvez les chaîner comme suit:

A=C+B=7+C=9

=> A=17, B=16, C=9

C'est plus court que C=9;B=16;A=17ou C=0;B=C+7;A=C+B.


Si vous avez besoin d’une boucle infinie, utilisez loop{...}. Les boucles de longueur inconnue peuvent être plus courtes avec d'autres boucles:

loop{break if'
'==f(gets)}

while'
'!=f(gets);end

Quelques autres astuces gsub / regexp. Utilisez les '\1'caractères d'échappement spéciaux au lieu d'un bloc:

"golf=great short=awesome".gsub(/(\w+)=(\w+)/,'(\1~>\2)')

"golf=great short=awesome".gsub(/(\w+)=(\w+)/){"(#{$1}~>#{$2})")

Et les variables spéciales, $1etc. si vous devez effectuer des opérations. Gardez à l'esprit qu'ils sont définis non seulement à l'intérieur du bloc:

"A code-golf challenge." =~ /(\w+)-(\w+)/
p [$1,$2,$`,$']

=> ["code", "golf", "A ", " challenge."] 

Débarrassez-vous des espaces, des nouvelles lignes et des parenthèses. Vous pouvez omettre un peu de rubis. En cas de doute, essayez toujours si cela fonctionne sans, et gardez à l'esprit que cela pourrait empêcher la surbrillance de la syntaxe de l'éditeur ...

x+=1if$*<<A==????::??==??
blutorange
la source
"S'il vous plaît poster un pourboire par réponse." Aussi, ?\nc’est bien, mais pas vraiment plus court que de mettre un caractère de nouvelle ligne entre guillemets. (idem pour tab)
Martin Ender
Et puts$*est encore plus court.
Cyoce
Je sais que vous avez essayé de prouver un point, mais je suis à peu près sûr que le dernier exemple est le même quex+=1;$*<<A
Asone Tuhid
6

Encore une autre façon d’utiliser l’opérateur splat: si vous souhaitez affecter un seul littéral de tableau, *le côté gauche est plus court que les parenthèses du côté droit:

a=[0]
*a=0

Avec plusieurs valeurs, vous n'avez même pas besoin de l'opérateur splat (merci à histocrat de m'avoir corrigé):

a=[1,2]
a=1,2
Martin Ender
la source
Ce dernier cas n'a pas réellement besoin du splat.
histocrat
@histocrat Oh wow, je pensais que la deuxième valeur serait simplement rejetée dans ce cas.
Martin Ender
1
Je ne peux pas croire que je ne les connais pas depuis tout ce temps que j'ai passé à jouer au golf à Ruby.
Poignée de porte
6

Quand un défi , il faut que vous afficher plusieurs lignes, vous n'avez pas à boucle à travers vos résultats afin d'imprimer chaque ligne, par exemple , un tableau. La putsméthode aplatira un tableau et imprimera chaque élément sur une ligne distincte.

> a = %w(testing one two three)
> puts a
testing
one
two
three

Combiner l'opérateur splat avec #pvous peut le rendre encore plus court:

p *a

L'opérateur Splat (techniquement *@, je pense, la méthode) convertit également vos énumérables non-tableaux en tableaux:

> p a.lazy.map{|x|x*2}
#<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:map>

contre

> p *a.lazy.map{|x|x*2}
2
4
6
Daniero
la source
1
*@n'est pas une méthode, splat est un sucre syntaxique
Asone Tuhid
6

Sauvegarder quelques octets lors de la suppression d'éléments répétés d'un tableau

a.uniq # before
a|[]   # after
    ^^

Si vous utilisez un tableau vide []dans une variable, vous pouvez enregistrer encore plus d'octets:

a.uniq;b=[] # before
a|b=[]      # after
      ^^^^^
Cyoce
la source
2
Pour le premier cas, a&a1 octet de moins
Asone Tuhid
5

Utilisez Goruby à la place de Ruby, qui ressemble à une version abrégée de Ruby. Vous pouvez l’installer avec rvm via

rvm install goruby

Goruby vous permet d'écrire l'essentiel de votre code comme vous écriviez Ruby, mais a des abréviations supplémentaires intégrées. Pour trouver l'abréviation disponible la plus courte, vous pouvez utiliser la méthode d'assistance shortest_abbreviation, par exemple:

shortest_abbreviation :puts
#=> "pts"

Array.new.shortest_abbreviation :map
#=> "m"

String.new.shortest_abbreviation :capitalize
#=> "cp"

Array.new.shortest_abbreviation :join
#=> "j"

Le pseudonyme saypour putslequel lui-même peut être abrégé est également très pratique s. Donc au lieu de

puts [*?a..?z].map(&:capitalize).join

vous pouvez maintenant écrire

s [*?a..?z].m(&:cp).j

imprimer l’alphabet en majuscules (ce qui n’est pas un très bon exemple). Ce billet de blog explique plus de choses et certains rouages ​​si vous souhaitez en savoir plus.

PS: ne manquez pas la hméthode ;-)

Patrick Oscity
la source
Plus de 2 ans plus tard, j'ai enfin compris ce que cette réponse me rappelait ...
undergroundmonorail
5

Pour rejoindre un tableau, au lieu de cela

[...].join

fais ça

[...]*''

ce qui sauve 2 octets. Pour joindre avec un séparateur, utilisez

[...]*?,
Markus
la source
5

Numéros souscripteurs!

Je viens de découvrir cela hier. n[i]retourne nle bit en i-th. Exemple:

irb(main):001:0> n = 0b11010010
=> 210
irb(main):002:0> n[0]
=> 0
irb(main):003:0> n[1]
=> 1
irb(main):004:0> n[2]
=> 0
irb(main):005:0> n[3]
=> 0
irb(main):006:0> n[4]
=> 1
irb(main):007:0> n[5]
=> 0
Cyoce
la source
Et maintenant, vous pouvez utiliser plus d'arguments tels quen[0..3]
Simply Beautiful Art
4

Vous pourrez peut-être enregistrer 2 caractères et utiliser

[*(...)]

au lieu de

(...).to_a

Par exemple, supposons que nous ayons une plage que nous voulons comme tableau:

(1..2000).to_a

Fais-le comme ça:

[*1..2000]  #  Parentheses around the (ran..ge) is not needed!

Et maintenant vous avez votre gamme comme un tableau.

Justin
la source
5
Je pense que ça [*1..2000]marche aussi?
Lynn
4

<< astuce

a.push x

peut être raccourci à:

a<<x

pour -4 octets.

MegaTom
la source
2
Remarque: cela fonctionne également pour Strings
Cyoce
4

Array#assoc/rassoc

Lorsque vous avez un tableau de tableaux et que vous voulez trouver le sous-tableau qui commence par une valeur particulière, n'utilisez pas Enumerable#find, utilisez Array#assoc:

a = [[0,"foo"],[0,"bar"],[1,"baz"],[0,"qux"]]
a.find{|x,|x==1} # => [1,"baz"]
a.assoc(1) # => [1,"baz"]

C'est également un bon remplacement Enumerable#any?dans certaines situations.

Array#rassoc fait la même chose, mais vérifie le dernier élément des sous-tableaux:

a = [[123,"good"],[456,"good"]]
a.any?{|*,x|x=="bad"} # => false
a.rassoc("bad") # => nil
Jordan
la source
Que fait la a.any?ligne dans l' rassoc exemple |x,|? En quoi est-ce différent |x|?
Cyoce
@Cyoce paramètre bloc destructuration suit les mêmes règles que l' affectation déstructurant, il est donc comme x=[1,2]vs x,=[1,2]. En utilisant mon exemple ci-dessus, avec |x|, dans la première itération xsera [0,"foo"]. Avec |x,y|, xsera 0et ysera "foo". De même, avec |x,|, xsera 0. En d'autres termes, il est écrit "placez le premier élément xet jetez le reste."
Jordanie
Notez que cela ne fonctionne pas en sens inverse, par exemple, il |,y|s'agit d'une syntaxe, une erreur |_,y|. Mais je viens de me rendre compte que cela |*,y|fonctionne, ce qui est plus propre que d'utiliser une variable nommée _(mais pas plus courte).
Jordanie