Lua'da golf için ipuçları


21

Lua'da golf oynamak için hangi genel ipuçlarınız var? Genel olarak golf problemlerini kodlamak için uygulanabilecek fikirleri arıyorum, en azından biraz Lua'ya özgü (örneğin, "yorumları kaldır" bir cevap değil). Lütfen cevap başına bir ipucu gönderin.


6
İpuçları soruları topluluk wiki olmalı. Ancak, bunu “öncelikli olarak görüşe dayalı” olarak yakın olarak sunanlara, Dilde Golf İçin İpuçları soruları bu kuralın kabul gören istisnasıdır. Bu soruların açık uçlu doğası neden topluluk wikid'leridir.
Jonathan Van Matre

Yanıtlar:


9

Daha önce yayınlanmış olanların yanı sıra, zaman içinde topladığım bazı püf noktaları, belirli bir sıraya göre değil ...

  • Bir sembolle ayrılmış yalnızca bir parametresi olan işlev çağrıları "için ( dizeler {için, tablolar için), parametrenin parantez içine alınması gerekmez.
    Örneğin, yapmak yerine print("hello"), şunları yapabilirsiniz:print"hello"

  • Mümkün olduğunca fazla boşluk bırakın - bu özellikle dizeleri kapatan bir sembolden sonra (veya bir açılıştan önce), işlev çağrıları, tablolar ... yapmak
    yerine kolaydır . Diğer örnek: .print(42) a=1print(42)a=1print(a and-1 or-2)

  • Mümkün olduğunda üçlü operatörü kullanın! Bunun yerine if a>0 then print("hello") else print("goodbye") endtercih et print(a>0 and "hello" or "goodbye"). Daha fazla bilgi burada .
    (Bu aslında iyi bile alabilirsiniz: print(a>0 and"hello"or"goodbye"))

  • Yapabileceğiniz zaman iki nokta çağrısı sözdizimsel şekeri kullanın: yerine string.rep(str,12), yapın str:rep(12). Bu ayrıca değişken olmayanlar üzerinde de bu şekilde çalışır (ve sadece bu şekilde):("a"):rep(5)

  • tonumber(str)Sadece yapmak yerinestr+0

  • Parametresiz olan fonksiyonlar için, normal yöntemle ( function tick() blabla() end) tanımlamak yerine , yapabilecekleriniz: ticks=loadstring"blabla()"içeriğe bağlı olarak 1 veya daha fazla bayt kazandıran. Ayrıca, birden fazla işlev tanımlarsanız, loadstringönce 1 karakterlik bir değişkene yerelleştirin ve çok fazla bayt kaydedin;). Bu numara için Jim Bauwens'e teşekkür ederiz.

  • Lua, boş dizgiyi (ve 0diğer dillerin aksine) koşullu testlerde doğru olarak kabul eder , bu nedenle, örneğin, yazmak yerine, while 1 do ... endyazarak 1 bayt tasarrufwhile''do ... end


(Yükleme hilesi eklendi)
Adriweb

2
0 bir gerçeği değeri olmak sadece saçma
SuperJedi224

başka bir str+0eşdeğer, ~~strönceliği için yararlı olabilir
Felipe Nardi Batista

@FelipeNardiBatista ancak Lua 5.3+ sürümünde desteklenmektedir
Adriweb

5

Ben zaten bir tane düşündüm. Başka dillerde de çalışıp çalışmadığını bilmiyorum ama Lua, işlevleri değişkenlerde saklamanıza izin veren tek şey. Bu nedenle, örneğin string.subprogramınızda birçok kez kullanılıyorsa, örneğin kullanın s=string.sub.


4
Ayrıca Python ve Ruby gibi birçok başka dilde çalışır.
nyuszika7h

4
Javascript ve Haskell de fonksiyon değerlerine sahip olabilir.
Gurur haskeller

Bu, dize değeri içeren herhangi bir değişkene eşittir s=("").subveya buna eşittir . s=a.suba
Egor Skriptunoff

Buna birinci sınıf fonksiyonlar denir
Redwolf Programları

5

