Yağ-ok işlevlerini kısaltmanın bir yolu var mı?


15

Burada PPCG'de geçirdiğim kadarıyla, yağ ok işlevlerini içeren JavaScript girişlerinin çoğu iki kamptan biri olma eğilimindedir:

  1. Tek bir ifade olarak çalışabilen ve bir cevap döndüren, yarasadan çıkabilen basit olanlar, x=(a,b)=>a*a+b

  2. Döngülerin kullanımı nedeniyle genellikle kıvırcık parantezleri olan ve bunun sonucunda bir returnifadenin kullanılmasını gerektiren daha karmaşık olanlar.p=b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}

Yukarıdaki örneği, konsept kanıtı olarak kıvırcık parantez konseptiyle almak ... Kıvırcık parantezleri de ortadan kaldırmak için bu kodu (veya benzerlerini) yeniden golf oynamak için bir yol olabilir mi return? Ben sadece bu potansiyel olarak (bu her zaman olacağını söyleyerek değil) bir JS golfçü kodundan 8 bayt ortadan kaldırmak gibi soruyorum . Bu örnekte kullanılabilecek teknikler var mı? Özyinelemeyi denedim, ancak m=bifadeyi sallayamıyorum gibi bir böcek gibi biraz kanıtlandı.

Yukarıdaki kod için, bir golf daha returnkısa golf ya da değil golf ne olursa olsun , açıklama ortadan kaldırmak için ?

Yanıtlar:


18

Özyineleme Kullan

Özyinelemenin (neredeyse) her zaman eval+ ' dan daha kısa olduğunu gördüm for. İçin eval için dönüştürmek için genel yolu:

for(a=n;b;c);d
(f=a=>b?f(c):d)(n)

Şimdi örneğinizi görelim:

b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}

İlk önce basitleştirebiliriz:

for(m=b,a=1;~-m;--m,a*=m*m)a%b;

Burada ne yaptık? Her şeyi basitçe forifadenin içine taşıdık, bu da doğrudan daha iyi olmayan ancak neredeyse her zaman bazı golflere yol açan noktalı virgül miktarını azaltmamıza yardımcı oluyor.


Bunu eval'e koyalım ve özyineleme sürümüyle karşılaştıralım:

b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}
b=>eval('for(m=b,a=1;~-m;--m,a*=m*m)a%b')
b=>(f=a=>~-m?(--m,f(a*=m*m)):a%b)(1,m=b)

For loop ( a=n) ' un ilk kısmı, bu değişkenleri argüman olarak ileterek başlayabiliriz. Koşul basitçe: dönüş değeri b?(c,f(a)):dnerede d. Genellikle cdeğiştirilir, aböylece birleştirilebilir. Bahsettiğim şeyi kullanarak daha da golf oynayabiliriz:

b=>(f=a=>~-m?(--m,f(a*=m*m)):a%b)(1,m=b)
b=>(f=a=>~-m?f(a*=--m*m):a%b)(1,m=b) // --m moved into a*=
b=>(f=a=>--m?f(a*=m*m):a%b)(1,m=b) // --m moved to condition

Bununla birlikte, @Niel tarafından belirtildiği gibi algoritmanızı basitleştiriyor. Bir dilde golf olan bir algoritma başka bir dilde golfy olmayabilir, bu nedenle farklı algoritmaları denediğinizden emin olun.


1
Orijinal kodun basitleştirilmesinde büyük bir tasarruf kaçırdınız. ~-m, m-1döngü olabilir for(m=b,a=1;--m;a*=m*m)a%b;ve özyinelemeli sürüm olabilir (denenmemiş)b=>(f=a=>--m?f(a*=m*m):a%b)(1,m=b)
Peter Taylor

1
Bazen sadece farklı bir algoritma kullanmanız gerekir, ancak bu durumda yapabileceğim en iyi şey @ PeterTaylor'un cevabı ile aynı uzunluktaydı:b=>b>1&(f=a=>--a<2||b%a&&f(a))(b)
Neil

11

Kötüye kullanım değerlendirmesi.

Basit. Onun yerine:

f=n=>{for(i=c=0;i<n;i++)c+=n;return c}

kullanım

f=n=>eval("for(i=c=0;i<n;i++)c+=n;c")

Eval son değerlendirilen ifadeyi döndürür. Bu durumda, son değerlendirilen ifade olacağından c+=n, cher iki durumda da, iki bayt tasarruf edeceğiz .

f=n=>eval("for(i=c=0;i<n;i++)c+=n")

Genel olarak:

f=n=>eval("code;x")

bir bayt ile bundan daha kısadır:

f=n=>{code;return x}

Bir not olarak, muhtemelen baytları kurtarmak için eval'i çağırmak için mezar kullanmak işe yaramaz, çünkü:

eval`string`

eşittir

["string"]

Şaşkınlık için faydalı! Kod golf için çok fazla değil.


2
foo`string`her zaman eşdeğerdir foo(["string"]), sadece birçok işlev diziyi istenen dizeye geri döndürür.
Neil

@Neil Oh, ne kadar ilginç!
Conor O'Brien
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.