Gibt es eine Möglichkeit, Fettpfeilfunktionen zu verkürzen?

15

Nach dem, was ich während meiner Zeit bei PPCG gesehen habe, handelt es sich bei den meisten JavaScript-Einträgen mit Fettpfeil-Funktionen in der Regel um eines von zwei Camps:

  1. Die einfachen, die in der Lage sind, als eine einzige Aussage zu laufen und eine Antwort direkt von der Fledermaus zurückzusenden, mögen x=(a,b)=>a*a+b

  2. Die komplexeren, die normalerweise geschweifte Klammern haben, weil Schleifen verwendet werden und daher die Verwendung einer returnAnweisung erfordern .. wiep=b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}

Nehmen wir das obige Beispiel aus Kategorie 2 mit dem Konzept der geschweiften Klammern als Proof-of-Concept ... Gibt es eine Möglichkeit, diesen Code (oder einen ähnlichen) so erneut zu spielen, dass sowohl die geschweiften Klammern als auch die geschweiften Klammern entfernt werden return? Ich frage dies nur, da dies potenziell (ohne zu sagen, dass dies die ganze Zeit passieren wird) 8 Bytes aus dem Code eines JS-Golfers eliminieren könnte. Gibt es Techniken, die man in diesem Fall verwenden könnte? Ich habe es mit Rekursion versucht, aber die m=bAussage hat sich als Bugbear erwiesen, da ich sie scheinbar nicht erschüttern kann.

Wie würde man mit dem obigen Code weiter Golf spielen, um die returnAussage zu eliminieren , unabhängig davon, ob es kürzer ist oder nicht?

WallyWest
quelle

Antworten:

18

Rekursion verwenden

Ich habe festgestellt, dass die Rekursion (fast) immer kürzer als eval+ ist for. Der allgemeine Weg von for nach eval zu konvertieren ist:

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

Sehen wir uns also Ihr Beispiel an:

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

Wir können es zunächst vereinfachen, um:

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

Was haben wir hier gemacht? Nun, wir haben einfach alles innerhalb der forAnweisung verschoben. Dies hilft uns, die Semikolonmenge zu reduzieren, was nicht direkt besser ist, aber fast immer zu etwas Golf führt.


Lassen Sie uns dies auswerten und mit der Rekursionsversion vergleichen:

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)

Im ersten Teil der for-Schleife ( a=n) können wir dies beginnen, indem wir diese Variablen als Argumente übergeben. Die Bedingung ist einfach: b?(c,f(a)):dWo dist der Rückgabewert. cÄndert sich normalerweise nur, adamit es darin zusammengeführt werden kann. So können wir noch mehr Golf spielen mit dem, was ich erwähnt habe:

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

Das heißt, wie von @Niel bemerkt, vereinfacht Ihren Algorithmus. Ein Algorithmus, der in einer Sprache Golf spielt, ist möglicherweise nicht in einer anderen Sprache Golf. Probieren Sie daher verschiedene Algorithmen aus und vergleichen Sie sie.

Downgoat
quelle
1
Sie haben eine große Einsparung bei der Vereinfachung des Originalcodes verpasst. ~-mist m-1, so kann die Schleife sein for(m=b,a=1;--m;a*=m*m)a%b;und die rekursive Version kann sein (ungetestet)b=>(f=a=>--m?f(a*=m*m):a%b)(1,m=b)
Peter Taylor
1
Manchmal muss man nur einen anderen Algorithmus verwenden, aber in diesem Fall war das Beste, was ich tun konnte, die gleiche Länge wie @ PeterTaylors Antwort:b=>b>1&(f=a=>--a<2||b%a&&f(a))(b)
Neil,
11

Missbrauch bewerten.

Es ist einfach. Anstatt von:

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

Verwenden

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

Eval gibt die zuletzt ausgewertete Anweisung zurück. In diesem Fall würden c+=nwir , da die letzte ausgewertete Anweisung wäre , cohnehin zwei Bytes einsparen.

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

Allgemein:

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

ist um ein Byte kürzer als dieses:

f=n=>{code;return x}

Hinweis: Das Aufrufen von eval mit graves, um möglicherweise Bytes zu speichern, funktioniert nicht, da:

eval`string`

ist äquivalent zu

["string"]

Hilfreich zur Verschleierung! Nicht so sehr für Code Golf.

Conor O'Brien
quelle
2
foo`string`ist immer gleichbedeutend mit foo(["string"]), es ist nur so, dass viele Funktionen das Array dann in den gewünschten String zurücksetzen.
Neil
@ Neil Oh, wie interessant!
Conor O'Brien