Golftipps in Lua

21

Welche allgemeinen Tipps haben Sie zum Golfen in Lua? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme im Allgemeinen anwenden lassen, die zumindest etwas spezifisch für Lua sind (z. B. "Kommentare entfernen" ist keine Antwort). Bitte posten Sie einen Tipp pro Antwort.

Scheurneus
quelle
6
Tipps Fragen sollten Community-Wiki sein. Aber für alle, die dies als "hauptsächlich meinungsbasiert" einreichten, sind die Tipps für Fragen zum Golfspielen in der Sprache unsere akzeptierte Ausnahme von dieser Regel. Die offene Natur dieser Fragen ist, warum sie Community-Wiki-ed sind.
Jonathan Van Matre

Antworten:

9

Zusätzlich zu den bereits veröffentlichten sind hier einige Tricks, die ich im Laufe der Zeit gesammelt habe, in keiner bestimmten Reihenfolge ...

  • Bei Funktionsaufrufen, bei denen nur ein Parameter durch ein Symbol begrenzt ist ( "für Zeichenfolgen, {für Tabellen), muss der Parameter nicht in Klammern gesetzt werden.
    Zum Beispiel können Sie stattdessen print("hello")einfach Folgendes tun:print"hello"

  • Entfernen Sie so viel Leerzeichen wie möglich - dies besonders einfach nach einem Symbol zu tun ist , dass schließt Strings (oder vor einer Öffnung), Funktionsaufrufe, Tische ...
    Statt die print(42) a=1Sie tun können print(42)a=1. Ein anderes Beispiel: print(a and-1 or-2).

  • Verwenden Sie den ternären Operator, wenn Sie können! Stattdessen if a>0 then print("hello") else print("goodbye") endlieber print(a>0 and "hello" or "goodbye"). Mehr Infos hier .
    (Dies kann tatsächlich noch besser werden: print(a>0 and"hello"or"goodbye"))

  • Verwenden Sie den syntaktischen Zucker mit Doppelpunktaufruf, wenn Sie: statt string.rep(str,12)tun können str:rep(12). Das funktioniert auch bei Nicht-Variablen so (und nur so):("a"):rep(5)

  • Anstatt tonumber(str)nur zu tunstr+0

  • Für Funktionen ohne Parameter können Sie Folgendes ausführen, anstatt sie auf die übliche Weise zu definieren ( function tick() blabla() end) ticks=loadstring"blabla()":, wodurch je nach Inhalt mindestens 1 Byte gespart werden. Wenn Sie mehrere Funktionen definieren, lokalisieren Sie diese zuvor loadstringin einer 1-Zeichen-Variablen, und Sie sparen eine Menge Bytes. Dank an Jim Bauwens für diesen Trick.

  • Lua betrachtet leere Zeichenfolgen (und im 0Gegensatz zu anderen Sprachen) als wahr in bedingten Tests. while 1 do ... endSparen Sie zum Beispiel 1 Byte durch Schreiben , anstatt dies zu tunwhile''do ... end

Adriweb
quelle
(Loadstring-Trick hinzugefügt)
Adriweb
2
0 ein wahrer Wert ist nur dumm
SuperJedi224
Ein anderes str+0Äquivalent ist ~~str, kann nützlich sein, weil es Vorrang hat
Felipe Nardi Batista
@FelipeNardiBatista, dies wird jedoch nur von Lua 5.3+
Adriweb
5

Ich habe schon an einen gedacht. Ich weiß nicht, ob es in anderen Sprachen funktioniert, aber ich kenne nur Lua, mit dem Sie Funktionen in Variablen speichern können. Wenn also zB string.subin Ihrem Programm mehrfach verwendet wird, verwenden Sie zB s=string.sub.

Scheurneus
quelle
4
Es funktioniert auch in vielen anderen Sprachen wie Python und Ruby.
nyuszika7h
4
Javascript und Haskell können auch Funktionswerte haben.
stolzer Haskeller
Dies ist äquivalent zu s=("").suboder s=a.subfür jede Variable, adie einen Zeichenfolgenwert enthält.
Egor Skriptunoff
Dies nennt man erstklassige Funktionen
Redwolf Programs
5

Es ist eine ziemlich ausführliche Sprache zum Golfen ... aber einige allgemeine Tipps, die mir einfallen, sind:

  • Vermeiden Sie Bedingungen, da if... then... else... endeine große Verschwendung ist.
  • Versuchen Sie stattdessen, sich auf kürzere Sprachkonstrukte zu konzentrieren, z for i=1,5 do.
  • Der #Betreiber ist ziemlich gut zum Golfen (und im Allgemeinen).
Tal
quelle
5

Verkürzen Sie Ihre Endlosschleife

Wenn Sie eine Endlosschleife verwenden müssen, können Sie an die Verwendung von a denken while, aber stattdessen ist die Verwendung eines Labels um 2 Byte kürzer:

while''do end
::a::goto a

Verwenden Sie so wenig Platz wie möglich

Es gibt eine einfache Sache, mit der Sie (ab) noch mehr Leerzeichen aus Ihrem Code entfernen können. Die Angaben von Lua zu dem Namen, den Sie Variablen geben, sind eindeutig: Sie müssen mit einem Buchstaben beginnen. Manchmal kann man Leerzeichen zwischen Zahlen und Funktionen / Variablen überspringen

x=0>1 and 0or 1print(x)

Die Möglichkeit, das Leerzeichen zu entfernen, hängt von dem Buchstaben ab, der auf die Zahl folgt. Mit dem folgenden Buchstaben können Sie dies nicht tun:

a,b,c,d,e,f            -- They would be interpreted as hexadecimal
x                      -- only fail when after a 0, other number are fine
                       -- (0x indicates the following is an hexadecimal number)

Indem Sie dies verwenden und darauf achten, wie Sie Ihre Variablen aufrufen, können Sie die meisten Ihrer Quellcodes platzsparend gestalten.

Wenn Sie hier bereits ein Beispiel aufgreifen und diesen Rat befolgen, ist hier ein weiteres Byte, das Sie abschneiden könnten :).

