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.
Réponses:
?d
à?~
en 1.8.$><<"string"
est plus court queprint"string"
.$<.map{|l|...}
est plus courte quewhile l=gets;...;end
. Aussi, vous pouvez utiliser$<.read
pour lire tout cela à la fois.$<
etgets
sera lu à partir d' un fichier au lieu de stdin si le nom de fichier estARGV
. Ainsi , la façon de golfiest réimplémentezcat
serait:$><<$<.read
.la source
cat
consiste à 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-p
drapeau.puts *$<
☺
ou♫
, ou si vous êtes assez fou:?﷽.ord=65021
Utilisez l'opérateur splat pour obtenir la queue et la tête d'un tableau:
Cela fonctionne aussi dans l'autre sens:
Utilisez la
*
méthode avec une chaîne sur un tableau pour joindre des éléments:la source
abort
pour terminer le programme et imprimer une chaîne sur STDERR - plus courte queputs
suivie deexit
gets
, vous pouvez alors utiliser~/$/
pour trouver sa longueur (cela ne compte pas une fin de ligne s'il existe)[]
pour vérifier si une chaîne en contient une autre:'foo'['f'] #=> 'f'
tr
au lieu degsub
pour les substitutions par caractère:'01011'.tr('01','AB') #=> 'ABABB'
chop
plutôt quechomp
la source
abort
et~/$/
~/$/
gets
, son résultat est stocké dans la$_
variable./regex/ ~= string
renvoie 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= ~/$/
Terminez votre
end
.Essayez de supprimer
end
de votre code.Ne pas utiliser
def...end
pour 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.Les appels de méthode sont
c n
ouc(n)
. Les appels Lambda sontc[n]
. Changer chacunc n
enc[n]
coûtant 1 caractère, donc si vous pouvez utiliserc n
plus de 5 fois, gardez la méthode.Toutes les méthodes qui prennent des
do...end
blocs 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.Remplacez-le
if...else...end
par l' opérateur ternaire?:
. Si une branche a deux ou plusieurs instructions, placez-les entre parenthèses.Vous n'avez probablement
while
niuntil
boucles ni boucles, mais si c'est le cas, écrivez-les sous forme de modificateur.la source
puts'statement 3'
nécessaires?Ajout à w0lf
Combiné avec ce qui précède -> vous pouvez le rendre encore plus court
-[p]
en enregistrant 2 caractères supplémentaires.la source
Utilisez les variables prédéfinies courtes autant que possible, par exemple à la
$*
place deARGV
. Il y a une bonne liste d'entre eux ici , ainsi que beaucoup d'autres informations utiles.la source
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$_
,$&
,$1
etc:Donc aussi si vous avez besoin d’imprimer une variable plus que vous ne l’utilisez, vous pouvez économiser des octets.
la source
Si vous avez besoin de savoir si un élément particulier se
e
trouve dans une plager
, vous pouvez utiliserau lieu du plus long:
ou
ou
la source
r===e
encore plus court?===
implémenté.$_
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
Kernel
qui fonctionnent$_
:chop
chomp
sub
gsub
En Ruby 1.9, ces quatre méthodes n'existent que si votre script utilise
-n
ou-p
.Si vous voulez imprimer une variable souvent, utilisez
trace_var(:var_name){|a|p a}
la source
-p
ou-n
. Référence.trace_var
ne fonctionne qu'avec les variables $ globalesUtilisez l'interpolation de chaîne!
À remplacer
to_s
. Si vous avez besoin de parenthèses autour de ce que vous voulez transformer en chaîne, l'to_s
interpolation de la chaîne est de deux octets plus longue: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:
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):
la source
Éviter
length
dansif a.length<n
length
est 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 obtiendreznil
, une valeur de falsey.Pour que vous puissiez changer:
if a.length<5
toif !a[4]
pour -5 octetsou
if a.length>5
toif a[5]
pour -6 octetsou
if a.length<n
toif !a[n-1]
pour -3 octetsou
if a.length>n
toif a[n]
pour -6 octetsRemarque : fonctionnera uniquement avec un tableau de toutes les valeurs de vérité. avoir
nil
oufalse
dans le tableau peut causer des problèmes.la source
size
… Mais c'est vraiment mieux. BTW, travaille pourString
aussi.N'utilisez pas les mots clés
true
etfalse
.Utilisation:
!p
pourtrue
(merci, histocrate!)!0
pourfalse
. Si tout ce dont vous avez besoin est une valeur de fausseté, vous pouvez simplement utiliserp
(qui retournenil
).pour sauver des caractères.
la source
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!!
.p
(qui évalue ànil
) est une valeur de Falsey plus courte. Ce qui signifie que le moyen le plus court d’obtenirtrue
est!p
.Construisez des tableaux en utilisant
a=i,*a
pour les obtenir dans l'ordre inverse. Vous n'avez même pas besoin d'initialisera
, et si vous le faites, il ne doit pas nécessairement s'agir d'un tableau .la source
Si vous avez besoin d’obtenir un nombre de
ARGV
,get
ou 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 dex.to_i.times{}
vous sauvera 2 caractères.Vous pouvez également réécrire des choses comme
p 1 while 1
oup 1 if 1
commep 1while 1
oup 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,=c
enregistrez deux caractères au lieu dea=c[0]
la source
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,
nil
mais que vous souhaitez enchaîner des appels de méthode supplémentaires, vous perdez des octets qui gèrent lenil
cas:"L'opérateur de navigation sûr" arrête la chaîne d'appels de méthode si on retourne
nil
et retournenil
pour toute l'expression:Array#dig
EtHash#dig
Accès profond aux éléments imbriqués, avec un joli nom court:
Renvoie
nil
s'il frappe dans une impasse:Enumerable#grep_v
L'inverse de -
Enumerable#grep
renvoie tous les éléments qui ne correspondent pas à l'argument donné (par rapport à===
). Commegrep
si un bloc est donné, le résultat est retourné à la place.Hash#to_proc
Retourne un Proc qui donne la valeur de la clé donnée, ce qui peut être très pratique:
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 justearr.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:Integer#digits
Ceci retourne un tableau de chiffres d'un nombre dans l'ordre d'importance le moins élevé:
Par rapport à, disons,
123.to_s.chars.map(&:to_i).reverse
c'est plutôt sympa.En prime, il faut un argument optionnel radix:
Comparable#clamp
Fait ce qu'il dit sur la boîte:
Comme il est dans Comparable, vous pouvez l’utiliser avec n’importe quelle classe incluant Comparable, par exemple:
String#unpack1
Une économie de 2 octets sur
.unpack(...)[0]
:Argument de précision pour
Numeric#ceil
,floor
ettruncate
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.
la source
Math::E.ceil(1)
àMath::E.ceil 1
, et même pourfloor
ettruncate
.Enumerable#sum
,.flatten.sum
est-ce que 2 octets sont plus courts que.sum{|a,b|a+b}
(-Math::E).truncate(1)
est équivalent à-Math::E.truncate(1)
1 octet de moins&.
peut être utilisé avec un indice comme celui-cia&.[]i
(1 octet plus court quea&.at i
). Bien que, si des crochets sont requis,a||a[i]
1 octet est plus court quea&.[](i)
oua&.at(i)
La notation scientifique peut souvent être utilisée pour éliminer un ou deux caractères:
la source
1e2
mieux vaut mieux que100.0
lorsqu'un pourcentage est nécessaire.1.0*
est-il plus court que celui-ci.to_f
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+c
ne fonctionnera pas (évidemment). La façon cool de Ruby d'avoir des opérateurs comme méthodes vient à la rescousse! Vous pouvez utilisera.*b+c
pour rendre la précédence de*
inférieure à celle de+
.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.@
)la source
Utilisez à la
||
placeor
et à la&&
placeand
.À côté du caractère que
and
vous avez choisi, vous pouvez enregistrer les espaces (et peut-être le crochet) autour de l'opérateur.Si vous bouclez sur un tableau que vous utilisez normalement
each
. Mais lesmap
boucles aussi sur un tableau et c'est un caractère plus court.la source
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
Par souci de code-golf, il n'est pas nécessaire de créer un module ou une classe.
Au lieu de
on peut faire
Enregistre 13 caractères!
la source
PigLatin
, mais aussi@pig_latin
,$pig_latin
et'pig'['latin']
.translate
a été défini surnil
.Le noyau # p est une méthode amusante.
Utilisez
p var
au lieu deputs 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,
p
retourne l'argument après l'avoir imprimé.Utilisé avec plusieurs arguments,
p
retourne les arguments dans un tableau.Utilisez
p
(sans argument) au lieu denil
.la source
p 'some string'
impressions"some string"
et pas seulementsome string
qui est souvent critiqué par d'autres.p s
la même chose queputs s.inspect
, mais ça revients
N'utilisez pas #each. Vous pouvez très bien parcourir tous les éléments avec #map. Donc au lieu de
vous pouvez faire la même chose en moins d'octets.
Bien sûr, dans ce cas
puts $*
serait encore plus court.Il existe des littéraux pour les nombres rationnels et complexes:
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:
Vous pouvez utiliser
?\n
et?\t
aussi, 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:
C'est plus court que
C=9;B=16;A=17
ouC=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:Quelques autres astuces gsub / regexp. Utilisez les
'\1'
caractères d'échappement spéciaux au lieu d'un bloc:Et les variables spéciales,
$1
etc. si vous devez effectuer des opérations. Gardez à l'esprit qu'ils sont définis non seulement à l'intérieur du bloc: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 ...
la source
?\n
c’est bien, mais pas vraiment plus court que de mettre un caractère de nouvelle ligne entre guillemets. (idem pour tab)puts$*
est encore plus court.x+=1;$*<<A
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:Avec plusieurs valeurs, vous n'avez même pas besoin de l'opérateur splat (merci à histocrat de m'avoir corrigé):
la source
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
puts
méthode aplatira un tableau et imprimera chaque élément sur une ligne distincte.Combiner l'opérateur splat avec
#p
vous peut le rendre encore plus court:L'opérateur Splat (techniquement
*@
, je pense, la méthode) convertit également vos énumérables non-tableaux en tableaux:contre
la source
*@
n'est pas une méthode, splat est un sucre syntaxiqueSauvegarder quelques octets lors de la suppression d'éléments répétés d'un tableau
Si vous utilisez un tableau vide
[]
dans une variable, vous pouvez enregistrer encore plus d'octets:la source
a&a
1 octet de moinsUtilisez Goruby à la place de Ruby, qui ressemble à une version abrégée de Ruby. Vous pouvez l’installer avec rvm via
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:Le pseudonyme
say
pourputs
lequel lui-même peut être abrégé est également très pratiques
. Donc au lieu devous pouvez maintenant écrire
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
h
méthode ;-)la source
Pour rejoindre un tableau, au lieu de cela
fais ça
ce qui sauve 2 octets. Pour joindre avec un séparateur, utilisez
la source
Numéros souscripteurs!
Je viens de découvrir cela hier.
n[i]
retournen
le bit eni
-th. Exemple:la source
n[0..3]
Vous pourrez peut-être enregistrer 2 caractères et utiliser
au lieu de
Par exemple, supposons que nous ayons une plage que nous voulons comme tableau:
Fais-le comme ça:
Et maintenant vous avez votre gamme comme un tableau.
la source
[*1..2000]
marche aussi?<< astuce
peut être raccourci à:
pour -4 octets.
la source
String
sArray#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
, utilisezArray#assoc
: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:la source
a.any?
ligne dans l'rassoc
exemple|x,|
? En quoi est-ce différent|x|
?x=[1,2]
vsx,=[1,2]
. En utilisant mon exemple ci-dessus, avec|x|
, dans la première itérationx
sera[0,"foo"]
. Avec|x,y|
,x
sera0
ety
sera"foo"
. De même, avec|x,|
,x
sera0
. En d'autres termes, il est écrit "placez le premier élémentx
et jetez le reste."|,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).