Dengan menggunakan bahasa pilihan Anda, tulislah sebuah fungsi yang mengambil sejumlah variabel argumen dan mengembalikan jumlah argumen yang dipanggil dengannya.
Spesifik:
- Bahasa Anda perlu mendukung fungsi argumen variadik: sesuatu yang dapat dipanggil yang mengambil jumlah argumen sewenang-wenang dan mengembalikan nilai.
- Parameter harus dapat dilewati secara individual. Ini berarti bahwa melewatkan array hanya akan dihitung untuk satu parameter. Anda dapat menggunakan larik "semua argumen yang berlalu" jika bahasa Anda mendukungnya; batasannya adalah bagaimana fungsi dipanggil.
- Kode yang memanggil fungsi ini tidak harus diharuskan untuk melewati jumlah argumen di sumbernya . Jika kompiler memasukkan jumlah argumen sebagai bagian dari konvensi pemanggilan, itu diperbolehkan.
- Argumen dapat berupa jenis apa pun yang Anda inginkan. Anda dapat mendukung hanya satu tipe (mis. Hanya pendukung
int
yang masih valid), tipe arbitrer (semua jenis argumen diperbolehkan), atau kombinasi jenis argumen apa pun (mis. Argumen pertama adalahint
, sisanya adalah string). - Fungsi Anda mungkin memiliki jumlah argumen maksimum (terutama karena sumber daya terbatas), tetapi harus mendukung setidaknya 2 argumen.
Sampel:
f()
kembali0
f(1)
atauf("a")
kembali1
f([1, 2, 3])
kembali1
saat dilewatkan array, bukan 3 argumenf(1, 10)
atauf(1, "a")
kembali2
Karena ini adalah kode-golf, solusi yang menang adalah yang menggunakan jumlah byte paling sedikit.
Jawaban:
Amstrad CPC Z80 panggilan biner dari BASIC, 1 byte, hex encoded
(Juga versi 2 dan 5 byte, lihat di bawah)
Setelah masuk ke panggilan, jumlah parameter yang dilewati akan ada dalam
A
register. Kode tersebut langsung kembali segera. Tidak ada konsep nilai pengembalian di Z80, hanya status masuk dan keluar. Nilai hanya "ada" yang dapat diakses dalam register karena kode tidak mengubah kondisi input, kecuali untukPC
(penghitung program) danSP
(penumpukan tumpukan). Namun, nilai dalamA
tidak dapat diakses oleh BASIC dan akan ditimpa segera.Contoh:
A
= 2A
= 1A
= 0Berdasarkan permintaan, berikut adalah beberapa kode yang membuat nilai dapat diakses di BASIC. Saya sangat terkejut menemukan ini bisa dilakukan hanya dalam 5 byte !:
Kode mesin:
Saat masuk:
AF
- register akumulator dan flag (diperlakukan sebagai dua register 8-bit)A
berisi jumlah parameter yang dilewati, hingga maksimal 32 parameterF
. Tampaknya memiliki semua flag RESET0
, kecuali dua flag yang tidak ditentukan yang keduanya1
. TheZ
flag (nol) adalah SET untuk1
jika tidak ada parameter yang dikirimkan diBC
B
- 32 minus jumlah parameter (A
+B
= 32)C
-&FF
DE
- Alamat parameter terakhir, atau alamat panggilan jika tidak ada parameter yang diteruskanHL
- Alamat byte pertama setelah perintah BASIC terpatok saat ini sedang dieksekusi (baik sebagai program atau dalam mode perintah langsung)IX
- Alamat stack pointer ke parameter terakhirIY
-&0000
Kode
L
oaD
alamat yang ditunjuk olehDE
dengan nilai diA
INC
rementsDE
XOR
sA
(withA
), memberi&00
L
ApakahD
nilaiA
ke alamat yang ditunjukkan olehDE
RET
guciSaat keluar:
A
dihancurkan (selalu&00
)DE
dihancurkan (selalu lebih tinggi daripada saat masuk)Dasar
Amstrad basic hanya memiliki tiga tipe data, ditambah array sederhana. Secara default, semua variabel BASIC adalah NYATA (ditandatangani, 32 bit mantissa, 8 bit eksponen), yang dapat dibuat eksplisit dengan
!
. Untuk penggunaan INTEGER (ditandatangani, 16 bit)%
dan untuk STRING (panjang string 1 byte, hingga 255 byte data karakter, biner safe) gunakan$
:x
- NYATA (implisit)x!
- NYATA (eksplisit)x%
- INTEGERx$
- STRINGAnda juga dapat menggunakan
DEFINT
,DEFREAL
danDEFSTR
dengan satu huruf, atau rentang dua huruf tunggal untuk menentukan jenis default untuk semua variabel yang dimulai dengan huruf itu, mirip dengan FORTRAN.DEFSTR a
DEFINT x-z
Sekarang:
a
- STRING (implisit)i
- NYATA (implisit)x
- INTEGER (implisit)x$
- STRING (eksplisit)Jenis yang paling mudah digunakan adalah integer. Kode mesin mengharapkan parameter terakhir untuk dilewati oleh alamat, bukan nilai, yang mengapa
@
diawali dengan variabel. Variabel kembali dihitung sebagai salah satuCALL
parameter s.Kode mesin disebut sebagai berikut dari BASIC (dengan asumsi itu dimuat di dalam memori di alamat
&8000
):n%
= 4Ini akan selalu memberikan hasil yang benar, terlepas dari nilai awal
n%
.Untuk versi 2-byte yang mempertahankan semua register input:
n%
= 4Ini melompati tiga byte pertama, dan hanya memberikan hasil yang benar jika nilai awal
n%
adalah0
-255
. Ini berfungsi karena Z80 adalah little-endian.Parameter pengembalian harus diinisialisasi sebelum dikirimkan, jika tidak, BASIC akan melempar
Improper argument
kesalahan. Pada gambar di bawah ini, saya mencetak (dengan pintasan?
karena saya juga ikut golf demonstrasi!) Nilai kembali segera sebelum dan sesudah panggilan untuk menunjukkan perubahan nilai. Saya menggunakan nilai&FFFF
karena itu adalah representasi biner-1
untuk integer yang ditandatangani. Ini menunjukkan bahwa program 5-byte dengan benar menulis kedua byte, sedangkan program 2-byte hanya menulis byte rendah dan mengasumsikan bahwa byte tinggi sudah ada&00
.sumber
A
, jika itu bagaimana Anda bisa melakukannya dari BASIC). Bukannya ada yang salah dengan itu, tapi mungkin itu jawaban yang lebih menarik untuk mengikuti konvensi pemanggil yang ada.A
ini sama segera setelahRET
instruksi. Umur nilai dalamA
sangat singkat karena akumulatornya. Tidak ada yang namanyax = CALL &8000, 42
. Itu harusCALL &8000, x, 42
, dan kode Z80 tambahan, tetapi kemudianx
akan menjadi2
, tidak1
.&00
s -NOP
no-ops. Byte lain dapat ditambahkan untuk membuatnya lebih aman, tetapi tentu saja tanpa parameter pengembalian tidak dapat mengatur apa pun.Java (JDK 10) , 11 byte
Cobalah online!
sumber
interface x{void f(Object...a);}
didefinisikan, dan lambda ini harus disimpan dalam variabel jenis antarmuka itu, atau diteruskan ke metode yang mengharapkan jenis antarmuka itu, jadi saya tidak benar-benar yakin itu diperhitungkan untuk tantangan ini (bahkan meskipun biasanya java lambdas diizinkan dalam tantangan codegolf)JavaScript, 15 byte
The
Array.prototype.push
fungsi mengambil sejumlah argumen, menambahkan mereka ke array nya, dan mengembalikan ukuran dari array. Oleh karena itu,push
fungsi yang digunakan pada array kosong mengembalikan jumlah argumen yang disediakanpush
.The
.bind(0)
hanya memberikanpush
fungsi tetapthis
nilai sehingga dapat disimpan dalam variabel. Bahkan, pengidentifikasi 7-byte[].push
dapat digunakan secara harfiah (tetapi tidak ditugaskan) tanpabind
:sumber
JavaScript (ES6), 16 byte
Tampilkan cuplikan kode
sumber
Haskell ,
1081079594 byteCobalah online!
Ini mengejutkan sulit untuk bekerja, tetapi saya senang mencoba mencari tahu bagaimana menerapkan sesuatu yang sepele dalam bahasa imperatif.
sumber
f
opsional jika Anda katakanz 0
adalah fungsi tanpa penjilidan, makamain = print $ ((z 0) pi 0 () [] :: Int)
berfungsi.z 0
::Int
harus dihitung dalam hitungan byte, karena jenis jawaban harus dinyatakan cepat atau lambat, seperti padamain = print $ ((z 0 :: Double -> Integer -> () -> [a] -> (Int->Int->Int) -> IO () -> Int) pi 0 () [] (+) main)
. Saya juga berpikir bahwa ini hanya berfungsi selama waktu kompilasi sehingga sesuatu sepertifoldl(\a b->a b) (z 0) $ [1..5])::Int
tidak dapat bekerja. Apa pun itu, ini adalah hal yang hebat.s/imperative/non-curry/
Python 3 , 15 byte
Cobalah online!
sumber
Zsh ,
75 byteCobalah online!
sumber
f(){ echo $#; }
Brain-Flak , 6 byte
Solusi Brain-Flak pertama saya yang layak diposkan, saya kira itu alat yang tepat untuk pekerjaan ini:
Cobalah online!
Penjelasan
Saat menjalankan program Brain-Flak, pada awalnya tumpukan kiri berisi semua argumen. Dari sana itu hanya masalah:
sumber
Bahasa Wolfram (Mathematica) , 11 byte
Cobalah online!
Disarankan oleh JungHwan Min. Beberapa batasan (input harus berbentuk persegi panjang) tetapi kami tidak diharuskan untuk menangani input yang sewenang-wenang.
11 byte
Cobalah online!
Solusi 11 byte lain yang disarankan oleh Martin Ender. Ini tampaknya salah ketika tidak ada satu input tetapi masih mengembalikan nilai yang benar dalam semua kasus.
12 byte
Cobalah online!
Solusi asli saya
Dalam Mathematica
##
singkatan dari sejumlah argumen dalam suatu fungsi.{
dan}
membungkusnya dalam daftar danLength@
mengambil panjang daftar ini.&
pada akhirnya mengubahnya menjadi fungsi yang sebenarnya.sumber
R , 30 byte
Cobalah online!
sumber
function(...)nargs()
adalah 20 byte, tetapi menggunakanlength(...)
pendekatan awal saya sampai saya googlednargs
fungsi-like.list(...)
menjadi logis sehinggasum()
dapat digunakan, tapi itu rumit: /...length()
melakukan hal yang sama denganlength(list(...))
Bash, 12 byte (terima kasih kepada paxdiablo karena menyimpan 4)
Salin dan tempel di bash prompt. Kemudian jalankan fungsi n dari prompt:
sumber
echo $#
:, 7 byte. (nanti akan ada shell yang Anda gunakan untuk meluncurkan skrip "./n" dengan. yaitu, Anda menjalankan bash? lalu ketika Anda:./n arg1 ... argn
itu akan ditafsirkan oleh bash.)C ++ 14 (gcc) , 34 byte
Sebagai fungsi lambda variadik generik (diperlukan C ++ 14):
Cobalah online!
Sebelumnya (salah) menjawab: 32 byte
Itu hilang
template<class...T>
dan(p)
sumber
p
(dan-w
untuk mematikan peringatan).-fpermissive
dikenakan biaya 12 byte untuk opsi itu, sih ? Jika bukan standar ISO C ++ atau GNU C ++.Ruby , 12 byte
Cobalah online!
*a
adalah percikan argumen, membuata
konsumsi semua argumen yang diteruskan ke Proc.a.size
mendapatkan ukurannya.sumber
Oktaf , 9 byte
Cobalah 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.sumber
Perl 6, 5 bytes
Thanks @Joshua for -5 bytes
Try it online!
sumber
{+@_}
sub
in Perl 6 (not in Perl 5, though).Perl 5, 9 bytes
Try it online!
sumber
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
sumber
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})
.sumber
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
sumber
C++, 72 bytes
Saves bytes by only working with ints.
sumber
sizeof...
.Rust, 57 bytes
Explanation:
Test:
sumber
PHP, 35 bytes
manual entry
sumber
Common Lisp, 28 bytes
Try it online!
sumber
Add++, 3 bytes
Try it online!
sumber
PHP, 11 bytes
Try it online: 1 input | 3 inputs
sumber
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:
sumber
: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).sumber
R, 20 bytes
Try it online!
R has a function just for that.
sumber
JavaScript, 35 bytes
sumber
Cauliflower, 16 bytes
Try it online!
sumber