print(a and-1 or-2)
print(a and-1or-2)

Verwenden Sie die richtige Eingabemethode

Wenn wir uns die vorformulierten und Kosten für jeden aussehen Haupt Art von Input, hier ist , was wir haben:

function f(x)x end
io.read()
arg[1]

Jede dieser Methoden erlaubt es uns, 1 Eingabe zu nehmen, wobei die Funktion die teuerste ist (aber es erlaubt uns, eine Tabelle als Eingabe zu nehmen).

Wir können jetzt sehen, dass die Verwendung von Befehlszeilenargumenten der richtige Weg ist, wenn Sie Golf spielen möchten. Beachten Sie jedoch, dass es sogar noch kürzer sein kann

arg[1]
...

Das ...ist etwas Besonderes in lua, es ist eine Variable, die den entpackten Inhalt von argoder die entpackten Parameter im Falle einer variadischen Funktion enthält.

Wenn Sie mehr als eine Eingabe benötigen und jede von ihnen verwenden müssen, kann es sinnvoll sein, sie in einer Variablen zu speichern. Hier sind einige Möglichkeiten zum Speichern von 2 Eingaben in Variablen

a=arg[1]b=arg[2]    -- highly un-efficient, costs 8 bytes by variable
a,b=unpack(arg)     -- costs 15, but at least doesn't depends on the number of argument
a,b=...             -- only costs 7

und hier sind die kürzesten Aufrufe, die Sie ohne die Variablen hätten machen können:

...     -- using a allow a gain of 1-2 bytes at each use
arg[2]  -- using b allow a gain of 4-5 bytes at each use

Ab dem Punkt, an dem Sie 3 Argumente haben, oder wenn Sie 2 Argumente verwenden, wobei eines zweimal verwendet wird, gewinnen Sie aufgrund von bereits Bytes a,b=...! :)

Fast nie verwenden, wenn!

