Suggerimenti per il golf a Lua


21

Quali consigli generali hai per giocare a golf a Lua? Sto cercando idee che possano essere applicate ai problemi del codice golf in generale che siano almeno in qualche modo specifiche per Lua (ad esempio "rimuovere i commenti" non è una risposta). Si prega di inviare un suggerimento per risposta.


6
Suggerimenti domande dovrebbero essere wiki della comunità. Ma per chiunque lo abbia presentato come "principalmente basato sull'opinione", i suggerimenti per le domande sul golf in lingua sono la nostra eccezione accettata a tale regola. La natura aperta di queste domande è il motivo per cui sono wiki della community.
Jonathan Van Matre,

Risposte:


9

Oltre a quelli già pubblicati, ecco alcuni trucchi che ho raccolto nel tempo, in nessun ordine specifico ...

  • Per le chiamate di funzione che hanno solo un parametro delimitato da un simbolo ( "per stringhe, {per tabelle), non è necessario racchiudere il parametro tra parentesi.
    Ad esempio, invece di farlo print("hello"), puoi semplicemente fare:print"hello"

  • Rimuovi quanto più spazio bianco possibile - questo è particolarmente facile da fare dopo un simbolo che chiude stringhe (o prima di un'apertura), chiamate di funzione, tabelle ...
    Invece di print(42) a=1te puoi farlo print(42)a=1. Altro esempio: print(a and-1 or-2).

  • Usa l'operatore ternario quando puoi! Invece di if a>0 then print("hello") else print("goodbye") end, preferisci print(a>0 and "hello" or "goodbye"). Maggiori informazioni qui .
    (Questo può effettivamente ottenere ancora meglio: print(a>0 and"hello"or"goodbye"))

  • Usa lo zucchero sintattico per i due punti quando puoi: invece di string.rep(str,12), fallo str:rep(12). Funziona anche su non variabili in questo modo (e solo in questo modo):("a"):rep(5)

  • Invece di fare tonumber(str)bastastr+0

  • Per le funzioni senza parametri, invece di definirle come di consueto ( function tick() blabla() end), puoi fare ticks=loadstring"blabla()":, che salva 1 o più byte, a seconda del contenuto. Inoltre, se si definiscono più funzioni, localizzare prima loadstringin una variabile a 1 carattere e si risparmieranno molti byte;). Ringraziamo Jim Bauwens per questo trucco.

  • Lua considera la stringa vuota (e 0troppo diversa dalle altre lingue) come vera nei test condizionali, quindi, ad esempio, invece di fare while 1 do ... end, salva 1 byte scrivendowhile''do ... end


(Aggiunto il trucco del cordone di carico)
Adriweb,

2
0 essendo un valore veritiero è semplicemente stupido
SuperJedi224,

un altro str+0equivalente è ~~str, può essere utile per la sua precedenza
Felipe Nardi Batista,

@FelipeNardiBatista, tuttavia, è supportato solo su Lua 5.3+
Adriweb,

5

Ne ho già pensato uno. Non so se funziona in altre lingue, ma Lua è l'unica che conosco che ti permette di memorizzare le funzioni in variabili. Quindi se ad esempio string.subviene utilizzato più volte nel programma, utilizzare ad es s=string.sub.


4
Funziona anche in molte altre lingue come Python e Ruby.
nyuszika7h

4
Anche Javascript e Haskell possono avere valori di funzione.
orgoglioso haskeller il

Ciò equivale s=("").subao s=a.subper qualsiasi variabile acontenente valore stringa.
Egor Skriptunoff,

Questo si chiama funzioni di prima classe
Programmi Redwolf

5

È un linguaggio piuttosto prolisso per il golf ... ma alcuni suggerimenti generali che vengono in mente sono:

  • Cercate di evitare i condizionali, poiché if... then... else... endè uno spreco maggiore.
  • Cerca invece di concentrarti su costrutti linguistici più brevi, ad es for i=1,5 do.
  • L' #operatore è piuttosto eccezionale per il golf (e in generale).

5

Accorcia il tuo ciclo infinito

Quando devi usare un ciclo infinito, potresti pensare di usare a while, ma invece usare un'etichetta è più breve di 2 byte:

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

Usa meno spazio possibile

C'è una cosa semplice che potresti (ab) usare per rimuovere ancora più spazi dal tuo codice. Le specifiche di Lua sono chiare sul nome che dai alle variabili: devono iniziare con una lettera. Implica che, a volte, è possibile saltare spazi tra numeri e funzioni / variabili

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

La possibilità di rimuovere lo spazio dipende dalla lettera che segue il numero, ecco la lettera che non ti permetterà di farlo:

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)

Usando questo, e prestando attenzione a come chiamate le vostre variabili, potete liberare spazio nella maggior parte dei vostri codici sorgente.

