Usando seu idioma de escolha, escreva uma função que use um número variável de argumentos e retorne o número de argumentos com os quais foi chamado.
Específicos:
- Seu idioma precisa suportar funções de argumento variadas: algo que pode ser chamado que pega um número arbitrário de argumentos e retorna um valor.
- Os parâmetros devem poder ser passados individualmente. Isso significa que a passagem de uma matriz contaria apenas um parâmetro. Você pode usar uma matriz "todos os argumentos passados" se o seu idioma suportar; a restrição é sobre como a função é chamada.
- O código que chama essa função não deve ser necessário para transmitir o número de argumentos em sua fonte . Se um compilador inserir o número de argumentos como parte de uma convenção de chamada, isso é permitido.
- Os argumentos podem ser de qualquer tipo que você desejar. Você pode suportar apenas um único tipo (por exemplo, apenas o suporte
int
ainda é válido), tipos arbitrários (qualquer tipo de argumento é permitido) ou qualquer combinação de tipos de argumentos (por exemplo, primeiro argumento éint
, resto é uma sequência de caracteres). - Sua função pode ter um número máximo de argumentos (especialmente porque os recursos são finitos), mas deve suportar pelo menos 2 argumentos.
Amostras:
f()
retorna0
f(1)
ouf("a")
retorna1
f([1, 2, 3])
retorna1
quando passa uma matriz, não 3 argumentosf(1, 10)
ouf(1, "a")
retorna2
Como se trata de código-golfe, a solução vencedora é a que utiliza o menor número de bytes.
Respostas:
Chamada binária Amstrad CPC Z80 de BASIC, 1 byte, codificado em hexadecimal
(Também versões de 2 e 5 bytes, veja abaixo)
Após a entrada na chamada, o número de parâmetros passados estará no
A
registro. O código simplesmente retorna imediatamente. Não há conceito de valores de retorno no Z80, apenas estados de entrada e saída. O valor é "lá" acessível no registro, pois o código não altera as condições de entrada, excetoPC
(o contador do programa) eSP
(o ponteiro da pilha). No entanto, o valor inA
não é acessível ao BASIC e é substituído quase imediatamente.Exemplos:
A
= 2A
= 1A
= 0Por solicitação, aqui está um código que torna o valor acessível em BASIC. Fiquei muito surpreso ao descobrir que isso poderia ser feito em apenas 5 bytes !:
O código da máquina:
Na entrada:
AF
- o acumulador e os registros de sinalizadores (tratados como dois registros de 8 bits)A
contém o número de parâmetros passados, até o máximo de 32 parâmetrosF
. Parece ter todos os sinalizadores RESET0
, exceto os dois sinalizadores indefinidos que são ambos1
. OZ
sinalizador (zero) é SET1
se não houver parâmetros passados noBC
B
- 32 menos o número de parâmetros (A
+B
= 32)C
-&FF
DE
- O endereço do último parâmetro ou o endereço de chamada se nenhum parâmetro foi passadoHL
- O endereço do primeiro byte após o comando BASIC tokenizado atualmente em execução (como um programa ou no modo de comando imediato)IX
- O endereço da pilha do ponteiro para o último parâmetroIY
-&0000
O código
L
oD
é o endereço indicado porDE
com o valor emA
INC
rementsDE
XOR
sA
(comA
), dando&00
L
oD
é o valorA
para o endereço indicado porDE
RET
urnasNa saída:
A
é destruído (é sempre&00
)DE
é destruído (é sempre mais alto do que na entrada)O básico
O Amstrad basic possui apenas três tipos de dados, além de matrizes simples. Por padrão, todas as variáveis BASIC são REAL (assinadas, mantissa de 32 bits, expoente de 8 bits), as quais podem ser explicitadas
!
. Para um uso INTEGER (assinado, 16 bits)%
e para um uso STRING (comprimento de cadeia de 1 byte, dados de caracteres de até 255 bytes, segurança binária)$
:x
- REAL (implícito)x!
- REAL (explícito)x%
- INTEGERx$
- CORDAVocê também pode usar
DEFINT
,DEFREAL
eDEFSTR
com uma única letra, ou um intervalo de duas letras simples para especificar o tipo padrão para todas as variáveis que começam com essa letra, semelhante ao Fortran.DEFSTR a
DEFINT x-z
Agora:
a
- STRING (implícito)i
- REAL (implícito)x
- INTEGER (implícito)x$
- STRING (explícito)O tipo mais fácil de trabalhar é o número inteiro. O código da máquina espera que o último parâmetro seja passado por endereço, não por valor, razão pela qual
@
é prefixado na variável. A variável de retorno é contada como um dosCALL
parâmetros.O código da máquina é chamado da seguinte forma no BASIC (assumindo que ele está carregado na memória no endereço
&8000
):n%
= 4Isso sempre fornecerá o resultado correto, independentemente do valor inicial de
n%
.Para uma versão de 2 bytes que preserva todos os registros de entrada:
n%
= 4Isso pula os três primeiros bytes e fornece apenas o resultado correto se o valor inicial de
n%
é0
-255
. Isso funciona porque o Z80 é pequeno-endian.O parâmetro de retorno deve ser inicializado antes de ser passado, caso contrário, o BASIC emitirá um
Improper argument
erro. Na imagem abaixo, estou imprimindo (com o atalho?
desde que também jogamos na demonstração!) Os valores de retorno imediatamente antes e depois da chamada para mostrar a alteração do valor. Estou usando o valor&FFFF
porque essa é a representação binária de-1
para um número inteiro assinado. Isso demonstra que o programa de 5 bytes grava corretamente os dois bytes, enquanto o programa de 2 bytes grava apenas o byte baixo e supõe que o byte alto já esteja&00
.fonte
A
, se for o caso). como você pode realmente fazê-lo no BASIC). Não que haja algo errado nisso, mas pode ser uma resposta mais interessante seguir uma convenção de convocação existente.A
é o mesmo imediatamente após aRET
instrução. A vida útil de um valorA
é muito curta, pois é o acumulador. Não existe tal coisax = CALL &8000, 42
. Teria que serCALL &8000, x, 42
, e código Z80 extra, mas depoisx
seria2
, não1
.&00
s-NOP
no-ops. Outro byte pode ser adicionado para torná-lo mais seguro, mas é claro que sem um parâmetro de retorno, ele não pode definir nada.Java (JDK 10) , 11 bytes
Experimente online!
fonte
interface x{void f(Object...a);}
seja definido, e esse lambda deve ser armazenado em uma variável desse tipo de interface ou ser passado para um método que espera esse tipo de interface, por isso não tenho certeza se isso conta para esse desafio (mesmo embora geralmente lambdas java são permitidos em desafios codegolf)JavaScript, 15 bytes
A
Array.prototype.push
função pega qualquer número de argumentos, os adiciona à sua matriz e retorna o tamanho da matriz. Portanto, apush
função usada em uma matriz vazia retorna o número de argumentos fornecidospush
.O
.bind(0)
simplesmente fornece àpush
função umthis
valor fixo para que possa ser armazenada em uma variável. De fato, o identificador de 7 bytes[].push
pode ser usado literalmente (mas não atribuído) sembind
:fonte
JavaScript (ES6), 16 bytes
Mostrar snippet de código
fonte
Haskell ,
1081079594 bytesExperimente online!
Foi surpreendentemente difícil começar a trabalhar, mas me diverti tentando descobrir como implementar algo que é trivial em linguagens imperativas.
fonte
f
é opcional se você disserz 0
é a função sem a ligação, entãomain = print $ ((z 0) pi 0 () [] :: Int)
funciona.z 0
::Int
devem ser contados na contagem de bytes, uma vez que o tipo de resposta tem que ser declarado mais cedo ou mais tarde, como emmain = print $ ((z 0 :: Double -> Integer -> () -> [a] -> (Int->Int->Int) -> IO () -> Int) pi 0 () [] (+) main)
. Eu também acho que isso funciona apenas durante o tempo de compilação, então algo comofoldl(\a b->a b) (z 0) $ [1..5])::Int
não pode funcionar. De qualquer forma, isso é ótimo.s/imperative/non-curry/
Python 3 , 15 bytes
Experimente online!
fonte
Zsh ,
75 bytesExperimente online!
fonte
f(){ echo $#; }
Brain-Flak , 6 bytes
Minha primeira publicação digna de solução Brain-Flak, acho que é a ferramenta certa para este trabalho:
Experimente online!
Explicação
Ao executar um programa Brain-Flak, inicialmente a pilha esquerda contém todos os argumentos. A partir daí, é simplesmente uma questão de:
fonte
Wolfram Language (Mathematica) , 11 bytes
Experimente online!
Sugerido por JungHwan Min. Algumas restrições (a entrada deve ser retangular), mas não somos obrigados a lidar com entradas arbitrárias.
11 bytes
Experimente online!
Outra solução de 11 bytes sugerida por Martin Ender. Isso parece erro quando não há uma entrada, mas ainda retorna o valor correto em todos os casos.
12 bytes
Experimente online!
Minha solução original.
No Mathematica,
##
significa um número variável de argumentos em uma função.{
e os}
agrupa em uma lista eLength@
ocupa o comprimento dessa lista.&
no final, transforma isso em uma função real.fonte
R , 30 bytes
Experimente online!
fonte
function(...)nargs()
tem 20 bytes, mas usarlength(...)
foi minha abordagem inicial até pesquisar umanargs
função no estilo.list(...)
a um tão lógicosum()
poderia ser usado, mas isso é complicado: /...length()
faz a mesma coisa quelength(list(...))
Bash, 12 bytes (graças a paxdiablo por salvar 4)
Copie e cole em um prompt do bash. Em seguida, execute a função n no prompt:
fonte
echo $#
:, 7 bytes. (será então qualquer shell que você usa para iniciar o script "./n" com ou seja, você corre o bash então quando você:.?./n arg1 ... argn
ele será interpretado pelo bash.)C ++ 14 (gcc) , 34 bytes
As generic variadic lambda function (C++14 required):
Try it online!
Previous (incorrect) answer: 32 bytes
It was missing the
template<class...T>
and(p)
fonte
p
(and-w
to turn off the warning).-fpermissive
cost you the 12 bytes for that option, though? If it's not standard ISO C++ or 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.fonte
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.fonte
Perl 6, 5 bytes
Thanks @Joshua for -5 bytes
Try it online!
fonte
{+@_}
sub
in Perl 6 (not in Perl 5, though).Perl 5, 9 bytes
Try it online!
fonte
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
fonte
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})
.fonte
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
fonte
C++, 72 bytes
Saves bytes by only working with ints.
fonte
sizeof...
.Rust, 57 bytes
Explanation:
Test:
fonte
PHP, 35 bytes
manual entry
fonte
Common Lisp, 28 bytes
Try it online!
fonte
Add++, 3 bytes
Try it online!
fonte
PHP, 11 bytes
Try it online: 1 input | 3 inputs
fonte
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:
fonte
: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).fonte
R, 20 bytes
Try it online!
R has a function just for that.
fonte
JavaScript, 35 bytes
fonte
Cauliflower, 16 bytes
Try it online!
fonte