Ecrivez une fonction f
qui prend un entier positif et retourne une fonction.
La nouvelle fonction renvoyée doit être identique à f
. Cependant, lorsque "l'appel de terminaison" se produit, f
doit plutôt renvoyer la somme de tous les entiers passés.
Par exemple, g=f(4)
(si f
est la première fonction) doit être défini g
sur une autre fonction. h=g(3)
va faire la même chose. Cependant, lorsque vous appelez h
sans argument (voir ci-dessous pour plus de détails), il doit générer 7, car c'est la somme des arguments de la fonction précédente. Autrement dit, f(3)(4)() == 7
.
Notez que ce n'est pas la même chose que f(3,4)()
.
"Appel de terminaison" est l’une des options suivantes (à vous de choisir):
- appel sans arguments
- null comme argument
- toute valeur non positive
Une quantité arbitraire d'appels de fonction doit être prise en charge, il n'y a pas de limite prédéfinie.
Il est garanti que la somme totale ne sera pas supérieure à 1'000.
Nous pouvons supposer qu'il y a au moins un appel passé avant "l'appel de terminaison".
Votre code ne doit pas utiliser de variables statiques, par programme. Il doit donc être possible d'exécuter le test plusieurs fois au cours de la même exécution et d'observer exactement le même comportement.
Exemples:
f(1)() == 1
f(4)(2)(7)() == 13
f(4)(2)(7)(5)(2)() == 20
la source
f(4)
renvoie une nouvelle fonction. Si cette nouvelle fonction est appelée sans arguments, elle retourne4
, mais si elle est appelée avec un autre argument, elle retournera à nouveau une nouvelle fonction avec la même sémantique mais avec le nouvel argument ajouté à4
and etc..q = f(2)(3); b = f(1)(2)(3); q(); b()
?Réponses:
JavaScript (ES6), 18 octets
Passez une valeur de fausseté pour récupérer la somme. Les zéros pourraient être autorisés pour un coût de 2 octets.
Essayez-le en ligne
Ungolfed:
la source
Haskell (GHC), 118 octets
Il s'agit de 98 octets pour le code et de 20 octets pour l'indicateur de compilation GHC
-XFlexibleInstances
, qui active une extension de système de types.Ceci définit une "fonction"
f
, qui peut être appelée avec un nombre arbitraire d'entiers suivi de l'unité()
, après quoi elle retourne un entier. Les annotations de type sont obligatoires. Essayez-le en ligne!Explication
Forcer le système de types strict de Haskell à permettre cela nécessite une certaine magie, à savoir l'activation de l'extension GHC pour des instances de classes de types flexibles. Cela fonctionne comme
f
une fonction polymorphe paramétrée restreinte par une contrainte de classe de type: son type estF a => Int -> a
. Cela signifie quef
prend un entier et retourne une valeur de typea
, pour tout typea
appartenant à la classe de typesF
.F
est simplement le nom de la classe de types qui fournit la fonctionf
; c'est déclaré sur la première ligne.Les deux lignes suivantes sont deux instances de
F
types différentsa
. La deuxième ligne indique()
àF
quel type de fonctions de en entiers appartient (où()
est le type d'unité dont le seul membre est la valeur()
), et l'implémentation estf n () = n
; la fonction retourne son premier argument. La dernière ligne indique que sia
appartient àF
, alors le type de fonctions allant d’entiers àa
: à partir d’une fonction,f :: Int -> a
nous pouvons générer une autre fonctionf :: Int -> Int -> a
. L'implémentation est la suivantef m n = f (m+n)
(le code utilise des combinateurs pour le rendre plus court), où le plusf
à gauche est le nouveau et le plusf
à droite est l'ancien. Cela donne essentiellementf
un nouvel argument entier, qui est ajouté au suivant. Plusieurs arguments sont résumés comme suit:Le
f
sur chaque ligne a un type différent.Les fonctions Haskell sont automatiquement configurées, donc si vous
f
ne donnez que des entiers, vous obtenez une fonction.la source
f
, pas une seule fonction qui fait le travail. Cependant, c'est aussi proche que possible de Haskell. Je ne pense pas qu'il soit possible de résoudre la tâche avec une seule fonction à cause du système de types strict.f
, mais un nombre infini de fonctions appeléesf
. (Un pour chaque nombre possible d'arguments.) Ces fonctions (de cette famille infinie) ont deux sortes de définitions: une sorte lorsque le nombre d'arguments est égal à zéro et une autre quand ce n'est pas le cas.f n()=n
etf=(f.).(+)
je l'appellerais donc définir deux fonctions.g 0 = 1
etg n = g (n-1) * n
, où il y a deux définitions mais une seule fonction. Nous avons ici deux définitions mais une infinité de fonctions. (Chacun d'un type différent.)ghci
charge ce qui précède et essaie:t f
- il diraf :: F a => Int -> a
(ce qui signifie que sia
est une instance de classef
, alorsf
est une fonctionInt -> a
). Nous pourrions donc considérer cela comme une fonction ou une infinité d’activités, mais bien qu’il ait deux sortes de définitions (tout comme la fonction factorielle), je ne vois aucune base valable pour considérer qu’il s’agit de deux fonctions.Python 2,
424136 octetsCette solution n'aura jamais de débordement, car Python prend en charge les entiers à précision arbitraire. Zéro est la "valeur spéciale".
Essayez-le en ligne
Ungolfed:
la source
C,
6258 octets, limite en concurrence4 octets sauvés grâce à Kevin! (Vous ne supprimez toujours pas typedef car c'est un élément nécessaire pour pouvoir être appelé.)
La fonction à appeler est
f
; vous arrêtez de l'appeler et obtenez le résultat en l'appelant avec un nombre non positif comme0
. Essayez un test de harnais en ligne!Donc, autant que je sache, le seul moyen de "curry" des fonctions ayant plusieurs types de retour consiste à effectuer l'une des opérations suivantes:
union
/struct
type qui a un sous-typeint
et une fonction / auto-référentielle.J'ai essayé de le faire (2), mais cela semblait un peu contraire à l'esprit de la question et, franchement, presque impossible. Ainsi, dans l’esprit du challenge, j’ai opté pour l’option (1). Cela nécessite de transformer chaque fonction retournée en une fonction, afin qu'elle puisse être utilisée.
Cette syntaxe "currying" semble un peu étrange, mais est assez similaire. Pour imiter
f(21)(1)
, il faudrait écrire((B)((B)f(21))(1))(0)
. J'ai défini leB
type comme étant une fonction qui prend un entier et renvoie un pointeur sur une fonction qui prend un entier. Développé, cela ressemble à:la source
q;f(x){return x?(q+=x,f):q;}
.q
après chaque manche, alors la fonction ne serait plus utilisableMathematica, 25 octets
Essayez-le en ligne! (Utilisation des mathématiques.)
Il est possible de faire trois octets de moins en portant la réponse JavaScript, mais je voulais présenter une solution Mathematica plus idiomatique. C'est
@
juste un peu de sucre syntaxique, ce qui rend la solution équivalente à:Donc, l'idée est que dans Mathematica, vous ne pouvez pas simplement définir une fonction,
f[x_]
mais vous pouvez également associer directement une valeur à une expression plus complexef
, par exemplef[x_]
en passant un autre argument. En définissant deux définitions pour cela, nous pouvons obtenir le comportement souhaité:f[x][y]
appel enf[x+y]
, consommant ainsi un "appel" et ajoutant les arguments à l'intérieur. Cette règle s'applique jusqu'à ce qu'il ne nous reste plusf[sum][]
.sum
.la source
C ++, 72 octets
Ceci définit un type
F
qui agit comme la fonction demandée et une variablef
de ce type à appeler. Il est valable à partir de C ++ 11 et fonctionne avec les versions en ligne de GCC, clang, icc et VC ++.Usage:
Explication:
Après prétraitement et reformatage, il se présente comme suit:
Ceci s’écrirait normalement:
return a;
etreturn {+a};
faites la même chose, car unary+
ne change pas la valeur, et les accolades redondantes autour de la valeur de retour sont autorisées.int m
etint(m)
faire la même chose, car les parenthèses redondantes autour d'un nom de variable sont autorisées, y compris les paramètres de fonction.return {m+a};
etreturn {int(m)+a};
faire la même chose, comme un casting dem
partirint
pourint
ne change pas sa valeur. Ces modificationsoperator()
rapprochent la syntaxe des deux surcharges, permettant ainsi d'invoquer deux fois une même définition de macro. Choisir le bon ordre pour les trois membres permetint
également d'inclure le premier mot de la ligne suivante ( ) dans la définition de macro.la source
operator()
pour faire ce travail était particulièrement cool.Ruby, 23 octets
Usage:
la source
C,
104 à96 octetsUtilise la méthode du lien partagé par @JulianWolf. Le dernier argument doit être 0.
Essayez-le en ligne!
la source
Math.JS, 38 octets
Appelez-le avec
f(number_a)(number_b)(...)(negative_number)
Si nous sommes autorisés à spécifier l'appel initial, vous
f(x)=i(x,0)\n
pouvez supprimer 12 octets ( ) et l'appelez aveci(number_one,0)(number_two)(...)(negative_number)
Essayez le!
Explication
Comme indiqué ci-dessus, LaTex
f(x)
appelle simplementi(x,0)
, puisi(x,y)
renvoie la valeury
if six
est inférieure à 0, ou la fonctionj(z)=i(z,x+y)
qui prend un argument, qui est bouclé. Ajout à la valeur dey
.la source
C,
232206 octetsCela peut probablement être joué de manière significative, mais devrait servir de preuve du concept que C peut être utilisé, sans aucune extension de langage *, pour résoudre ce problème en appelant sans arguments plutôt qu'avec une valeur magique.
* @hvd a noté que, bien que cela fonctionne immédiatement avec gcc, une partie du comportement n'est pas définie dans la norme C, ce qui signifie que cela peut ne pas être portable. À utiliser à vos risques et périls!
Ungolfed:
Compiler et exécuter avec des
gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-currying
sorties (après quelques avertissements)la source
g
eth
à continuer une chaîne d’invocations de macros fonctionne, car il n’est pas précisé si la prochaineg
apparaît dans le contexte de l’extension de la premièreg
. C11 ajoute un exemple à 6.10.3.4 pour préciser qu'il n'est pas spécifié. (IIRC, le préprocesseur de TenDRA en est un qui ne pourrait pas être étendu comme vous le souhaitez.) Hormis cela, aucune version du langage ne prend en charge les arguments de macro vides et les int implicites. Par conséquent, un programme C valide ne peut pas utiliser les deux. :) Toujours, bonne réponse. Cherchez-vous à jouer au golf plus loin?*s
au lieu destrlen(s)
. Les chaînes C ont une longueur implicite et se terminent par unechar
valeur with0
. Nice hack macro pour permettre un appel avec / sans argument!8086 code machine, 27 octets
Ce code machine doit être à l'adresse 0x100 et suppose le modèle de code minuscule (cs = ds = es = ss). L'emplacement de la fonction peut cependant être modifié sans que cela ne coûte des octets supplémentaires. Le mettre en décalage
0
permettrait d'économiser un octet (xor si,si
au lieu demov si, 0x100
)Convention d'appel obligatoire
Cela suppose que l'appelant a pré-alloué au moins 27 octets sur la pile. Il prend un nombre
ax
et renvoie un pointeur de fonctionbx
. L'appel de ce pointeur avecax=0
termine la chaîne et renvoie la somme enbx
.Donc pour le premier appel:
Ensuite, pour chaque appel suivant:
Terminer:
Ungolfed (désassemblage commenté du code machine):
Après avoir appelé cela avec AX non nul,
bx = sp
le tampon est rempli avec une copie modifiée du code machine defunction
. L'instantané 16 bits de la première instruction contient le total. (Il est écrit par la dernière instruction avant leret
.)push di
/pop bx
pourrait être remplacé parmov bx, di
(avantrep movsb
), le rendant plus simple mais pas d'économies.Demander à l'appelant de passer un pointeur sur la mémoire tampon dst
di
permettrait de gagner 4 octets au lieu de le calculer par rapport àsp
.Si l'adresse de début de la fonction est identique à la taille de la fonction, vous économiserez un octet (
mov cx, si
).la source
objdump -b binary
au lieu dehexdump -C
di
(4 octets). Rendre la fonction adresse de départ = taille:mov cx, si
au lieu demov cx, 0x1b
.C #, 62 octets
Pour mettre fin à l’appel, passez un numéro négatif, par exemple
la source
null
ou aucun paramètre à la fin. Cependant, tous les moyens que j'ai essayés étaient beaucoup plus longs!m
place dem<0
et passernull
ou0
comme dernier paramètre?Boolean
peut être utilisé en tant queBoolean
... J'ai essayé avecnull
mais cela a juste pris plus de temps. Je voulais utiliser??
ce qui signifie que si LHS est nul, faire RHS, mais comme j'ai besoin de si LHS n'est pas nul, faire ceci sinon faire RHS, je ne pourrais pas.Scala, 58 caractères
Essayez-le en ligne
Ungolfed:
Explication:
Ce code définit un
case class
f appelé avec un constructeur prenant un int. Définissez une classe de cas qui générera les méthodes equals, hashcode, toString et copy, ainsi qu'un objet compagnon du même nom pour permettre la création d'objet sans lenew
mot clé.Cette classe a une méthode apply surchargée: on prend un autre entier à ajouter et crée un nouvel objet avec la somme mise à jour, et un autre sans arguments pour obtenir la somme.
En Scala, tout objet avec une méthode apply peut être appelé comme une méthode, c'est-à-dire qu'il
o.apply(x)
peut être écrit en tant queo(x)
. Ceci est utilisé dans la bibliothèque standard pour les tableaux, les listes, les cartes et leFunction1
trait implémenté par les fonctions anonymesla source
Pyth, 19 octets
Essayez-le en ligne!
Je suis impressionné par le fait que Javascript bat Pyth, mais là encore, Pyth n'est pas conçu pour passer des fonctions.
la source
Perl 5, 36 octets
la source
-M5.016
? Il semble que vous devriez pouvoir supprimer-M5.016
, puis supprimermy
et enregistrer quelques octets. Si c'est justesay
, vous pouvez utiliser le drapeau à la-E
place, qui ne s'active pasuse strict
, donc vous pouvez toujours laisser tomber lemy
.__SUB__
) mais je l'ai changé avant de soumettre et je n'ai pas supprimé le passage relatif à la version 5.16. Je vais enlever ça. Je ne pense pas que laisser tombermy
serait correct cependant.say
dans le code, c'est à des fins d'illustration)my
sansuse strict
,$n
est implicitement une variable globale. C'est une mauvaise forme dans les scripts Perl appropriés, mais c'est assez courant dans les one-liners, et cela semble fonctionner ici.Brain-Flak , 6 octets
En fait, je viens de remarquer que puisque le type de rapport est un format de retour valide, le 0 n'est pas nécessaire, ce qui permet d'économiser 2 octets:
Essayez-le en ligne!
Soumission (s) originale (s), 8 octets
Utilise
0
comme valeur spéciale:Essayez-le en ligne!
Explication
Étant donné les arguments a 1 , a 2 ,…, a n , 0, la pile ressemble initialement à ceci:
un n
⋮
un 2
un 1
0
Le code continue ensuite, apparaît chaque a i , les accumule, le 0 les ajoute et pousse le résultat:
Solutions alternatives, 8 octets
Au lieu d'afficher le 0 et de l'ajouter à la somme, nous pouvons également échanger les piles puisque la bonne est initialement vide:
Essayez-le en ligne!
En utilisant le
-r
drapeau, le 0 est en haut de la pile, nous pourrions donc le faire apparaître en premier:Essayez-le en ligne!
Essayez-le en ligne!
la source
C (GCC), 83 octets
Mon premier golf C! Il existe deux autres solutions C, mais celle-ci est un peu différente. L'utilisation du préprocesseur est purement cosmétique. Cette approche a été discuté dans la réponse de Conor O'Brien ici .
La valeur terminale est zéro. La valeur de retour est une union, donc pour appeler le résultat, utilisez le champ
f
, et pour accéder à la valeur finale, utilisez le champv
, par exempleEssayez-le en ligne
Limites
Une variable globale contient le total cumulé. Bien que cela soit explicitement interdit, la soumission prend en charge les appels répétés (le total est réinitialisé dans l'appel du terminal), ce qui semble être la raison de l'interdiction de l'état global.
Un pointeur sur
f
est stocké vers l'union retournée par l'intermédiaire duint
membre. Il est donc clair que ce n'est pas portable. Je ne sais pas si cela fonctionne sur GCC sur toutes les plateformes, ni sur Linux, ni sur x86, ni avec ELF ou ... Si quelqu'un connaît des détails à ce sujet, veuillez commenter ou envoyer un message!la source
APL (Dyalog Classic) ,
48474644 32 32 octetsEssayez-le en ligne!
Termine en passant à zéro. Syntaxe d'appel:
((0 f 1) 2) 0
-15 octets grâce à @ngn
A besoin
⎕IO←0
Tous les conseils de golf sont les bienvenus!
la source
:If x<0
de:If×x
et échanger les « si » clauses et « else »r←⍎condition⊃'else' 'then'
Perl 6 , 31 octets
la source
Dyvil , 34 octets
Utilisation :
La fin
()
peut être omis.Explication :
Définit un opérateur de juxtaposition qui prend deux ints et les ajoute. Le paramètre
j
a la valeur par défaut0
pour prendre en charge l'appel sans arguments. Le0
dans les exemples ci-dessus n'est pas le nom, mais un littéral.la source
Julia v0.5 +, 52 octets
Appeler comme
F
. Cela pourrait probablement être beaucoup plus court en adoptant une méthode moins OO, mais j'aime toujours avoir la chance d'utiliser cet idiome.Si on peut supposer qu '"au moins un appel sera passé avant l'appel de terminaison", la deuxième ligne peut être supprimée pour économiser 6 octets.
la source
Julia 0.5 , 18 octets
Essayez-le en ligne!
la source
R, 40 octets
0 agit ici comme la valeur d'arrêt. Pour deux autres octets, nous pouvons l'omettre.
Le problème est que R manque d'un lambda intégré concis. Mais si nous en ajoutons un , nous pouvons obtenir le code à 26 octets :
(Oui, c'est valide R. Il faut juste importer.)
la source
PHP, 44 octets
Une idée de @ user63956
Appel de terminaison
0
Version en ligne
Appel de terminaison avec
NULL
besoin d'un càst[$i]
à[+$i]
PHP, 47 octets
Version en ligne
PHP, 52 octets
Appel de terminaison
NULL
ou toute autre valeur fausse en PHPsi le programme doit se terminer après la sortie, remplacer
print$s
pardie("$s")
+ 2 octetsVersion en ligne
la source
$s
. afin que vous puissiez faire quelque chose commereturn$i?f:$s
à la finfunction f($i){return[$_GET[0]+=$i][$i]?:f;}
.PowerShell, 86 octets
Essayez-le en ligne!
Code de test:
Sortie: 20
la source
$n="$args"
au lieu de$n=$args[0]
. Cela ne fonctionnera pas sur l'autre$args[0]
, cependant, car vous obtiendrez la concaténation de chaînes plutôt que l'addition.Python 3 , 63 octets
Essayez-le en ligne!
Termine avec 0
la source
Python, 69 octets
la source
Octave, 39 octets
* L’argument de l’appel de terminaison est 0.
Essayez-le en ligne!
*
endfunction
requis pour ajouter d'autres codes.la source
R,
5452 octets2 octets sauvés grâce à MickyT!
Semblable à l'une des réponses python. Ungolfed:
Fonctionne comme
la source
f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
return
.return
dans R n'est pas la même que dans d'autres langues, il effectue un abandon prématuré. Ne pas utiliserreturn
est idiomatique. D'autre part votre version non-golfée a toujours le golféif
.if
était de la paresse, maisreturn
c'est juste pour la lisibilité - ça donne le même résultat avec ou sansreturn
.return
diminue la lisibilité, car elle signale la mauvaise chose (sortie prématurée) et constitue un exemple de programmation culte de la cargaison .C ++ (gcc) ,
9591 octetsEssayez-le en ligne!
la source