En utilisant la langue de votre choix, écrivez une fonction qui prend un nombre variable d’arguments et renvoie le nombre d’arguments avec lesquels elle a été appelée.
Détails:
- Votre langue doit prendre en charge des fonctions d’argument variadique: un objet appelable qui prend un nombre arbitraire d’arguments et renvoie une valeur.
- Les paramètres doivent pouvoir être passés individuellement. Cela signifie que passer un tableau ne compterait que pour un paramètre. Vous pouvez utiliser un tableau "tous les arguments passés" si votre langue le supporte; la restriction est sur la façon dont la fonction est appelée.
- Le code qui appelle cette fonction ne doit pas être obligé de transmettre le nombre d'arguments dans son source . Si un compilateur insère le nombre d'arguments dans le cadre d'une convention d'appel, cela est autorisé.
- Les arguments peuvent être de tout type que vous voulez. Vous ne pouvez prendre en charge qu'un seul type (par exemple, seule la prise en charge
int
est toujours valide), des types arbitraires (tout type d'argument est autorisé) ou toute combinaison de types d'arguments (par exemple, le premier argument estint
, restes sont des chaînes). - Votre fonction peut avoir un nombre maximum d'arguments (surtout depuis que les ressources sont finies), mais doit supporter au moins 2 arguments.
Échantillons:
f()
résultats0
f(1)
ouf("a")
retourne1
f([1, 2, 3])
retourne1
comme un tableau, pas 3 argumentsf(1, 10)
ouf(1, "a")
retourne2
S'agissant de code-golf, la solution gagnante est celle qui utilise le moins d'octets.
Réponses:
Appel binaire Amstrad CPC Z80 de BASIC, 1 octet, codé en hexadécimal
(Également versions 2 et 5 octets, voir ci-dessous)
Lors de l'entrée dans l'appel, le nombre de paramètres transmis sera dans le
A
registre. Le code revient simplement immédiatement. Il n'y a pas de concept de valeurs de retour dans le Z80, juste des états d'entrée et de sortie. La valeur est simplement "là" accessible dans le registre puisque le code ne modifie aucune condition d'entrée, sauf pourPC
(le compteur de programme) etSP
(le pointeur de pile). Cependant, la valeur deA
n'est pas accessible à BASIC et est écrasée presque immédiatement.Exemples:
A
= 2A
= 1A
= 0Sur demande, voici un code rendant la valeur accessible en BASIC. J'ai été très surpris de constater que cela pouvait être fait en seulement 5 octets !:
Le code machine:
En entrée:
AF
- les registres d'accumulateur et de drapeaux (traités comme deux registres de 8 bits)A
contient le nombre de paramètres passés, jusqu'à un maximum de 32 paramètresF
. Il semble que tous les indicateurs RESET soient réinitialisés0
, à l'exception des deux indicateurs non définis qui sont tous les deux1
. L'Z
indicateur (zéro) est réglé sur SET1
si aucun paramètre n'a été transmisBC
B
- 32 moins le nombre de paramètres (A
+B
= 32)C
-&FF
DE
- L'adresse du dernier paramètre ou l'adresse du demandeur si aucun paramètre n'a été passéHL
- l'adresse du premier octet après l'exécution de la commande BASIC à jeton (soit en tant que programme, soit en mode de commande immédiate)IX
- l'adresse de pile du pointeur sur le dernier paramètreIY
-&0000
Le code
L
oaD
l'adresse indiquée parDE
avec la valeur dansA
INC
rementsDE
XOR
sA
(avecA
), donnant&00
L
oaD
la valeurA
de l'adresse indiquée parDE
RET
urnesEn sortie:
A
est détruit (c'est toujours&00
)DE
est détruit (il est toujours supérieur à l'entrée)Les bases
Amstrad basic n'a que trois types de données, plus des tableaux simples. Par défaut, toutes les variables BASIC sont REAL (signées, mantisse 32 bits, exposant 8 bits), qui peuvent être explicites avec
!
. Pour une utilisation INTEGER (signée, 16 bits)%
et pour une chaîne STRING (longueur de chaîne sur 1 octet, données caractères jusqu'à 255 octets, sécurité binaire), utilisez$
:x
- REAL (implicite)x!
- REAL (explicite)x%
- INTEGERx$
- CHAÎNEVous pouvez également utiliser
DEFINT
,DEFREAL
etDEFSTR
avec une seule lettre, ou une plage de deux lettres simples pour spécifier le type par défaut de toutes les variables commençant par cette lettre, similaire à FORTRAN.DEFSTR a
DEFINT x-z
À présent:
a
- STRING (implicite)i
- REAL (implicite)x
- INTEGER (implicite)x$
- STRING (explicite)Le type le plus facile à utiliser est le nombre entier. Le code machine attend que le dernier paramètre soit transmis par adresse, et non par valeur, raison
@
pour laquelle la variable est préfixée. La variable de retour est comptée comme un desCALL
paramètres.Le code machine est appelé comme suit à partir de BASIC (en supposant qu’il soit chargé en mémoire à l’adresse
&8000
):n%
= 4Cela donnera toujours le résultat correct, quelle que soit la valeur initiale de
n%
.Pour une version à 2 octets qui conserve tous les registres d'entrée:
n%
= 4Ce saute les trois premiers octets, et ne donne que le résultat correct si la valeur initiale
n%
est0
-255
. Cela fonctionne parce que le Z80 est un peu endian.Le paramètre de retour doit être initialisé avant d’être passé, sinon BASIC renverra une
Improper argument
erreur. Dans l'image ci-dessous, je suis en?
train d' imprimer (avec le raccourci depuis que j'ai aussi joué à la démonstration!) Les valeurs de retour immédiatement avant et après l'appel pour montrer que la valeur change. J'utilise la valeur&FFFF
parce que c'est la représentation binaire de-1
pour un entier signé. Cela montre que le programme de 5 octets écrit correctement les deux octets, alors que le programme de 2 octets n'écrit que l'octet de poids faible et suppose que l'octet de poids fort existe déjà&00
.la source
A
, si c'est le cas. comment vous pourriez réellement le faire à partir de BASIC). Cela n’est pas faux, mais il serait peut-être plus intéressant de suivre une convention d’appel existante.A
est la même immédiatement après l'RET
instruction. La durée de vie d'une valeurA
est très courte car c'est l'accumulateur. Il n'y a rien de tel quex = CALL &8000, 42
. Il faudrait que ce soitCALL &8000, x, 42
un code Z80 supplémentaire, mais cex
ne serait2
pas le cas1
.&00
s -NOP
no-ops. Un autre octet peut être ajouté pour le rendre plus sûr, mais bien sûr, sans paramètre de retour, il ne peut rien définir.Java (JDK 10) , 11 octets
Essayez-le en ligne!
la source
interface x{void f(Object...a);}
pour être défini, et ce lambda doit être soit stocké dans une variable de ce type d'interface, soit être passé à une méthode qui attend ce type d'interface, donc je ne suis pas vraiment sûr que cela compte pour ce défi (même java lambdas sont généralement autorisés dans les challenges codegolf)JavaScript, 15 octets
La
Array.prototype.push
fonction prend un nombre quelconque d'arguments, les ajoute à son tableau et retourne la taille du tableau. Par conséquent, lapush
fonction utilisée sur un tableau vide renvoie le nombre d'arguments fournis àpush
.Le
.bind(0)
donne simplement à lapush
fonction unethis
valeur fixe pour pouvoir la stocker dans une variable. En fait, l'identifiant à 7 octets[].push
peut être utilisé littéralement (mais non attribué) sansbind
:la source
JavaScript (ES6), 16 octets
Afficher l'extrait de code
la source
Haskell ,
1081079594 octetsEssayez-le en ligne!
C'était étonnamment difficile à faire fonctionner, mais je me suis amusé à essayer de trouver comment implémenter quelque chose de trivial dans des langages impératifs.
la source
f
est optionnel si vous ditesz 0
est la fonction sans la liaison,main = print $ ((z 0) pi 0 () [] :: Int)
fonctionne donc .z 0
::Int
devrait être compté dans le nombre d'octets, car le type de réponse doit être déclaré tôt ou tard, comme dansmain = print $ ((z 0 :: Double -> Integer -> () -> [a] -> (Int->Int->Int) -> IO () -> Int) pi 0 () [] (+) main)
. Je pense aussi que cela ne fonctionne que pendant le temps de compilation, donc quelque chose commefoldl(\a b->a b) (z 0) $ [1..5])::Int
ne peut pas fonctionner. Quoi qu'il en soit, c'est génial.s/imperative/non-curry/
Python 3 , 15 octets
Essayez-le en ligne!
la source
Zsh ,
75 octetsEssayez-le en ligne!
la source
f(){ echo $#; }
Brain-Flak , 6 octets
Ma première solution Brain-Flak digne d'être publiée, je suppose que c'est le bon outil pour ce travail:
Essayez-le en ligne!
Explication
Lors de l'exécution d'un programme Brain-Flak, la pile de gauche contient initialement tous les arguments. À partir de là, c'est simplement une question de:
la source
Wolfram Language (Mathematica) , 11 octets
Essayez-le en ligne!
Proposé par JungHwan Min. Certaines restrictions (l'entrée doit être rectangulaire) mais nous ne sommes pas obligés de gérer une entrée arbitraire.
11 octets
Essayez-le en ligne!
Une autre solution de 11 octets suggérée par Martin Ender. Cela semble être une erreur s’il n’ya pas une entrée, mais renvoie toujours la valeur correcte dans tous les cas.
12 octets
Essayez-le en ligne!
Ma solution d'origine.
Dans Mathematica
##
, un nombre variable d’arguments est défini dans une fonction.{
et les}
enroule dans une liste etLength@
prend la longueur de cette liste.&
à la fin, cela devient une fonction réelle.la source
R , 30 octets
Essayez-le en ligne!
la source
function(...)nargs()
est de 20 octets, mais l’utilisationlength(...)
était ma première approche jusqu’à googler unenargs
fonction similaire.list(...)
en logique poursum()
pouvoir l'utiliser, mais c'est délicat: /...length()
fait la même chose quelength(list(...))
Bash, 12 octets (merci à paxdiablo pour la sauvegarde de 4)
Copier et coller à une invite bash. Ensuite, lancez la fonction n à l’invite:
la source
echo $#
:, 7 octets. (ce sera alors n'importe quel shell que vous utiliserez pour lancer le script "./n" avec. c'est-à-dire que vous exécuterez bash? alors quand vous:./n arg1 ... argn
il sera interprété par bash.)C ++ 14 (gcc) , 34 octets
En tant que fonction lambda variadique générique (C ++ 14 requis):
Essayez-le en ligne!
Réponse précédente (incorrecte): 32 octets
Il manquait le
template<class...T>
et(p)
la source
p
(et-w
désactiver l'avertissement).-fpermissive
vous coûterait-il pas les 12 octets? Si ce n'est pas la norme ISO C ++ ou GNU C ++.Ruby , 12 octets
Essayez-le en ligne!
*a
est une combinaison d'arguments, faisanta
consommer tous les arguments passés au Proc.a.size
obtient sa taille.la source
Octave , 9 octets
Essayez-le en ligne!
Fonction anonyme en prenant un certain nombre d'arguments (et rejeter silencieusement le lot), et délivre en sortie le nombre d'arguments à travers le haut-
nargin
. Cela ne fonctionne pas dans MATLAB, où vous devezvarargin
autoriser de nombreux arguments arbitraires.la source
Perl 6 , 5 octets
Merci @Joshua pour -5 octets
Essayez-le en ligne!
la source
{+@_}
sub
dans Perl 6 (pas dans Perl 5, cependant).Perl 5 , 9 octets
Essayez-le en ligne!
la source
sub
sub
, I don't think so. It's not a function without it.sub
invalid since the result isn't something you can call or assign to a variablePHP, 34 bytes
la source
function(){return func_num_args();}
(35 bytes, posted below).C# .NET, 11 bytes
Try it online.
Explanation:
In C# .NET
object
is used for multi-type arguments, allowing one to pass integers, strings, characters, etc. as possible inputs. For example:C# .NET can also have a fixed size of optional arguments. For example:
And there are also varargs, which is an undefined amount of optional arguments (which is what I've used in this answer). For example:
Usually lambdas are created like this:
But unfortunately
System.Func
doesn't supportparams
varargs, so I'll have to create adelegate
instead:Which is my answer for this challenge, and can be found in the linked TIO test code.
The only limitation is that inputting an actual
object[]
likef(new object[]{1,2,3})
will result in 3 instead of 1.f(new int[]{1,2,3})
will still result in 1, because it interprets theint[]
as a singleobject
. To have theobject[]
parameter be interpret as a single object as well it can be casted to an object like this:f((object)new object[]{1,2,3})
.la source
object[]
parameters toobject
, like this:f((object)new object[]{1,2,3});
. There is no way to differentiate betweenf(new object[]{1,2,3});
andf(1,2,3);
as far as I could find.f(1, new object[]{1,2,3})
again though. Not sure if a solution for this behavior can be found.Dodos,
3231 bytesTry it online!
Uses Dennis' increment function.
Explanation
Alternatively, 32 bytes without recursion in target function (thanks @Leo)
Try it online!
Explanation
la source
C++, 72 bytes
Saves bytes by only working with ints.
la source
sizeof...
.Rust, 57 bytes
Explanation:
Test:
la source
PHP, 35 bytes
manual entry
la source
Common Lisp, 28 bytes
Try it online!
la source
Add++, 3 bytes
Try it online!
la source
PHP, 11 bytes
Try it online: 1 input | 3 inputs
la source
Batch,
5049 bytesNo builtin in Batch, so we have to go old-school. Saved 1 byte thanks to @IsmaelMiguel. Outputs via exit code, or save 3 bytes if output via global variable is valid. Example of use in a full program:
la source
:a|set r=0&for %%a in (%*)do set/ar+=1
(|
= windows-style newline). This solution is 38 bytes. To execute it, docall :a <args>
with agoto :eof
before the function, being the value available inside the variabler
. If you want to keep your solution, remove the/a
on the firstset
, and remove those@
.x86 32-bit (i386) machine code function, 13 bytes
Calling convention: i386 System V (stack args), with a NULL pointer as a sentinel / terminator for the end-of-arg-list. (Clobbers EDI, otherwise complies with SysV).
C (and asm) don't pass type info to variadic functions, so the OP's description of passing integers or arrays with no explicit type info could only be implemented in a convention that passed some kind of struct / class object (or pointers to such), not bare integers on the stack. So I decided to assume that all the args were non-NULL pointers, and the caller passes a NULL terminator.
A NULL-terminated pointer list of args is actually used in C for functions like POSIX
execl(3)
:int execl(const char *path, const char *arg, ... /* (char *) NULL */);
C doesn't allow
int foo(...);
prototypes with no fixed arg, butint foo();
means the same thing: args unspecified. (Unlike in C++ where it meansint foo(void)
). In any case, this is an asm answer. Coaxing a C compiler to call this function directly is interesting but not required.nasm -felf32 -l/dev/stdout arg-count.asm
with some comment lines removed.The question shows that the function must be able to return 0, and I decided to follow that requirement by not including the terminating NULL pointer in the arg count. This does cost 1 byte, though. (For the 12-byte version, remove the LEA and uncomment the
scasd
outside the loop and thexchg
, but not thedec edx
. I used LEA because it costs the same as those other three instructions put together, but is more efficient, so the function is fewer uops.)C caller for testing:
Built with:
-fcall-used-edi
is required even at -O0 to tell gcc to assume that functions clobberedi
without saving/restoring it, because I used so many calls in one C statement (theprintf
call) that even-O0
was using EDI. It appears to be safe for gcc'smain
to clobber EDI from its own caller (in CRT code), on Linux with glibc, but otherwise it's totally bogus to mix/match code compiled with different-fcall-used-reg
. There's no__attribute__
version of it to let us declare the asm functions with custom calling conventions different from the usual.Two other versions also came in at 13 bytes: this one based on
loopne
returns a value that's too high by 1.This version uses rep scasd instead of a loop, but takes the arg count modulo 256. (Or capped at 256 if the upper bytes of
ecx
are 0 on entry!)Amusingly, yet another version based on
inc eax
/pop edx
/test edx,edx
/jnz
came in at 13 bytes. It's a callee-pops convention, which is never used by C implementations for variadic functions. (I popped the ret addr into ecx, and jmp ecx instead of ret. (Or push/ret to not break the return-address predictor stack).la source
R, 20 bytes
Try it online!
R has a function just for that.
la source
JavaScript, 35 bytes
la source
Cauliflower, 16 bytes
Try it online!
la source