Es gibt so gut wie keine Fälle, in denen die Verwendung einer if / elseif / if-Anweisung weniger kostet als eine ternäre Anweisung. Das Boilerplate für eine solche Aussage ist wirklich schwer:

-- exemple with dumb values
if 1>0then v=1 else v=0 end
v=1>0 and 1or 0

Mit einem einfachen Beispiel sparen Sie bereits 12 Bytes, wenn Sie ein paar elseifs machen müssen, wird es immer wichtiger, also seien Sie sich dessen bewusst!

Auch Ternaries in Lua sind etwas Besonderes , es gibt einige Bedingungen, wie sie funktionieren. Für Interessierte erkläre ich es hier:

Ternaries in lua sind von der Form <condition> and <case true: have to be a true value> or <case false: can be anything>

Sehen wir uns zunächst die Wahrheitstabelle der or. A orkann als eine Funktion betrachtet werden: Es gibt immer einen Wert zurück. Hier ist der Wert, den es zurückgibt:

x | y ||x or y
------||-------
0 | 0 ||   y
0 | 1 ||   y
1 | 0 ||   x
1 | 1 ||   x

Das ist es, was uns erlaubt, unser Dreistöckchen zu konstruieren.

Das andist es, was es uns ermöglichen , den Zustand zu beurteilen, es wird immer wieder zurückkehren , ywenn x and yauswertet auf true.

Das Problem dabei ist, dass es fehlschlagen wird, wenn wir eine niloder falseeine Rückgabe wünschen, wenn die Bedingung erfüllt ist false. Beispielsweise wird das Folgende immer 5 zurückgeben, obwohl die Bedingung erfüllt ist.

v = true and false or 5

Hier ist eine schrittweise Auswertung eines Ternärs, um zu erklären, wie es funktioniert (nützlich, wenn Sie sie verschachteln müssen :))

-- let's use our dumb ternary
= true and false or 5
-- and statement will be evaluated first, leading to
= false or 5
-- and we saw how the or works
= 5
Katenkyo
quelle
Ein Tipp pro Antwort, bitte.
ATaco
Beachten Sie, dass der Trick "Verwenden Sie möglichst wenig Speicherplatz" nur unter Lua 5.2 und höher funktioniert.
Adriweb
4

Ich habe auch einige Tipps zusammengestellt. Ich bin sicher, einige von mir werden sich mit den bereits genannten überschneiden, aber ich werde sie trotzdem in den Prozess der Erstellung einer vollständigeren Antwort einbeziehen.


Weisen Sie Variablen wiederholte Funktionen zu

Mit Lua können Sie Variablen Funktionen zuweisen. Sogar Variablen mit einem Zeichen. Das heißt, wenn Sie die Funktion string.sub(x, y)mehr als zweimal wiederholen , profitieren Sie davon, wenn Sie sie einer Variablen zuweisen.

Ohne Zuordnung zu einer Variablen (69 Zeichen):

print(string.sub(x, y))
print(string.sub(x, y))
print(string.sub(x, y))

Zuweisen zu einer Variablen (51 Zeichen):

s=string.sub
print(s(x,y))
print(s(x,y))
print(s(x,y))

Es gibt Fälle, in denen Sie noch einen Schritt weiter gehen können. Lua erlaubt einem OOP die Manipulation von Strings wie folgt: str:sub(x, y)oder str.sub(x, y)Dies eröffnet neue Optionen für unseren Code. Sie können der Funktion eine Variable zuweisen, indem Sie wie gezeigt auf sie verweisen (46 Zeichen).

s=z.sub
print(s(x, y))
print(s(x, y))
print(s(x, y))

Verwenden Sie die effizienteste Methode zum Parsen von Zeichenfolgen

Möglicherweise verwenden Sie eine forSchleife string.sub, um Zeichen für Zeichen in Lua zu iterieren. Manchmal funktioniert das am besten, je nach Ihren Anforderungen, aber manchmal funktioniert string.gmatch auch mit weniger Zeichen. Hier ist ein Beispiel für beide:

s=io.read()
for a = 1, s:len() do
    print(s:sub(a, a))
end 

for i in io.read():gmatch('.') do
    print(i)
