Usando el lenguaje de su elección, escriba una función que tome un número variable de argumentos y devuelva el número de argumentos con los que se llamó.
Detalles específicos:
- Su lenguaje debe admitir funciones de argumento variadic: algo invocable que toma un número arbitrario de argumentos y devuelve un valor.
- Los parámetros deben poder pasarse individualmente. Esto significa que pasar una matriz solo contaría para un parámetro. Puede usar una matriz "todos los argumentos pasados" si su idioma lo admite; la restricción está en cómo se llama la función.
- El código que llama a esta función no debe ser requerido para pasar el número de argumentos en su fuente . Si un compilador inserta el número de argumentos como parte de una convención de llamada, eso está permitido.
- Los argumentos pueden ser de cualquier tipo que desee. Puede admitir solo un tipo (por ejemplo, solo el soporte
int
sigue siendo válido), tipos arbitrarios (se permite cualquier tipo de argumento) o cualquier combinación de tipos de argumento (por ejemplo, el primer argumento esint
, el resto son cadenas). - Su función puede tener un número máximo de argumentos (especialmente porque los recursos son finitos), pero debe admitir al menos 2 argumentos.
Muestras:
f()
devoluciones0
f(1)
of("a")
vuelve1
f([1, 2, 3])
devuelve1
cuando se pasa una matriz, no 3 argumentosf(1, 10)
of(1, "a")
vuelve2
Como se trata de código de golf, la solución ganadora es la que utiliza la menor cantidad de bytes.
Respuestas:
Llamada binaria Amstrad CPC Z80 desde BASIC, 1 byte, codificado hexadecimal
(También versiones de 2 y 5 bytes, ver más abajo)
Al ingresar a la llamada, el número de parámetros pasados estará en el
A
registro. El código simplemente regresa de inmediato. No hay un concepto de valores de retorno en el Z80, solo estados de entrada y salida. El valor solo está "allí" accesible en el registro ya que el código no cambia las condiciones de entrada, exceptoPC
(el contador del programa) ySP
(el puntero de la pila). Sin embargo, el valor enA
no es accesible para BASIC y se sobrescribe casi de inmediato.Ejemplos:
A
= 2A
= 1A
= 0A pedido, aquí hay un código que hace que el valor sea accesible en BASIC. ¡Me sorprendió mucho descubrir que se podía hacer en solo 5 bytes !:
El código de la máquina:
En la entrada:
AF
- el acumulador y los registros de banderas (tratados como dos registros de 8 bits)A
contiene el número de parámetros pasados, hasta el máximo de 32 parámetrosF
. Parece que todas las banderas RESET0
, excepto las dos banderas indefinidas que son ambas1
. ElZ
indicador (cero) se establece en1
si no se pasaron parámetros enBC
B
- 32 menos el número de parámetros (A
+B
= 32)C
-&FF
DE
- La dirección del último parámetro, o la dirección de llamada si no se pasaron parámetrosHL
- La dirección del primer byte después del comando BASIC tokenizado que se está ejecutando actualmente (ya sea como programa o en modo de comando inmediato)IX
- La dirección de la pila del puntero al último parámetroIY
-&0000
El código
L
oaD
s la dirección apuntada porDE
con el valor enA
INC
rementsDE
XOR
sA
(conA
), dando&00
L
oaD
s el valorA
de la dirección señalada porDE
RET
urnasA la salida:
A
se destruye (siempre es&00
)DE
se destruye (siempre es uno más alto que en la entrada)Lo básico
Amstrad basic solo tiene tres tipos de datos, más matrices simples. Por defecto, todas las variables BÁSICAS son REALES (con signo, mantisa de 32 bits, exponente de 8 bits), que se pueden hacer explícitas con
!
. Para un uso INTEGER (firmado, 16 bits)%
y para un STRING (longitud de cadena de 1 byte, hasta 255 bytes de datos de caracteres, binario seguro) use$
:x
- REAL (implícito)x!
- REAL (explícito)x%
- INTEGERx$
- CUERDATambién puede usar
DEFINT
,DEFREAL
yDEFSTR
con una sola letra, o un rango de dos letras individuales para especificar el tipo predeterminado para todas las variables que comienzan con esa letra, similar a FORTRAN.DEFSTR a
DEFINT x-z
Ahora:
a
- STRING (implícito)i
- REAL (implícito)x
- INTEGER (implícito)x$
- STRING (explícito)El tipo más fácil para trabajar es el entero. El código de máquina espera que el último parámetro pase por dirección, no por valor, razón por la cual
@
está prefijado a la variable. La variable de retorno se cuenta como uno de losCALL
parámetros s.El código de máquina se llama como sigue desde BASIC (suponiendo que se cargue en la memoria en la dirección
&8000
):n%
= 4Esto siempre dará el resultado correcto, independientemente del valor inicial de
n%
.Para una versión de 2 bytes que conserva todos los registros de entrada:
n%
= 4Esto omite los primeros tres bytes y solo da el resultado correcto si el valor inicial de
n%
es0
-255
. Esto funciona porque el Z80 es little-endian.El parámetro de retorno debe inicializarse antes de pasarlo; de lo contrario, BASIC arrojará un
Improper argument
error. En la imagen a continuación, estoy imprimiendo (¡con el atajo?
ya que también jugué la demostración!) Los valores de retorno inmediatamente antes y después de la llamada para mostrar el cambio de valor. Estoy usando el valor&FFFF
porque esa es la representación binaria de-1
un entero con signo. Esto demuestra que el programa de 5 bytes escribe correctamente ambos bytes, mientras que el programa de 2 bytes solo escribe el byte bajo y supone que el byte alto ya está&00
.fuente
A
, si eso es cómo podría hacerlo desde BASIC). No es que haya nada de malo en eso, pero podría ser una respuesta más interesante seguir una convención de llamadas existente.A
es el mismo inmediatamente después de laRET
instrucción. La vida útil de un valor enA
es muy corta ya que es el acumulador. No hay tal cosa comox = CALL &8000, 42
. Tendría que serCALL &8000, x, 42
, y un código Z80 adicional, pero luegox
sería2
, no1
.&00
s -NOP
no-ops. Se puede agregar otro byte para hacerlo más seguro, pero, por supuesto, sin un parámetro de retorno no se puede establecer nada.Java (JDK 10) , 11 bytes
Pruébalo en línea!
fuente
interface x{void f(Object...a);}
ser definido, y este lambda debe almacenarse en una variable de ese tipo de interfaz, o pasar a un método que espere ese tipo de interfaz, por lo que no estoy realmente seguro de que cuente para este desafío (incluso aunque generalmente se permiten las lambdas de Java en los desafíos de codegolf)JavaScript, 15 bytes
La
Array.prototype.push
función toma cualquier número de argumentos, los agrega a su matriz y devuelve el tamaño de la matriz. Por lo tanto, lapush
función utilizada en una matriz vacía devuelve el número de argumentos suministradospush
.El
.bind(0)
simplemente le da a lapush
función unthis
valor fijo para que pueda almacenarse en una variable. De hecho, el identificador de 7 bytes[].push
se puede usar literalmente (pero no asignado) sinbind
:fuente
JavaScript (ES6), 16 bytes
Mostrar fragmento de código
fuente
Haskell ,
1081079594 bytesPruébalo en línea!
Esto fue sorprendentemente difícil de conseguir, pero me divertí tratando de descubrir cómo implementar algo que es trivial en los idiomas imperativos.
fuente
f
es opcional si dice quez 0
es la función sin el enlace, por lo quemain = print $ ((z 0) pi 0 () [] :: Int)
funciona.z 0
::Int
debe contarse en el recuento de bytes, ya que el tipo de respuesta debe declararse tarde o temprano, como enmain = print $ ((z 0 :: Double -> Integer -> () -> [a] -> (Int->Int->Int) -> IO () -> Int) pi 0 () [] (+) main)
. También creo que esto funciona solo durante el tiempo de compilación, por lo que algo comofoldl(\a b->a b) (z 0) $ [1..5])::Int
no puede funcionar. De cualquier manera, esto es genial.s/imperative/non-curry/
Python 3 , 15 bytes
Pruébalo en línea!
fuente
Zsh ,
75 bytesPruébalo en línea!
fuente
f(){ echo $#; }
Brain-Flak , 6 bytes
Mi primera publicación digna de solución de Brain-Flak, creo que es la herramienta adecuada para este trabajo:
Pruébalo en línea!
Explicación
Al ejecutar un programa Brain-Flak, inicialmente la pila izquierda contiene todos los argumentos. A partir de ahí, se trata simplemente de:
fuente
Wolfram Language (Mathematica) , 11 bytes
Pruébalo en línea!
Sugerido por JungHwan Min. Algunas restricciones (la entrada debe ser rectangular) pero no estamos obligados a manejar entradas arbitrarias.
11 bytes
Pruébalo en línea!
Otra solución de 11 bytes sugerida por Martin Ender. Esto parece un error cuando no hay una entrada pero aún así devuelve el valor correcto en todos los casos.
12 bytes
Pruébalo en línea!
Mi solución original
En Mathematica
##
significa un número variado de argumentos en una función.{
y los}
envuelve en una lista yLength@
toma la longitud de esta lista.&
al final convierte esto en una función real.fuente
R , 30 bytes
Pruébalo en línea!
fuente
function(...)nargs()
es de 20 bytes, pero el usolength(...)
fue mi enfoque inicial hasta que busqué en Google unanargs
función similar.list(...)
en lógico parasum()
poder usarlo, pero eso es complicado: /...length()
hace lo mismo comolength(list(...))
Bash, 12 bytes (gracias a paxdiablo por guardar 4)
Copie y pegue en un indicador de bash. Luego ejecute la función n desde el indicador:
fuente
echo $#
7 bytes. (será entonces cualquier shell que use para iniciar el script "./n" con. ej., ejecuta bash? luego cuando:./n arg1 ... argn
será interpretado por bash.)C ++ 14 (gcc) , 34 bytes
Como función lambda variadic genérica (se requiere C ++ 14):
Pruébalo en línea!
Respuesta anterior (incorrecta): 32 bytes
Faltaba el
template<class...T>
y(p)
fuente
p
(y-w
desactivar la advertencia).-fpermissive
costaría los 12 bytes para esa opción? Si no es estándar ISO C ++ o GNU C ++.Ruby, 12 bytes
Try it online!
*a
is a splat of the arguments, makinga
consume all arguments passed to the Proc.a.size
obtains its size.fuente
Octave, 9 bytes
Try it online!
Anonymous function taking any number of arguments (and silently discarding the lot), and outputs the number of arguments through the built-in
nargin
. This does not work in MATLAB, where you would needvarargin
to allow for arbitrary many arguments.fuente
Perl 6, 5 bytes
Thanks @Joshua for -5 bytes
Try it online!
fuente
{+@_}
sub
in Perl 6 (not in Perl 5, though).Perl 5, 9 bytes
Try it online!
fuente
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
fuente
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})
.fuente
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
fuente
C++, 72 bytes
Saves bytes by only working with ints.
fuente
sizeof...
.Rust, 57 bytes
Explanation:
Test:
fuente
PHP, 35 bytes
manual entry
fuente
Common Lisp, 28 bytes
Try it online!
fuente
Add++, 3 bytes
Try it online!
fuente
PHP, 11 bytes
Try it online: 1 input | 3 inputs
fuente
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:
fuente
: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).fuente
R, 20 bytes
Try it online!
R has a function just for that.
fuente
JavaScript, 35 bytes
fuente
Cauliflower, 16 bytes
Try it online!
fuente