Golf oynamak için oldukça ayrıntılı bir dil ... ama akla gelen bazı genel ipuçları:

  • Çünkü çıkarabilseniz kaçının if... then... else... endbüyük bir kaybıdır.
  • Bunun yerine, örneğin daha kısa olan dil yapılarına odaklanmaya çalışın for i=1,5 do.
  • #Operatör oldukça golf için büyük (ve genel olarak) 'dir.

5

Sonsuz döngünüzü kısaltın

Sonsuz bir döngü kullanmanız gerektiğinde, bir kullanmayı düşünebilirsiniz while, ancak bir etiket kullanmak yerine 2 bayt daha kısa:

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

Mümkün olduğunca az yer kullanın

(Ab) kodunuzdan daha fazla boşluk çıkarmak için kullanabileceğiniz basit bir şey var. Lua'nın özellikleri değişkenlere verdiğiniz ad konusunda net: Bir harfle başlamak zorundalar. Bu, bazen, sayılar ve işlevler / değişkenler arasındaki boşlukları atlayabileceğiniz anlamına gelir.

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

Boşluk bırakma olasılığı, sayıyı izleyen harfe bağlıdır, işte size bunu yapmanıza izin vermeyecek harf:

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)

Bunu kullanarak ve değişkenlerinizi nasıl adlandırdığınıza dikkat ederek, kaynak kodlarınızın çoğunu boşluksuz hale getirebilirsiniz.

Zaten burada bir örnek almak ve bu tavsiyeyi kullanmak, işte traş olabileceğiniz bir bayt daha :).

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

Doğru giriş yöntemini kullanın

Her bir ana girdi tipinin kazanına ve maliyetine bakarsak , işte elimizde:

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

Bu yöntemin her biri 1 girdi almamıza izin veriyor, işlev en ağır maliyete sahip (ancak girdi olarak bir tablo almamızı sağlıyor).

Şimdi, komut satırı argümanını kullanmanın golf oynamak istiyorsanız gitmenin yolu olduğunu görebiliyoruz, ancak bunun farkında olun: daha da kısa olabilir

arg[1]
...

...Lua biraz özeldir, bu paketlenmemiş içeriği içeren bir değişken argveya variadic fonksiyonu durumunda ambalajsız parametreleri.

Birden fazla giriş almanız ve her birini kullanmanız gerektiğinde, bunları bir değişkene kaydetmeniz iyi olur. İşte 2 girişi değişkenlere kaydetmenin bazı yolları

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

ve işte değişkenler olmadan yapabileceğiniz en kısa çağrı:

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

3 bağımsız değişkeninizin olduğu noktadan veya 2 bağımsız değişken kullandığınızda, biri iki kez kullanılmışsa, zaten nedeniyle nedeniyle bayt kazanıyorsunuz a,b=...! :)

Neredeyse asla kullanmayın!

İf / elseif / if ifadesinin kullanılmasının üçlü fiyattan daha düşük maliyetli olduğu hiçbir durum yoktur. Böyle bir ifade için kazan çok ağır:

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

Basit bir örnekle, zaten 12 bayt kurtarıyorsunuz, başka şeyler yapmanız gerektiğinde, bu çok daha önemli hale geliyor, bu yüzden bunun farkında olun!

Ayrıca, Lua'daki özel sayılar özeldir , nasıl çalıştıkları konusunda bir şart var, ilgilenenler için, aşağıda açıklayacağım:

Lua'daki üçlüler biçimindedir <condition> and <case true: have to be a true value> or <case false: can be anything>

Her şeyden önce, hadi doğruluk tablosunu görelim or. A or, bir işlev olarak düşünülebilir: her zaman bir değer döndürür, işte döndürdüğü değer:

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

Bu üçlüsümüzü inşa etmemize izin veren şeydi.

andHer zaman dönecektir bize durumunu değerlendirmek için izin ne yolursa x and ydeğerlendirir true.

Bununla ilgili sorun , şart olduğunda geri dönmeyi istiyorsak nilya falseda geri dönmek istiyorsak başarısızlığa uğraması false. Örneğin, aşağıdaki koşulun doğru olmasına rağmen her zaman 5 değerini döndürür.

v = true and false or 5