Raccogliendo un esempio già qui, e usando questo consiglio, ecco un altro byte che potresti radere :).

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

Usa il metodo di input corretto

Se osserviamo la piastra di caldaia e i costi per ciascun tipo principale di input, ecco cosa abbiamo:

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

Ognuno di questi metodi ci consente di prendere 1 input, con la funzione che è quella con il costo più pesante (ma ci permette di prendere una tabella come input)

Ora possiamo vedere che l'uso dell'argomento della riga di comando è la strada da percorrere se si desidera giocare a golf, ma attenzione: può essere ancora più breve

arg[1]
...

La ...sono un po 'speciale in lua, è una variabile che contiene il contenuto di directory del argoi parametri imballati in caso di una funzione variadic.

Quando dovrai ottenere più di un input e utilizzarli ciascuno, può essere utile salvarli in una variabile. Ecco alcuni modi per salvare 2 input in variabili

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

e qui ci sono le chiamate più brevi che avresti potuto fare senza le variabili:

...     -- 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

Dal punto in cui hai 3 argomenti, o quando usi 2 argomenti, con uno usato due volte, stai già guadagnando byte a causa di a,b=...! :)

Quasi mai usare se!

Non c'è quasi nessun caso in cui l'uso di un'istruzione if / elseif / if costerà meno di un ternario. il bollettino per tale affermazione è davvero pesante:

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

Con un semplice esempio, salvi già 12 byte, quando devi fare qualche altra cosa, diventa sempre più importante, quindi fai attenzione!

Inoltre, i ternari in lua sono speciali , ci sono alcune condizioni nel loro funzionamento, per chi è interessato, lo spiegherò di seguito:

I ternari in lua sono della forma <condition> and <case true: have to be a true value> or <case false: can be anything>

Prima di tutto, vediamo la tabella di verità di or. A orpuò essere considerata come una funzione: restituisce sempre un valore, ecco il valore che restituisce:

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

Questo è ciò che ci consente di costruire il nostro ternario.

Il andè ciò che ci permette di valutare la condizione, sarà sempre tornare yse x and yrestituisce true.

Il problema è che fallirà se vogliamo un nilo falseessere restituito quando la condizione è false. Ad esempio, quanto segue restituirà sempre 5, nonostante la condizione sia vera.

v = true and false or 5

Ecco una valutazione dettagliata di un ternario per spiegare come funziona (sarà utile quando devi nidificarli :))

-- 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

Un consiglio per risposta, per favore.
ATaco,

Nota che il trucco "Usa meno spazio possibile" funziona solo su Lua 5.2 e versioni successive.
Adriweb,

4

Ho anche compilato diversi suggerimenti. Sono sicuro che alcuni dei miei si sovrapporranno a quelli già dichiarati, ma li includerò comunque nella vena di creare una risposta più completa.


Assegna funzioni ripetute alle variabili

Lua ti consente di assegnare funzioni alle variabili. Anche una variabile di carattere. Ciò significa che se ripeti la funzione string.sub(x, y)più di due volte, otterrai un vantaggio dall'assegnarla a una variabile.

Senza assegnare a una variabile (69 caratteri):

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

Assegnare a una variabile (51 caratteri):

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

Ci sono casi in cui puoi fare ancora un ulteriore passo avanti. Lua consente a un OOP di manipolare le stringhe, in questo modo: str:sub(x, y)oppure str.sub(x, y)Questo apre nuove opzioni per il nostro codice. È possibile assegnare una variabile alla funzione tramite il riferimento come mostrato (46 caratteri.)

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

Utilizzare il modo più efficiente per analizzare le stringhe

Potresti ritrovarti a utilizzare un forloop e string.suba iterare carattere per personaggio in Lua. A volte questo può funzionare meglio, a seconda delle tue esigenze, ma altre volte, string.gmatch funzionerà con meno caratteri. Ecco un esempio di entrambi:

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

E quando si gioca a golf, la differenza è più evidente:

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

Ristruttura le assegnazioni per ottimizzare gli spazi bianchi

In Lua, non è necessario inserire uno spazio tra parentesi chiuse o virgolette finali e il carattere successivo. Finora, ho trovato due casi in cui la ristrutturazione con questo in mente taglierà i personaggi.

  • Assegnare variabili:

     x,y=io.read(),0 print(x)
     vs.
     y,x=0,io.read()print(x)
    
  • Se dichiarazioni:

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

Restituisce il minor numero possibile di caratteri

Se devi restituire un valore vero o falso, allora devi necessariamente usare almeno 5 caratteri per il valore restituito. In realtà anche i seguenti funzionano:

return true
return false
vs
return 1>0
return 0>1

Ottimi consigli, ho preso la libertà di suggerire una modifica al tuo post. Solo nile falsevaluta falso in lua, tutto il resto è vero, quindi i tuoi consigli sulla sostituzione x==0,x=="" e x==''dai xè falso. Attualmente lo sto cambiando in nil:).
Katenkyo,

