Schreiben Sie eine Funktion, f
die eine positive Ganzzahl aufnimmt und eine Funktion zurückgibt.
Die zurückgegebene neue Funktion sollte mit identisch sein f
. Wenn jedoch der "Beendigungsaufruf" auftritt, f
sollte stattdessen die Summe aller übergebenen Ganzzahlen zurückgegeben werden.
Zum Beispiel sollte g=f(4)
(wenn f
ist die erste Funktion) auf g
eine andere Funktion eingestellt werden. h=g(3)
werde das gleiche tun. Wenn Sie jedoch h
keine Argumente aufrufen (siehe unten für Details), sollte 7 ausgegeben werden, da dies die Summe der vorherigen Funktionsargumente ist. Anders ausgedrückt f(3)(4)() == 7
.
Beachten Sie, dass dies nicht dasselbe ist wie f(3,4)()
.
"Terminierungsanruf" ist eine der folgenden Optionen (Ihre Wahl):
- Aufruf ohne Argumente
- Null als Argument
- ein nicht positiver Wert
Beliebig viele Funktionsaufrufe sollen unterstützt werden, es gibt kein vordefiniertes Limit.
Es ist garantiert, dass die Gesamtsumme nicht größer als 1'000 sein wird.
Wir können davon ausgehen, dass vor dem "Terminierungsanruf" mindestens ein Anruf getätigt wird.
In Ihrem Code sollten keine statischen programmspezifischen Variablen verwendet werden. Daher sollte es möglich sein, das Experiment mehrere Male in derselben Laufzeit auszuführen und genau dasselbe Verhalten zu beobachten.
Beispiele:
f(1)() == 1
f(4)(2)(7)() == 13
f(4)(2)(7)(5)(2)() == 20
quelle
f(4)
eine neue Funktion zurückgegeben wird. Wenn diese neue Funktion ohne Argumente aufgerufen wird, wird sie zurückgegeben4
. Wenn sie jedoch mit einem anderen Argument aufgerufen wird, wird erneut eine neue Funktion mit der gleichen Semantik zurückgegeben, jedoch mit dem neuen Argument, das dem4
usw. hinzugefügt wurde .q = f(2)(3); b = f(1)(2)(3); q(); b()
?Antworten:
JavaScript (ES6), 18 Byte
Übergeben Sie einen falschen Wert, um die Summe abzurufen. Nullen können für 2 Byte zugelassen werden.
Probieren Sie es online aus
Ungolfed:
quelle
Haskell (GHC), 118 Bytes
Dies sind 98 Byte für den Code und 20 Byte für das GHC-Compiler-Flag
-XFlexibleInstances
, das eine Typsystemerweiterung ermöglicht.Dies definiert eine "Funktion"
f
, die mit einer beliebigen Anzahl von Ganzzahlen aufgerufen werden kann, gefolgt von der Einheit()
, nach der eine Ganzzahl zurückgegeben wird. Typanmerkungen sind erforderlich. Probieren Sie es online!Erläuterung
Damit das strenge Typensystem von Haskell dies zulässt, ist ein gewisses Maß an Magie erforderlich, nämlich die Aktivierung der GHC-Erweiterung für flexible Typklasseninstanzen. Wie dies funktioniert,
f
ist eine parametrisch polymorphe Funktion, die durch eine Typklassenbeschränkung eingeschränkt ist: ihr Typ istF a => Int -> a
. Dies bedeutet, dass für jeden Typ , der zur Typenklasse gehört,f
eine Ganzzahl verwendet und ein Wert vom Typ zurückgegebena
wird . ist nur der Name der Typklasse, die die Funktion bereitstellt ; Es ist in der ersten Zeile deklariert.a
F
F
f
Die nächsten beiden Zeilen sind zwei Instanzen von
F
für verschiedene Typena
. Die zweite Zeile gibt an, dass der Typ der Funktionen von()
bis zu ganzen Zahlen gehörtF
(wobei()
der Einheitentyp ist, dessen einziges Element der Wert ist()
), und die Implementierung istf n () = n
; Die Funktion gibt ihr erstes Argument zurück. Die letzte Zeile besagt, dass, wenn zua
gehörtF
, auch die Art der Funktionen von Ganzzahlen zua
: von einer Funktion könnenf :: Int -> a
wir eine andere Funktion generierenf :: Int -> Int -> a
. Die Implementierung istf m n = f (m+n)
(der Code verwendet Kombinatoren, um sie zu verkürzen), wobeif
links die neue undf
rechts die alte ist. Dies gibt im Wesentlichenf
ein neues ganzzahliges Argument, das dem nächsten hinzugefügt wird. Mehrere Argumente werden folgendermaßen zusammengefasst:Die
f
in jeder Zeile hat einen anderen Typ.Haskell-Funktionen werden automatisch aufgerufen. Wenn Sie also
f
nur Ganzzahlen angeben, erhalten Sie eine Funktion.quelle
f
, und keine einzige Funktion, die die Aufgabe erfüllt. Dies ist jedoch so nah wie Sie in Haskell bekommen können. Ich denke nicht, dass es möglich ist, die Aufgabe mit einer einzigen Funktion zu lösen, da das Typensystem streng ist.f
, sondern unendlich viele aufgerufene Funktionenf
. (Eine für jede mögliche Anzahl von Argumenten.) Diese Funktionen (aus dieser unendlichen Familie) haben zwei Arten von Definitionen, eine Sortierung, wenn die Anzahl der Argumente Null ist, und eine andere, wenn sie nicht ist.f n()=n
undf=(f.).(+)
nenne es zwei definierende Funktionen.g 0 = 1
und definiereng n = g (n-1) * n
, wobei es zwei Definitionen gibt, aber nur eine Funktion. Hier haben wir zwei Definitionen, aber unendlich viele Funktionen. (Jeder von einem anderen Typ.)ghci
das obige laden und versuchen:t f
- es wird sagenf :: F a => Int -> a
(was bedeutet, dass wenna
eine Instanz der Klasse istf
, dannf
ist eine FunktionInt -> a
). Wir könnten dies also entweder als eine Funktion oder als unendlich viele betrachten, aber obwohl es zwei Arten von Definitionen gibt (genau wie die Fakultätsfunktion), sehe ich keine gute Grundlage, um es als zwei Funktionen zu betrachten.Python 2,
424136 BytesDiese Lösung wird niemals überlaufen, da Python Ganzzahlen mit willkürlicher Genauigkeit unterstützt. Null ist der "spezielle Wert".
Probieren Sie es online aus
Ungolfed:
quelle
C,
6258 Bytes, Borderline-Konkurrenz4 Bytes gespart dank Kevin! (Typedef wird immer noch nicht entfernt, da es zum Aufrufen benötigt wird.)
Die aufzurufende Funktion ist
f
; Sie hören auf, es anzurufen, und erhalten das Ergebnis, indem Sie es mit einer nicht positiven Zahl wie aufrufen0
. Probieren Sie ein Testgeschirr online aus!Soweit ich das beurteilen kann, besteht die einzige Möglichkeit, Funktionen mit mehreren Rückgabetypen zu "curryen", darin, eine der folgenden Aktionen auszuführen:
union
/struct
-Typ mit einemint
und -Funktions- / Selbstreferenz-Untertyp.Ich habe versucht (2) zu tun, aber es schien ein bisschen gegen den Geist der Frage und, ganz offen gesagt, fast unlösbar. Aus diesem Grund habe ich mich im Sinne der Herausforderung für Option (1) entschieden. Dazu muss jede zurückgegebene Funktion in eine Funktion umgewandelt werden, die verwendet werden kann.
Diese "currying" Syntax sieht ein bisschen seltsam aus, ist aber ziemlich ähnlich. Um zu emulieren
f(21)(1)
, müsste man schreiben((B)((B)f(21))(1))(0)
. Ich habe denB
Typ als eine Funktion definiert, die eine Ganzzahl annimmt und einen Zeiger auf eine Funktion zurückgibt, die eine Ganzzahl annimmt. Erweitert sieht das so aus:quelle
q;f(x){return x?(q+=x,f):q;}
.q
nach jedem Lauf auf Null gesetzt hätte, wäre die Funktion nicht mehr verwendbarMathematica, 25 Bytes
Probieren Sie es online! (Verwenden von Mathematik.)
Durch Portierung der JavaScript-Antwort können drei Bytes gespart werden, aber ich wollte eine idiomatischere Mathematica-Lösung vorstellen. Das
@
ist nur ein bisschen syntaktischer Zucker, was die Lösung äquivalent macht zu:Die Idee ist also, dass Sie in Mathematica nicht nur eine Funktion definieren,
f[x_]
sondern einem komplizierteren Ausdruckf
, der z. B.f[x_]
ein anderes Argument enthält , direkt einen Wert zuweisen können. Indem wir zwei Definitionen dafür einrichten, können wir das gewünschte Verhalten erhalten:f[x][y]
Aufruf auff[x+y]
einen "Aufruf" und addiert die darin enthaltenen Argumente. Diese Regel gilt, bis wir mit verlassen werdenf[sum][]
.sum
.quelle
C ++, 72 Bytes
Dies definiert einen Typ,
F
der als angeforderte Funktion fungiert, und eine Variablef
dieses Typs, die aufgerufen werden soll. Es ist ab C ++ 11 gültig und funktioniert mit Online-Versionen von GCC, Clang, ICC und VC ++.Verwendungszweck:
Erläuterung:
Nach der Vorverarbeitung und Neuformatierung sieht es so aus:
Dies würde normalerweise geschrieben werden:
return a;
undreturn {+a};
das gleiche tun, als einstellige+
den Wert nicht ändert, und redundante Klammern um den Rückgabewert erlaubt.int m
undint(m)
das gleiche tun, wie redundante Klammern um einen Variablennamen erlaubt sind, einschließlich Funktionsparameter.return {m+a};
undreturn {int(m)+a};
mache dasselbe, da eine Besetzung vonm
vonint
bisint
ihren Wert nicht ändert. Diese Änderungen rücken die beidenoperator()
Überladungen in der Syntax näher zusammen, sodass eine einzelne Makrodefinition zweimal aufgerufen werden kann. Wenn Sie die richtige Reihenfolge für die drei Elemente auswählen, wird auch das erste Wort der nächsten Zeile (int
) in die Makrodefinition aufgenommen.quelle
operator()
, um diese Arbeit zu machen, war besonders cool.Ruby, 23 Bytes
Verwendungszweck:
quelle
C
10496 BytesVerwendet die Methode aus dem Link, den @JulianWolf freigegeben hat. Das letzte Argument muss 0 sein.
Probieren Sie es online!
quelle
Math.JS, 38 Bytes
Nennen Sie es mit
f(number_a)(number_b)(...)(negative_number)
Wenn wir den ersten Aufruf angeben dürfen, können 12 Bytes (
f(x)=i(x,0)\n
) verworfen und mit aufgerufen werdeni(number_one,0)(number_two)(...)(negative_number)
Versuch es!
Explination
Wie in obigem LaTex gezeigt,
f(x)
ruft es einfach aufi(x,0)
und gibt danni(x,y)
den Wert vony
ifx
kleiner als 0 oder die Funktion zurückj(z)=i(z,x+y)
, die ein Argument annimmt und die eine Schleife durchläuft. Addieren zum Wert vony
.quelle
C
232206 BytesDies kann wahrscheinlich erheblich verbessert werden, sollte jedoch als Beweis dafür dienen, dass C ohne Spracherweiterungen * verwendet werden kann, um dieses Problem durch Aufrufen ohne Argumente und nicht mit einem magischen Wert zu lösen.
* @hvd hat festgestellt, dass dies zwar mit gcc funktioniert, einige Verhaltensweisen jedoch nicht im C-Standard definiert sind, was bedeutet, dass dies möglicherweise nicht portabel ist. Benutzung auf eigene Gefahr!
Ungolfed:
Kompilieren und Ausführen mit
gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-currying
Ausgaben (nach einigen Warnungen)quelle
g
undh
diese fortzusetzen, funktioniert nicht unbedingt, da nicht festgelegt ist, ob die nächsteg
im Kontext der Erweiterung der ersten stehtg
. C11 fügt ein Beispiel zu 6.10.3.4 hinzu, um zu verdeutlichen, dass es nicht spezifiziert ist. (IIRC, der Präprozessor von TenDRA, lässt sich nicht beliebig erweitern.) Außerdem unterstützt keine Sprachversion sowohl leere Makroargumente als auch implizites int, sodass ein gültiges C-Programm nicht beide verwenden kann. :) Trotzdem schöne Antwort. Möchten Sie weiter Golf spielen?*s
anstelle von auf die leere Zeichenfolge testenstrlen(s)
. C-Zeichenfolgen haben implizite Länge und werden mit einemchar
mit Wert abgeschlossen0
. Netter Makro-Hack, um einen Aufruf mit / ohne Argument zuzulassen!8086 Maschinencode, 27 Bytes
Dieser Maschinencode muss an der Adresse 0x100 sein und setzt das winzige Codemodell (cs = ds = es = ss) voraus. Der Funktionsort kann jedoch geändert werden, ohne dass zusätzliche Bytes anfallen. Wenn Sie den Wert auf Offset setzen
0
, wird ein Byte (xor si,si
anstelle vonmov si, 0x100
) gespeichert.Erforderliche Anrufkonvention
Dies setzt voraus, dass der Aufrufer mindestens 27 Bytes auf dem Stapel vorab zugewiesen hat. Es nimmt eine Zahl in
ax
und gibt einen Funktionszeiger in zurückbx
. Der Aufruf dieses Zeigers mitax=0
beendet die Kette und gibt die Summe in zurückbx
.Also für den ersten Anruf:
Dann für jeden nachfolgenden Anruf:
Zu beenden:
Ungolfed (kommentierte Demontage des Maschinencodes):
Nach dem Aufruf mit AX ungleich Null wird
bx = sp
der Puffer mit einer geänderten Kopie des Maschinencodes von gefülltfunction
. Das 16-Bit-Direkt in der ersten Anweisung enthält die Summe. (Es ist von der letzten Anweisung vor dem geschriebenret
.)push di
Ichpop bx
könnte durchmov bx, di
(vorherrep movsb
) ersetzt werden, was es einfacher macht, aber keine Einsparungen bringt.Wenn der Aufrufer einen Zeiger an den dst-Puffer übergeben muss
di
, werden 4 Bytes gespart, verglichen mit der Berechnung in Bezug aufsp
.Wenn Sie die Startadresse der Funktion auf die gleiche Größe wie die Funktionsgröße einstellen, wird ein Byte (
mov cx, si
) gespeichert .quelle
objdump -b binary
statthexdump -C
di
(4 Byte) übergeben. Stellen Sie die Funktion Startadresse = Größe:mov cx, si
stattmov cx, 0x1b
.C #, 62 Bytes
Um den Anruf zu beenden, geben Sie eine negative Nummer ein, z
quelle
null
keine Parameter übergebe oder beende. Alle!m
stattm<0
und übergebennull
oder0
als letzten Parameter verwenden?Boolean
kann eingesetzt werden , werdenBoolean
... Ich habe versucht , mitnull
aber es hat nur länger. Ich wollte benutzen,??
was bedeutet, wenn LHS null ist, mache RHS, aber da ich brauche, wenn LHS nicht null ist, mache ich dies, sonst mache ich RHS, ich konnte nicht.Scala, 58 Zeichen
Probieren Sie es online aus
Ungolfed:
Erläuterung:
Dieser Code definiert ein
case class
aufgerufenes f, wobei ein Konstruktor ein int übernimmt. Definieren Sie eine Case-Klasse, die die Methoden equals, hashcode, toString und copy generiert, und ein Begleitobjekt mit demselben Namen, um die Objekterstellung ohne dasnew
Schlüsselwort zu ermöglichen .Diese Klasse verfügt über eine überladene Apply-Methode: Eine verwendet eine andere Ganzzahl zum Hinzufügen und erstellt ein neues Objekt mit der aktualisierten Summe und eine ohne Argumente zum Abrufen der Summe.
In Scala kann jedes Objekt mit einer apply-Methode wie eine Methode aufgerufen werden, dh wie folgt
o.apply(x)
geschrieben werdeno(x)
. Dies wird in der Standardbibliothek für Arrays, Listen, Maps und dieFunction1
von anonymen Funktionen implementierten Merkmale verwendetquelle
Pyth, 19 Bytes
Probieren Sie es online!
Ich bin beeindruckt, dass Javascript Pyth schlägt, aber andererseits ist Pyth nicht so konzipiert, dass es Funktionen übergibt.
quelle
Perl 5, 36 Bytes
quelle
-M5.016
? Es scheint, als ob Sie in der Lage sein sollten , ein paar Bytes zu löschen-M5.016
und dann auch zu löschenmy
und zu speichern. Wenn es nur so istsay
, können Sie-E
stattdessen die Flagge verwenden, die nicht aktiviert wirduse strict
, sodass Sie die immer noch ablegen könnenmy
.__SUB__
), aber ich habe das vor dem Absenden geändert und das Bit über 5.16 nicht entfernt. Ich werde das entfernen. Ich denke nicht, dass das Fallenlassenmy
richtig wäre.say
als Teil des Codes, es ist nur zur Veranschaulichung)my
ohne entfernenuse strict
,$n
ist implizit eine globale Variable. Es ist eine schlechte Form in richtigen Perl-Skripten, aber in Einzeiler-Skripten ziemlich häufig, und es scheint hier zu funktionieren.Brain-Flak , 6 Bytes
Eigentlich ist mir gerade aufgefallen, dass, da der ToS ein gültiges Rückgabeformat ist, das Poppen der 0 nicht wirklich benötigt wird, was 2 Bytes spart:
Probieren Sie es online!
Ursprüngliche Einreichung (en), 8 Bytes
Verwendet
0
als Sonderwert:Probieren Sie es online!
Erläuterung
Mit den Argumenten a 1 , a 2 ,…, a n , 0 sieht der Stack zunächst so aus:
a n
⋮
a 2
a 1
0
Der Code geht dann auf, jede erscheint ein i , sammelt sie, springt der 0 fügt sie und legt das Ergebnis:
Alternative Lösungen, 8 Bytes
Anstatt die 0 zu platzieren und zur Summe hinzuzufügen, können wir auch die Stapel tauschen, da der rechte anfänglich leer ist:
Probieren Sie es online!
Mit dem
-r
Flag befindet sich die 0 oben auf dem Stapel, so dass wir sie zuerst platzieren können:Probieren Sie es online!
Probieren Sie es online!
quelle
C (GCC) 83 Bytes
Mein erstes C Golf! Es gibt ein paar andere C-Lösungen, aber diese sind etwas anders. Die Verwendung von Präprozessoren ist rein kosmetisch. Dieser Ansatz wurde zuerst in der Antwort von Conor O'Brien hier erörtert .
Der Endwert ist Null. Der Rückgabewert ist eine Vereinigung. Um das Ergebnis aufzurufen, verwenden Sie das Feld
f
, und um auf den Endwert zuzugreifen, verwenden Sie das Feldv
, zProbieren Sie es online
Einschränkungen
Eine globale Variable enthält die laufende Summe. Dies ist zwar ausdrücklich untersagt, die Übermittlung unterstützt jedoch wiederholte Aufrufe (die Gesamtsumme wird im Terminalaufruf zurückgesetzt), was der Grund für das Verbot des globalen Staates zu sein scheint.
Ein Zeiger auf
f
wird über dasint
Mitglied in der zurückgegebenen Union gespeichert , sodass dies eindeutig nicht portierbar ist. Ich bin mir nicht sicher, ob dies auf GCC auf allen Plattformen oder nur auf Linux oder nur auf x86 oder nur mit ELF oder ... funktioniert.quelle
APL (Dyalog Classic) ,
48474644 32 BytesProbieren Sie es online!
Beendet durch Übergabe von Null. Aufrufsyntax:
((0 f 1) 2) 0
-15 Bytes dank @ngn
Benötigt
⎕IO←0
Alle Golftipps sind willkommen!
quelle
:If x<0
zu:If×x
und tauschen Sie die „if“ und „else“ Klauselnr←⍎condition⊃'else' 'then'
Perl 6 , 31 Bytes
quelle
Dyvil , 34 Bytes
Verwendung :
Das Nachziehen
()
kann weggelassen werden.Erklärung :
Definiert einen Nebeneinanderstellungsoperator, der zwei Ints benötigt und diese hinzufügt. Der Parameter
j
hat den Standardwert0
, um den Aufruf ohne Argumente zu unterstützen. Das0
in den obigen Beispielen ist nicht der Name, sondern ein Literal.quelle
Julia v0.5 +, 52 Bytes
Anrufen als
F
. Dies könnte wahrscheinlich durch die Anwendung einer weniger OO-Methode erheblich verkürzt werden, aber ich mag es immer, die Chance zu bekommen, diese Redewendung zu verwenden.Wenn davon ausgegangen werden kann, dass "mindestens ein Anruf vor dem Beendigungsanruf getätigt wird", kann die zweite Zeile entfernt werden, um 6 Bytes zu sparen.
quelle
Julia 0,5 , 18 Bytes
Probieren Sie es online!
quelle
R, 40 Bytes
0 fungiert hier als Stoppwert. Für zwei weitere Bytes können wir es weglassen.
Das Problem ist, dass R ein knappes eingebautes Lambda fehlt. Aber wenn wir eins hinzufügen , können wir den Code auf 26 Bytes bringen :
(Ja, das ist gültig R. Es muss nur importiert werden.)
quelle
PHP, 44 Bytes
Eine Idee von @ user63956
Kündigungsruf
0
Online Version
Termination Anruf mit
NULL
benötigen einen CAST[$i]
zu[+$i]
PHP, 47 Bytes
Online Version
PHP, 52 Bytes
Abbruchaufruf
NULL
oder ein anderer Wert, der in PHP falsch istWenn das Programm nach der Ausgabe beendet werden muss, ersetzen Sie es
print$s
durchdie("$s")
+ 2 BytesOnline Version
quelle
$s
. so etwas könnte manreturn$i?f:$s
am Ende machenfunction f($i){return[$_GET[0]+=$i][$i]?:f;}
.PowerShell, 86 Byte
Probieren Sie es online!
Testcode:
Ausgabe: 20
quelle
$n="$args"
anstelle von$n=$args[0]
. Auf der anderen Seite wird es jedoch nicht funktionieren$args[0]
, da Sie dann eher eine Zeichenfolgenverkettung als eine Addition erhalten.Python 3 , 63 Bytes
Probieren Sie es online!
Beendet mit 0
quelle
Python, 69 Bytes
quelle
Oktave, 39 Bytes
* Argument des Beendigungsaufrufs ist 0.
Probieren Sie es online!
*
endfunction
erforderlich, um weitere Codes hinzuzufügen.quelle
R,
5452 Bytes2 Bytes gespart dank MickyT!
Ähnlich wie bei einer der Python-Antworten. Ungolfed:
Läuft als
quelle
f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
return
.return
in R ist nicht dasselbe wie in anderen Sprachen, es führt einen vorzeitigen Abbruch durch. Nichtbenutzungreturn
ist idiomatisch. Auf der anderen Seite hat Ihre ungolfed Version immer noch den Golfif
.if
war faul , aber derreturn
dient nur der Lesbarkeit - er gibt das gleiche Ergebnis mit oder ohnereturn
.return
die Lesbarkeit beeinträchtigt, weil es das Falsche signalisiert (vorzeitiges Verlassen) und ein Beispiel für die Programmierung von Frachtkult ist .C ++ (GCC) ,
9591 BytesProbieren Sie es online!
quelle