İşte nasıl çalıştığını açıklamak için bir üçlünün adım adım değerlendirilmesi (bunları yuvalamanız gerektiğinde faydalı olacaktır :))

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

Cevap başına bir ipucu lütfen.
ATaco

"Mümkün olduğunca az yer kullanın" numarasının yalnızca Lua 5.2 ve daha sonraki sürümlerde çalıştığını unutmayın.
Adriweb

4

Ben de birkaç ipucu derledim. Eminim ki bazılarım daha önce belirtilenlerle örtüşecek, ancak onları daha eksiksiz bir cevap oluşturma damarına dahil edeceğim.


Değişkenlere tekrarlanan fonksiyonlar atama

Lua değişkenlere fonksiyon atamanıza izin verir. Tek karakter değişkenleri bile. Bu, işlevi string.sub(x, y)iki defadan fazla tekrarlarsanız, bir değişkene atamaktan faydalanacağınız anlamına gelir .

Bir değişkene atanmadan (69 karakter):

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

Bir değişkene atama (51 karakter):

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

Bunu bir adım öteye götürebileceğin durumlar var. Lua, bir OOP'un aşağıdaki gibi manipülasyon yapmasına izin verir: str:sub(x, y)veya str.sub(x, y)Bu, kodumuz için yeni seçenekler açar. İşleve değişken olarak gösterilen referansı (46 karakter) gösterebilirsiniz.

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

Dizeleri ayrıştırmak için en etkili yolu kullanın

Kendinizi bir fordöngü kullanarak bulabilir ve string.subLua'da karakter karakter yineleme yapmak için bulabilirsiniz . Bazen bu gereksinimlerinize bağlı olarak en iyi şekilde çalışır, ancak diğer zamanlarda string.gmatch daha az karakterle çalışır. İşte ikisine de bir örnek:

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

Ve golf oynadığında, fark daha belirgindir:

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

Beyaz Boşluğu Optimize Etmek İçin Yapılandırma Atama

Lua'da, kapalı bir parantez veya son tırnak işareti ile bir sonraki karakter arasına boşluk karakteri koymanız gerekmez. Şimdiye kadar, bu akılda yeniden yapılanmanın karakterleri keseceği iki durum buldum.

  • Değişken atama:

     x,y=io.read(),0 print(x)
     vs.
     y,x=0,io.read()print(x)
    
  • Eğer İfadeler:

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

Mümkün olan en az sayıda karakteri döndür

Doğru veya yanlış bir değer döndürmeniz gerekiyorsa, dönüş değeri için mutlaka en az 5 karakter kullanmanız gerekir. Gerçekte aşağıdakiler de aynı şekilde çalışır:

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

Harika ipuçları, yayınınıza bir düzenleme önerme özgürlüğünü kullandım. Sadece nilve falsedeğiştirilmesi hakkında ipuçları böylece değerlendirir lua false, her şey doğrudur x==0, x==""ve x==''tarafından xyanlıştır. Şu anda onu değiştiriyorum nil:).
Katenkyo

Ah, haklısın. Bunu düzelttiğin için teşekkürler!
Skyl3r

2

Bunlar sadece Lua (bence) optimizasyonları:

Dizeler, üzerlerinde aritmetik işlemler yaparken otomatik olarak sayılara dönüştürülür. Sadece koşullu ifadelere dikkat edin, bunlar otomatik olarak dönüştürülmez. Bu, yerden tasarruf ederken kullanıcı girdisini sayı olarak almak için mükemmeldir.

İki değişkenin içeriğini değiştirmek geçici bir değişken gerektirmez. a,b=b,aa ve b değerlerini değiştirir.

Ayrıca, yukarıda söylenenleri genişletmek için, herhangi bir alfanümerik karakter alfanümerik olmayan bir karaktere dokunabilir. Öyleyse a,b=io.read():match"(.+)/(.+)"u,v=a,b, boşluksuz olsa bile mükemmel, çalışan bir senaryo.


2

Yerel Değişken Atamaları Birleştir

Yerine:

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

Paralel ödev kullan:

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

Her değişken için 6 bayt kaydedildi!

Kullanılmayan İşlev Parametreleriyle Yerel Değişkenleri Bildirin