end

Und wenn man Golf spielt, ist der Unterschied bemerkenswerter:

s=io.read()for a=1,s:len()do print(s:sub(a, a))end

for i in io.read():gmatch'.'do print(i)end

Umstrukturierungszuweisungen zur Optimierung des Leerraums

In Lua müssen Sie kein Leerzeichen zwischen eine geschlossene Klammer oder ein Anführungszeichen am Ende und das nächste Zeichen setzen. Bisher habe ich zwei Fälle gefunden, in denen eine Umstrukturierung vor diesem Hintergrund die Zeichen schneidet.

  • Variablen zuweisen:

     x,y=io.read(),0 print(x)
     vs.
     y,x=0,io.read()print(x)
    
  • If-Anweisungen:

     if x:sub(1,1)==1 then
     vs
     if 1==x:sub(1,1)then
    

Geben Sie die wenigsten Zeichen zurück, die möglich sind

Wenn Sie einen wahren oder falschen Wert zurückgeben müssen, müssen Sie anscheinend mindestens 5 Zeichen für den Rückgabewert verwenden. In Wirklichkeit funktioniert Folgendes genauso gut:

return true
return false
vs
return 1>0
return 0>1
Skyl3r
quelle
Tolle Tipps, ich habe mir die Freiheit genommen, eine Änderung für Ihren Beitrag vorzuschlagen. Nur nilund das falseErgebnis falsch in lua, alles andere ist wahr, so dass Ihre Tipps zu ersetzen x==0, x==""und x==''durch xfalsch. Ich ändere es gerade auf nil:).
Katenkyo
Ah, du hast recht. Vielen Dank, dass Sie das behoben haben!
Skyl3r
2

Dies sind (meiner Meinung nach) nur Lua-Optimierungen:

Zeichenfolgen werden bei arithmetischen Operationen automatisch in Zahlen umgewandelt. Achten Sie auf bedingte Anweisungen, die nicht automatisch konvertiert werden. Dies ist ideal, um Benutzereingaben als Zahlen zu verwenden und dabei Platz zu sparen.

Das Umschalten des Inhalts zweier Variablen erfordert keine temporäre Variable. a,b=b,avertauscht die Werte von a und b.

Um das oben Gesagte zu erweitern, kann jedes alphanumerische Zeichen ein nicht alphanumerisches Zeichen berühren. Es a,b=io.read():match"(.+)/(.+)"u,v=a,bist also ein perfektes, funktionierendes Skript, auch wenn Leerzeichen fehlen.

Dwayne Slater
quelle
2

Kombinieren Sie Zuweisungen lokaler Variablen

Anstatt:

local a=42
local b=17
local c=99

Verwenden Sie die parallele Zuordnung:

local a,b,c=42,17,19

6 Bytes für jede Variable gespeichert!

Deklarieren Sie lokale Variablen über nicht verwendete Funktionsparameter

Anstatt:

function foo(a,b) local c,d ... end
function bar(a,b) local c,d=42,17 ... end

Verwenden

function foo(a,b,c,d) ... end
function bar(a,b,c,d) c,d=42,17 ... end

6 Bytes gespeichert (minus 1-2 Bytes für jede Variable, die dupliziert werden könnte).

Phrogz
quelle
1
Abgestimmt, weil es absolut keinen Fall gibt, in dem die Verwendung localbeim Golfen gerechtfertigt ist, weil Sie nur einen anderen Namen verwenden müssen. Wir könnten ALLE Namen von bis zu 7 Zeichen UND Tabellen mit Zeichenfolgenindizes von bis zu 7 Zeichenkombinationen verwenden, bevor wir auf etwas stoßen, das von der Verwendung von Einheimischen profitieren könnte
Katenkyo,
1

Variadische Funktionen

Die Hauptvariablenfunktion, die Sie stören wird, ist print(). Wenn Sie es beispielsweise verwenden, String.gsub()wird die von Ihnen geänderte Zeichenfolge UND die Häufigkeit der gsubAuslösung gedruckt .