Ah, hai ragione. Grazie per averlo risolto!
Skyl3r,

2

Queste sono solo ottimizzazioni (credo) di Lua:

Le stringhe vengono automaticamente convertite in numeri quando si eseguono operazioni aritmetiche su di esse. Fai attenzione alle dichiarazioni condizionali, che non si convertono automaticamente. Questo è ottimo per prendere l'input dell'utente come numeri risparmiando spazio.

Il cambio del contenuto di due variabili non richiede una variabile temporanea. a,b=b,ascambieranno i valori di ae b.

Inoltre, per estendere quanto detto sopra, qualsiasi carattere alfanumerico può toccare un carattere non alfanumerico. Quindi a,b=io.read():match"(.+)/(.+)"u,v=a,bè una sceneggiatura perfetta e funzionante, anche con la mancanza di spazi bianchi.


2

Combina assegnazioni di variabili locali

Invece di:

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

Usa assegnazione parallela:

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

6 byte salvati per ogni variabile!

Dichiarare variabili locali tramite parametri di funzione non utilizzati

Invece di:

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

Uso

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

6 byte salvati (meno 1-2 byte per ogni variabile che potrebbe essere duplicata).


1
Sottovalutato perché non c'è assolutamente nessun caso in cui l'uso localè giustificato quando si gioca a golf, perché devi solo usare un nome diverso. Potremmo usare TUTTI i nomi fino a 7 caratteri E tabelle con indici di stringa fino a 7 combinazioni di caratteri prima di colpire qualcosa che potrebbe trarre vantaggio dall'uso della gente del posto
Katenkyo,

1

Funzioni variabili

La principale funzione variadica che ti disturberà è print(). Ad esempio, quando lo usi insieme String.gsub()stamperà la stringa che hai modificato E il numero di voltegsub innescate.

Per sopprimere quel secondo output, incapsula il tuo gsubin parentesi per forzarlo a restituire un solo valore

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

1

Sapere come produrre

Esistono due metodi principali per produrre in lua

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

Quando è necessario concatenare più volte, è possibile accorciarlo utilizzando io.write()assegnato a una variabile di una lettera anziché l'operatore di concatenazione standard..

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

Guadagni 2 byte ad ogni chiamata pagando in anticipo

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

Sei anche alla terza concatenazione e inizi a guadagnare byte sul quarto.


3
Lo è printe non printf!
dice Val Reinstate Monica il

@val Wow, non so nemmeno come potrei fare quell'errore. Grazie per averlo sottolineato, lo modificherò
Katenkyo,

1

Un sacco di consigli in nessun ordine particolare:

  • stringè un nome piuttosto lungo. In modo efficiente, ('').charè lo stesso di string.char. Risultati ancora migliori possono essere raggiunti se lo si utilizza insieme a un punto e virgola sulle variabili:, a=...; print(a:sub(1, 5))ma alcune stringfunzioni non accettano stringhe come input.
  • Lua ha conversioni automatiche tra stringhe e numeri per la maggior parte dei casi, quindi tonumbere +0spesso spreca solo byte.
  • Usa sempre load'your function code here'invece di function()your function code here end. Accedi agli argomenti della funzione usando ...inside.
  • Alcune funzioni di stringa in Lua possono essere utilizzate in modo non intenzionale! Per esempio,a:gsub('.',load'my function') sembra essere il modo più breve per scorrere i caratteri in una stringa
  • Mentre il motore di stringa è potente, fai attenzione alla sua potenza quando usi l'input dell'utente come pattern! Per questo motivo, potrebbe essere necessario utilizzare a:find('.',1,1)(per verificare questo problema, provare ad includere %in vari punti dell'input e verificare i risultati). Innumerevoli idee si sono rotte a causa del tentativo di Lua di analizzare l'input come modello.
  • nilè di tre byte, _è uno (è solo un nome casuale che molto probabilmente non esiste). Inoltre, qualsiasi cifra funzionerà come valore di verità.
  • Conosci la tua logica dietro x and i or o. Non è solo un operatore ternario, è un'espressione logica completa. In realtà, significa quanto segue: "se xè vero, prova i. Se x o i è falso, restituisci o". Quindi, se inon è vero, il risultato è o. Inoltre, entrambe ando orparti possono essere omesse ( x and i,x or o ).
  • Uso divisione intera da uno invece di math.floor: 5.3//1==5.0. Si noti che il numero risultante segue sempre il tipo di input uno (intero / float).

1
"Inoltre, qualsiasi cifra funzionerà come valore di verità." Volevo solo chiarire che questo include 0, che potrebbe non essere molto intuitivo per alcuni programmatori da uno sfondo C / C ++.
ouflak,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.