Yerine:

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

kullanım

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

6 bayt kaydedildi (kopyalanabilecek her değişken için eksi 1-2 bayt).


1
Reddedildi local, çünkü golf oynarken kullanımın haklı olduğu bir durum yok , çünkü sadece farklı bir isim kullanmak zorundasınız. Yerliler kullanmaktan faydalanabilecek bir şeye çarpmadan önce 7 karaktere kadar TÜM isimleri VE 7 karaktere kadar kombinasyon
dizgili dizgileri olan tabloları kullanabiliriz

1

Variadik İşlevler

Başınızı belaya sokacak temel değişken işlevi print(). Örneğin, boyunca kullandığınızda String.gsub(), değiştirdiğiniz dizeyi VE gsubtetiklenen sayıyı yazdıracaktır .

Bu ikinci çıktının bastırılması için gsub, yalnızca bir değer döndürmeye zorlamak için parenlerinizi kapsülleyin

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

1

Çıktıyı bilmek

Lua’da iki ana çıkış metodu vardır.

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

Birden çok kez birleştirmek zorunda kaldığınızda, bunu kullanarak bunu kısaltabilirsiniz. io.write() , standart birleştirme operatörü yerine bir harf değişkeni..

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

Önceden ödeme yaparken her aramada 2 bayt kazanırsınız

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

Üçüncü bitiştirmede bile konum ve dördüncü kişide bayt kazanmaya başlayın.


3
Öyle printve değil printf!
val diyor Reinstate Monica

@val Wow, bu hatayı nasıl yapabileceğimi bile bilmiyorum. Gösterdiğin için teşekkürler, Düzenleyeceğim
Katenkyo

1

Belirli bir düzende olmayan bir ipucu:

  • stringoldukça uzun bir isim. Verimli, ('').charaynıdır string.char. Değişkenler üzerinde noktalı virgül ile birlikte kullanırsanız daha iyi sonuçlar alınabilir: a=...; print(a:sub(1, 5))ancak bazı stringişlevler dizge olarak girdi almazlar.
  • Lua, çoğu durum için dizeleri ve sayılar arasında otomatik dönüşümü bulunmayan bu yüzden tonumberve+0 genellikle sadece bayt boşa.
  • Her zaman load'your function code here'yerine kullanın function()your function code here end. Access işlevini kullanarak...İçini .
  • Lua'daki bazı string fonksiyonları istenmeyen şekillerde kullanılabilir! Örneğin,a:gsub('.',load'my function') bir dizedeki karakterleri yinelemenin en kısa yolu gibi görünüyor
  • String motor güçlü olsa da, kullanıcı girişini kalıp olarak kullanırken gücüne dikkat edin! Bu nedenle, kullanmanız gerekebilir a:find('.',1,1)(bu sorunu sınamak için %, girişinize çeşitli yerleri dahil etmeyi deneyin ve sonuçları inceleyin). Sayısız fikir, Lua'nın girişi desen olarak ayrıştırmaya çalışması nedeniyle kırıldı.
  • nilüç bayttır, _birdir (sadece büyük olasılıkla bulunmayan rastgele bir isimdir). Ayrıca, herhangi bir basamak truthy değeri olarak çalışacaktır.
  • Mantığınızı ardında bilin x and i or o. Bu sadece bir üçlü operatör değil, tam bir mantıksal ifadedir. Aslında, şu anlama gelir: "eğer xhakikaten, dene i. Eğer x ya da i hatalıysa, o döndür". Yani eğer itruthy değilse, sonuç o. Ayrıca, her ikisi andveya orparçalar ihmal edilebilir ( x and i, x or o).
  • Bir yerine tarafından tamsayı bölme math.floor: 5.3//1==5.0. Lütfen sonuçta elde edilen sayının her zaman bir giriş türünü takip ettiğini unutmayın (tam sayı / değişken).

1
"Ayrıca, herhangi bir rakam truthy değeri olarak çalışacaktır." Sadece C / C ++ arkaplanındaki bazı kodlayıcılar için sezgisel olmayabilecek olan 0 değerini içermek istiyordum.
ouflak
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.