Um diese zweite Ausgabe zu unterdrücken, kapseln Sie Ihre gsubIn-Parens ein, um zu erzwingen, dass nur ein Wert zurückgegeben wird

print(String.gsub("aa",".","!"))    -- outputs "!!    2\n"
print((String.gsub("aa",".","!")))  -- outputs "!!\n"
Katenkyo
quelle
1

Wissen, wie man ausgibt

Es gibt zwei Hauptmethoden für die Ausgabe in lua

io.write()    -- outputs without trailing newline
print()       -- outputs with trailing new line and shorter by 3 bytes

Wenn Sie mehrere Male verketten müssen, können Sie dies verkürzen, indem Sie io.write()anstelle des Standardverkettungsoperators eine Variable mit einem Buchstaben verwenden..

i(a)    -- i was defined as io.write
s=s..a

Sie erhalten 2 Bytes bei jedem Anruf, während Sie im Voraus bezahlen

i=io.write  -- longer by 6 bytes
s=""

Sie befinden sich bereits in der dritten Verkettung und erhalten ab der vierten Byte.

Katenkyo
quelle
3
Es ist printund nicht printf!
Val sagt Reinstate Monica
@val Wow, ich weiß nicht mal, wie ich diesen Fehler machen könnte. Vielen Dank für den Hinweis, ich werde bearbeiten
Katenkyo
1

Eine Reihe von Tipps in keiner bestimmten Reihenfolge:

  • stringist ein ziemlich langer Name. Effizient ('').charist das gleiche wie string.char. Noch bessere Ergebnisse können erzielt werden, wenn Sie es zusammen mit einem Semikolon für Variablen: verwenden a=...; print(a:sub(1, 5)). Einige stringFunktionen verwenden jedoch keine Zeichenfolgen als Eingabe.
  • Lua hat in den meisten Fällen automatische Konvertierungen zwischen Zeichenfolgen und Zahlen, also tonumberund+0 oft nur Bytes verschwenden.
  • Immer load'your function code here'statt verwenden function()your function code here end. Auf Funktionsargumente zugreifen mit... inside auf .
  • Einige String-Funktionen in Lua können unbeabsichtigt verwendet werden! Beispielsweise,a:gsub('.',load'my function') scheint der kürzeste Weg zu iterieren Zeichen in einer Zeichenfolge zu sein
  • Während die String-Engine leistungsstark ist, sollten Sie auf ihre Leistungsfähigkeit achten, wenn Sie Benutzereingaben als Muster verwenden! Aus diesem Grund müssen Sie möglicherweise verwenden a:find('.',1,1)(um dieses Problem zu testen, versuchen Sie, %an verschiedenen Stellen in Ihre Eingabe aufzunehmen und die Ergebnisse zu überprüfen). Unzählige Ideen gingen kaputt, weil Lua versuchte, Eingaben als Muster zu analysieren.
  • nilist drei Bytes, _ist eins (es ist nur ein zufälliger Name, der höchstwahrscheinlich nicht existiert). Außerdem wird jede Ziffer als Wahrheitswert verwendet.
  • Kennen Sie Ihre Logik dahinter x and i or o. Es ist nicht nur ein ternärer Operator - es ist ein vollständiger logischer Ausdruck. Tatsächlich bedeutet dies Folgendes: "Wenn xes wahr ist, versuchen Sie es i. Wenn entweder x oder i falsch ist, geben Sie o zurück." Wenn ialso nicht wahr ist, ist das Ergebnis o. Es können auch beide andoder orTeile weggelassen werden ( x and i, x or o).
  • Verwendung ganzzahligen Division durch eine statt math.floor: 5.3//1==5.0. Bitte beachten Sie, dass die resultierende Zahl immer der Art der Eingabe eins (Integer / Float) folgt.
val sagt Reinstate Monica
quelle
1
"Außerdem funktioniert jede Ziffer als Wahrheitswert." Ich wollte nur darauf eingehen, dass dies 0 enthält, was für einige Programmierer mit C / C ++ - Hintergrund möglicherweise nicht sehr intuitiv ist.
30.