Welche allgemeinen Tipps können Sie zum Golfen in Ruby geben?
Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme im Allgemeinen anwenden lassen, die speziell für Ruby gelten. (Zum Beispiel wäre "Kommentare entfernen" keine Antwort.)
Bitte posten Sie einen Tipp pro Antwort.
Antworten:
?d
um?~
in 1.8.$><<"string"
ist sie kürzer alsprint"string"
.$<.map{|l|...}
ist dies kürzer alswhile l=gets;...;end
. Sie können auch verwenden$<.read
, um alles auf einmal zu lesen.$<
undgets
statt stdin aus einer Datei lesen, wenn der Dateiname in istARGV
. So ist die golfiest Weise neu zu implementierencat
wäre:$><<$<.read
.quelle
cat
besteht darin, die Ruby-Datei vollständig leer zu lassen (0 Byte) und darauf zu bestehen, dass sie über die Befehlszeile mit dem-p
Flag ausgeführt wird.puts *$<
☺
oder♫
, oder wenn Sie verrückt genug sind:?﷽.ord=65021
Verwenden Sie den splat-Operator, um den Schwanz und den Kopf eines Arrays zu erhalten:
Das funktioniert auch andersherum:
Verwenden Sie die
*
Methode mit einer Zeichenfolge in einem Array, um Elemente zu verbinden:quelle
abort
das Programm und gibt einen String an STDERR aus - kürzer alsputs
gefolgt vonexit
gets
, können Sie~/$/
ihre Länge ermitteln (dies zählt keine nachgestellte neue Zeile, falls vorhanden).[]
diese Option , um zu überprüfen, ob eine Zeichenfolge eine andere enthält:'foo'['f'] #=> 'f'
tr
anstelle vongsub
für zeichenweise Ersetzungen:'01011'.tr('01','AB') #=> 'ABABB'
chop
anstelle vonchomp
quelle
abort
und~/$/
~/$/
gets
wird das Ergebnis in der$_
Variablen gespeichert ./regex/ ~= string
Gibt den Index der ersten Übereinstimmung zurück. Das Aufrufen~
eines regulären Ausdrucks entspricht/regex/ ~= $_
. Also wäre es so etwas wies=gets;l= ~/$/
Beende deine
end
.Versuchen Sie,
end
aus Ihrem Code zu entfernen .Verwenden Sie nicht
def...end
, um Funktionen zu definieren. Machen Sie ein Lambda mit dem new -> Operator in Ruby 1.9. (Der Operator -> ist eine "Stabby-Lambda" - oder "Dash-Rakete" .) Dadurch werden 5 Zeichen pro Funktion gespeichert .Methodenaufrufe sind
c n
oderc(n)
. Lambda ruft anc[n]
. Ändern jederc n
aufc[n]
Kosten 1 Zeichen, so dass , wenn Sie verwenden können ,c n
mehr als 5 - mal, dann die Methode halten.Alle Methoden, die
do...end
Blöcke annehmen , können{...}
stattdessen Blöcke annehmen . Das spart 3 bis 5 Zeichen. Wenn die Priorität von{...}
zu hoch ist, verwenden Sie Klammern, um sie zu beheben.Ersetzen Sie
if...else...end
durch den ternären Operator?:
. Wenn ein Zweig zwei oder mehr Anweisungen enthält, setzen Sie sie in Klammern.Sie haben wahrscheinlich keine
while
oderuntil
Schleifen, aber wenn Sie dies tun, schreiben Sie sie in Modifikatorform.quelle
puts'statement 3'
notwendig?Zusatz zu w0lf
Kombiniert mit oben -> können Sie es mit noch kürzer machen
-[p]
, um weitere 2 Zeichen zu sparen.quelle
Verwenden Sie nach Möglichkeit die kurzen vordefinierten Variablen, z . B.
$*
anstelle vonARGV
. Es gibt eine gute Liste von ihnen hier , zusammen mit vielen anderen nützlichen Informationen.quelle
Wenn Sie die Zeichenfolgeninterpolation verwenden (wie Sie es bei Martin Büttners Beitrag tun sollten ), brauchen Sie die geschweiften Klammern nicht, wenn Ihr Objekt ein Siegel (
$
,@
) vor sich hat. Nützlich für magische Variablen wie$_
,$&
,$1
etc:Wenn Sie also eine Variable häufiger drucken müssen als sonst, können Sie einige Bytes sparen.
quelle
Wenn Sie feststellen müssen, ob sich ein bestimmtes Element
e
in einem Bereich befindetr
, können Sie verwendenstatt der längeren:
oder
oder
quelle
r===e
noch kürzer?===
implementiert.$_
ist die zuletzt gelesene Zeile.print
- wenn kein Argument für den Druckinhalt von$_
~/regexp/
- kurz für$_=~/regexp/
In Ruby 1.8 stehen Ihnen vier Methoden zur Verfügung
Kernel
, mit denen Sie arbeiten können$_
:chop
chomp
sub
gsub
In Ruby 1.9 gibt es diese vier Methoden nur, wenn Ihr Skript
-n
oder verwendet-p
.Wenn Sie eine Variable häufig drucken möchten, verwenden Sie
trace_var(:var_name){|a|p a}
quelle
-p
oder ausführen-n
. Referenz.trace_var
nur mit globalen $Verwenden Sie die String-Interpolation!
Zu ersetzen
to_s
. Wenn Sie Klammern benötigen, um eine Zeichenfolge zu erstellen,to_s
sind diese zwei Byte länger als die Zeichenfolgeninterpolation:Verkettung ersetzen. Wenn Sie etwas verketten, das von zwei anderen Zeichenfolgen umgeben ist, können Sie durch Interpolation ein Byte sparen:
Funktioniert auch, wenn das Mittelteil selbst verkettet ist, wenn Sie die Verkettung nur innerhalb der Interpolation verschieben (anstatt mehrere Interpolationen zu verwenden):
quelle
Vermeiden Sie
length
inif a.length<n
length
ist 6 Bytes, ein bisschen teuer in Code Golf. In vielen Situationen können Sie stattdessen überprüfen, ob das Array an einem bestimmten Punkt etwas enthält. Wenn Sie über den letzten Indexnil
hinausgreifen, erhalten Sie einen falschen Wert.So können Sie Folgendes ändern:
if a.length<5
bisif !a[4]
für -5 Bytesoder
if a.length>5
bisif a[5]
für -6 Bytesoder
if a.length<n
bisif !a[n-1]
für -3 Bytesoder
if a.length>n
bisif a[n]
für -6 BytesHinweis : Funktioniert nur mit einem Array aller Wahrheitswerte. Das Vorhandensein
nil
oderfalse
das Einfügen in das Array kann zu Problemen führen.quelle
size
... Aber das ist definitiv besser. BTW, funktioniertString
auch.Verwenden Sie nicht die Schlüsselwörter
true
undfalse
.Verwenden:
!p
fürtrue
(danke, Histokrat!)!0
fürfalse
. Wenn Sie nur einen falschen Wert benötigen, können Sie einfachp
(den Rückgabewertnil
) verwenden.um ein paar Zeichen zu sparen.
quelle
true
(dh wenn ein wahrer Wert ausreicht, wie in einer if-Bedingung), brauchen Sie nicht einmal!!
.p
(was auswertetnil
) ein kürzerer Falsey-Wert. Was bedeutet, der kürzeste Wegtrue
ist!p
.Erstellen Sie Arrays mit
a=i,*a
, um sie in umgekehrter Reihenfolge abzurufen. Sie müssen nicht einmal initialisierena
, und wenn Sie dies tun , muss es kein Array sein .quelle
Wenn Sie jemals brauchen eine Reihe von bekommen
ARGV
,get
oder etwas ähnlichem etwas , das oft zu tun, statt Aufrufto_i
auf ihn können Sie nur verwenden ,?1.upto x{do something x times}
wobei x eine Zeichenfolge ist.Also mit
?1.upto(a){}
x.to_i.times{}
Wenn Sie anstelle von verwenden , sparen Sie 2 Zeichen.Sie können auch Dinge wie
p 1 while 1
oder umschreibenp 1 if 1
alsp 1while 1
oder umschreibenp 1if 1
Dieses Beispiel ist nicht sehr nützlich, könnte aber für andere Zwecke verwendet werden.
Wenn Sie das erste Element eines Arrays einer Variablen zuweisen müssen,
a,=c
werden im Gegensatz zu zwei Zeichen gespeicherta=c[0]
quelle
Neue Funktionen in Ruby 2.3 und 2.4
Es ist gut, sich über neue Sprachfunktionen zu informieren, die Ihrem Golfspiel helfen. In den neuesten Rubinen gibt es einige großartige.
Ruby 2.3
Der sichere Navigationsbetreiber:
&.
Wenn Sie eine Methode aufrufen, die möglicherweise zurückgibt,
nil
aber wenn dies nicht dernil
Fall ist, möchten Sie zusätzliche Methodenaufrufe verketten, verschwenden Sie Bytes, die den Fall behandeln:Der "Safe Navigation Operator" stoppt die Kette von Methodenaufrufen, wenn man zurückgibt
nil
undnil
für den gesamten Ausdruck zurückgibt :Array#dig
&Hash#dig
Tiefgreifender Zugriff auf verschachtelte Elemente mit einem schönen Kurznamen:
Gibt zurück,
nil
wenn es eine Sackgasse erreicht:Enumerable#grep_v
Die Umkehrung von -
Enumerable#grep
gibt alle Elemente zurück, die nicht mit dem angegebenen Argument übereinstimmen (verglichen mit===
). Wiegrep
, wenn ein Block gegeben sein Ergebnis wird stattdessen zurückgegeben.Hash#to_proc
Gibt einen Proc zurück, der den Wert für den angegebenen Schlüssel liefert, was sehr praktisch sein kann:
Ruby 2.4
Ruby 2.4 ist noch nicht verfügbar, wird aber bald verfügbar sein und einige großartige kleine Funktionen bieten. (Wenn es veröffentlicht wird, aktualisiere ich diesen Beitrag mit einigen Links zu den Dokumenten.) Die meisten davon habe ich in diesem großartigen Blog-Beitrag erfahren .
Enumerable#sum
Nicht mehr
arr.reduce(:+)
. Das kannst du jetzt einfach machenarr.sum
. Es wird ein optionales Anfangswertargument verwendet, das für numerische Elemente ([].sum == 0
) den Standardwert 0 hat . Für andere Typen müssen Sie einen Anfangswert angeben. Es akzeptiert auch einen Block, der vor dem Hinzufügen auf jedes Element angewendet wird:Integer#digits
Dies gibt ein Array der Ziffern einer Zahl in der Reihenfolge der niedrigsten bis höchsten Signifikanz zurück:
Im Vergleich zu sagen
123.to_s.chars.map(&:to_i).reverse
, das ist ziemlich schön.Als Bonus gibt es ein optionales Grundargument:
Comparable#clamp
Tut was es verspricht:
Da es in Comparable enthalten ist, können Sie es mit jeder Klasse verwenden, die Comparable enthält, zB:
String#unpack1
Einsparungen von 2 Byte gegenüber
.unpack(...)[0]
:Präzisions - Argument für
Numeric#ceil
,floor
undtruncate
Mehrfachzuordnung in Bedingungen
Dies löst einen Fehler in früheren Ruby-Versionen aus, ist jedoch in 2.4 zulässig.
quelle
Math::E.ceil(1)
zuMath::E.ceil 1
und ebenfalls fürfloor
undtruncate
.Enumerable#sum
,.flatten.sum
ist 2 Byte kürzer als.sum{|a,b|a+b}
(-Math::E).truncate(1)
entspricht-Math::E.truncate(1)
dem ist 1 Byte kürzer&.
kann mit einem solchen Index verwendet werdena&.[]i
(1 Byte kürzer alsa&.at i
). Obwohl, wenn Klammern erforderlich sind,a||a[i]
ist 1 Byte kürzer alsa&.[](i)
odera&.at(i)
Wissenschaftliche Notation kann oft verwendet werden, um ein oder zwei Zeichen zu entfernen:
quelle
1e2
ist besser, als100.0
wenn ein Prozentsatz benötigt wird.1.0*
ist 1.to_f
Verwenden Sie Operatormethoden anstelle von Klammern
Angenommen, Sie möchten ausdrücken
a*(b+c)
. Funktioniert aus Gründen des Vorrangsa*b+c
(offensichtlich) nicht. Rubys coole Art, Operatoren als Methoden zu haben, ist die Rettung! Sie können verwendena.*b+c
, um den Vorrang von*
niedriger als den von zu machen+
.Dies kann auch mit den Operatoren
!
und funktionieren~
(Dinge wie unary+
oder unary-
funktionieren nicht, weil ihre Methoden so sind-@
und sind+@
, speichern,()
aber hinzufügen.@
)quelle
Verwenden Sie
||
stattdessenor
und&&
stattdessenand
.Neben dem einen Charakter aus
and
Sie die Leerzeichen (und möglicherweise die Klammer) um den Operator herum speichern.Wenn Sie eine Schleife auf einem Array ausführen, verwenden Sie normalerweise
each
. Abermap
Schleifen auch über ein Array , und es ist ein Zeichen kürzer.quelle
Ich habe gerade versucht, eine TDD-Code-Golf-Challenge durchzuführen, dh, ich schreibe den kürzesten Code, um die Spezifikationen zu erfüllen. Die Angaben waren so etwas wie
Für Code-Golf muss kein Modul oder keine Klasse erstellt werden.
Anstatt von
man kann tun
Speichert 13 Zeichen!
quelle
PigLatin
, sondern auch@pig_latin
,$pig_latin
und'pig'['latin']
.translate
, dass am definiert wurdenil
.Kernel # p ist eine unterhaltsame Methode.
Verwenden Sie
p var
anstelle vonputs var
. Dies funktioniert perfekt mit ganzen Zahlen und Gleitkommazahlen, aber nicht mit allen Typen. Zeichenfolgen werden in Anführungszeichen gesetzt. Dies ist wahrscheinlich nicht das, was Sie möchten.Wird mit einem einzigen Argument verwendet.
p
das Argument nach dem Drucken zurückgegeben.Wird mit mehreren Argumenten verwendet.
p
die Argumente in einem Array zurückgegeben.Verwenden Sie
p
(ohne Argumente) anstelle vonnil
.quelle
p 'some string'
druckt"some string"
nicht nursome string
was oft von anderen kritisiert wird.p s
ist es dasselbe wieputs s.inspect
, aber es kehrt zurücks
Verwenden Sie nicht #each. Mit #map können Sie alle Elemente in einer Schleife durchlaufen. Also statt
Sie können dasselbe in weniger Bytes tun.
Natürlich
puts $*
wäre in diesem Fall noch kürzer.Es gibt Literale für rationale und komplexe Zahlen:
Sie können die meisten Bytes in Strings verwenden.
"\x01"
(6 Bytes) können auf""
(3 Bytes) gekürzt werden . Wenn Sie nur dieses eine Byte benötigen, kann dies noch weiter verkürzt werden?
(2 Byte) .Aus dem gleichen Grund können Sie Zeilenumbrüche wie folgt kürzen:
Sie können auch
?\n
und verwenden?\t
, das ist ein Byte kürzer als"\n"
und"\t"
. Zur Verschleierung gibt es auch ein Leerzeichen.Verwenden Sie Konstanten, anstatt Argumente zu übergeben, auch wenn Sie sie ändern müssen. Der Dolmetscher wird stderr warnen , aber wen interessiert das? Wenn Sie weitere miteinander in Beziehung stehende Variablen definieren möchten, können Sie diese wie folgt verketten:
Dies ist kürzer als
C=9;B=16;A=17
oderC=0;B=C+7;A=C+B
.Wenn Sie eine Endlosschleife benötigen, verwenden Sie
loop{...}
. Schleifen unbekannter Länge können mit anderen Schleifen kürzer sein:Noch ein paar gsub / regexp-Tricks. Verwenden Sie die speziellen
'\1'
Escape-Zeichen anstelle eines Blocks:Und die speziellen Variablen
$1
usw., wenn Sie Operationen ausführen müssen. Denken Sie daran, dass sie nicht nur innerhalb des Blocks definiert sind:Entfernen Sie Leerzeichen, Zeilenumbrüche und Klammern. Bei Ruby kann man einiges weglassen. Wenn Sie Zweifel haben, versuchen Sie immer, wenn es ohne funktioniert, und denken Sie daran, dies könnte einige Editor-Syntax-Hervorhebungen beschädigen ...
quelle
?\n
Ist auch nett, aber nicht wirklich kürzer als das Setzen eines Zeilenumbruchs in Anführungszeichen. (Gleiches gilt für die Registerkarte)puts$*
ist noch kürzer.x+=1;$*<<A
Noch eine andere Möglichkeit, den splat-Operator zu verwenden: Wenn Sie ein einzelnes Array-Literal zuweisen möchten, ist a
*
auf der linken Seite kürzer als eckige Klammern auf der rechten Seite:Bei mehreren Werten benötigen Sie nicht einmal den splat-Operator (danke an histocrat, der mich korrigiert hat):
quelle
Wenn eine Herausforderung erfordert , dass Sie die Ausgabe über mehrere Zeilen, Sie haben nicht zu Schleife durch Ihre Ergebnisse, um jede Zeile von zB einem Array zu drucken. Die
puts
Methode reduziert ein Array und druckt jedes Element in einer separaten Zeile.Wenn Sie den splat-Operator mit
#p
Ihnen kombinieren, können Sie ihn noch kürzer machen:Der splat-Operator (technisch gesehen die
*@
Methode) wandelt auch Ihre Nicht-Array-Enumerables in Arrays um:vs
quelle
*@
ist keine Methode, Splat ist syntaktischer ZuckerSpeichern Sie einige Bytes, wenn Sie wiederholte Elemente eines Arrays entfernen
Wenn Sie ein leeres Array
[]
in einer Variablen verwenden, können Sie noch mehr Bytes sparen:quelle
a&a
ist 1 Byte kürzerVerwenden Sie Goruby anstelle von Ruby, einer abgekürzten Version von Ruby. Sie können es mit rvm über installieren
In Goruby können Sie den größten Teil Ihres Codes so schreiben, wie Sie Ruby schreiben würden, es sind jedoch zusätzliche Abkürzungen integriert. Um die kürzeste verfügbare Abkürzung für etwas herauszufinden, können Sie
shortest_abbreviation
beispielsweise die Hilfsmethode verwenden :Sehr praktisch ist auch der Alias,
say
mitputs
dem sich selbst abkürzen lässts
. Also stattSie können jetzt schreiben
das Alphabet in Großbuchstaben zu drucken (was kein besonders gutes Beispiel ist). In diesem Blog-Beitrag werden weitere Themen und einige Aspekte des Innenlebens erläutert, wenn Sie weiterlesen möchten.
PS:
h
Lass dir die Methode nicht entgehen ;-)quelle
Stattdessen einem Array beitreten
mach das
Das spart 2 Bytes. Um sich mit einem Trennzeichen zu verbinden, verwenden Sie
quelle
Subskriptionsnummern!
Ich habe das erst gestern entdeckt.
n[i]
Gibtn
das Bit an deri
-ten Position zurück. Beispiel:quelle
n[0..3]
Möglicherweise können Sie 2 Zeichen speichern und verwenden
Anstatt von
Angenommen, wir möchten einen Bereich als Array definieren:
Mach es einfach so:
Und jetzt haben Sie Ihre Reichweite als Array.
quelle
[*1..2000]
funktioniert auch?<< Trick
kann gekürzt werden auf:
für -4 Bytes.
quelle
String
sArray#assoc
/rassoc
Wenn Sie ein Array von Arrays haben und das Unterarray suchen möchten, das mit einem bestimmten Wert beginnt, verwenden Sie nicht
Enumerable#find
, sondern verwenden SieArray#assoc
:Dies ist auch ein guter Ersatz für
Enumerable#any?
in manchen Situationen .Array#rassoc
tut dasselbe, prüft aber das letzte Element des Subarrays:quelle
a.any?
Zeile imrassoc
Beispiel|x,|
? Wie unterscheidet es sich von|x|
?x=[1,2]
vsx,=[1,2]
. Mit meinem obigen Beispiel wird mit|x|
in der ersten Iterationx
sein[0,"foo"]
. Mit|x,y|
,x
wird0
undy
wird sein"foo"
. Ebenso mit|x,|
,x
wird0
. Mit anderen Worten heißt es: "Setze das erste Element einx
und wirf den Rest weg.|,y|
ein SyntaxError, ergo|_,y|
. Aber ich habe gerade erst gemerkt, dass das|*,y|
funktioniert, was sauberer ist als die Verwendung einer Variablen namens_
(aber nicht kürzer).