Schreiben Sie in der Sprache Ihrer Wahl eine Funktion, die eine variable Anzahl von Argumenten akzeptiert und die Anzahl der Argumente zurückgibt, mit denen sie aufgerufen wurde.
Besonderheiten:
- Ihre Sprache muss verschiedene Argumentfunktionen unterstützen: Eine aufrufbare Funktion, die eine beliebige Anzahl von Argumenten akzeptiert und einen Wert zurückgibt.
- Parameter müssen einzeln übergeben werden können. Dies bedeutet, dass das Übergeben eines Arrays nur für einen Parameter zählt. Sie können ein Array "alle übergebenen Argumente" verwenden, wenn Ihre Sprache dies unterstützt. Die Einschränkung besteht darin, wie die Funktion aufgerufen wird.
- Code, der diese Funktion aufruft, muss nicht erforderlich sein, um die Anzahl der Argumente in seiner Quelle zu übergeben . Wenn ein Compiler die Anzahl der Argumente als Teil einer Aufrufkonvention einfügt, ist dies zulässig.
- Die Argumente können von einem beliebigen Typ sein. Sie können nur einen einzelnen Typ unterstützen (z. B. ist nur die Unterstützung
int
noch gültig), beliebige Typen (jede Art von Argument ist zulässig) oder eine beliebige Kombination von Argumenttypen (z. B. erstes Argument istint
, Rest sind Zeichenfolgen). - Ihre Funktion kann eine maximale Anzahl von Argumenten enthalten (insbesondere, da die Ressourcen endlich sind), muss jedoch mindestens 2 Argumente unterstützen.
Proben:
f()
kehrt zurück0
f(1)
oderf("a")
kehrt zurück1
f([1, 2, 3])
Gibt1
beim Übergeben ein Array zurück, nicht 3 Argumentef(1, 10)
oderf(1, "a")
kehrt zurück2
Da dies Codegolf ist, ist die gewinnbringende Lösung diejenige, die die geringste Anzahl von Bytes verwendet.
Antworten:
Amstrad CPC Z80-Binäraufruf von BASIC, 1 Byte, hexadezimal codiert
(Auch 2- und 5-Byte-Versionen, siehe unten)
Bei der Eingabe zum Aufruf wird die Anzahl der übergebenen Parameter im
A
Register gespeichert. Der Code kehrt einfach sofort zurück. Es gibt kein Konzept für Rückgabewerte im Z80, nur für Ein- und Ausstiegszustände. Auf den Wert kann nur "dort" im Register zugegriffen werden, da der Code bis aufPC
(den Programmzähler) undSP
(den Stapelzeiger) keine Eingabebedingungen ändert . Der Wert inA
ist jedoch für BASIC nicht zugänglich und wird fast sofort überschrieben.Beispiele:
A
= 2A
= 1A
= 0Auf Anfrage finden Sie hier einen Code, der den Wert in BASIC zugänglich macht. Ich war sehr überrascht, dass dies in nur 5 Bytes möglich war !:
Der Maschinencode:
Bei der Einreise:
AF
- die Akkumulator- und Merkerregister (behandelt als zwei 8-Bit-Register)A
enthält die Anzahl der übergebenen Parameter bis zu maximal 32 ParameternF
. Es scheinen alle Flags auf RESET zu sein0
, mit Ausnahme der beiden undefinierten Flags, die beide sind1
. DasZ
Flag (Null) wird auf gesetzt,1
wenn keine Parameter übergeben wurdenBC
B
- 32 minus die Anzahl der Parameter (A
+B
= 32)C
-&FF
DE
- Die Adresse des letzten Parameters oder die aufrufende Adresse, wenn keine Parameter übergeben wurdenHL
- Die Adresse des ersten Bytes nach dem aktuell ausgeführten tokenisierten BASIC-Befehl (entweder als Programm oder im Sofortbefehlsmodus)IX
- Die Stapeladresse des Zeigers auf den letzten ParameterIY
-&0000
Der Code
L
oaD
s die Adresse, auf die vonDE
mit dem Wert in verwiesen wirdA
INC
rementsDE
XOR
sA
(mitA
) geben&00
L
oaD
s der Wert inA
der Adresse, auf die von verwiesen wirdDE
RET
UrnenBei der Ausfahrt:
A
ist zerstört (es ist immer&00
)DE
ist zerstört (es ist immer eine höher als bei der Einreise)Das BASIC
Amstrad Basic hat nur drei Datentypen sowie einfache Arrays. Standardmäßig sind alle BASIC-Variablen REAL (vorzeichenbehaftet, 32-Bit-Mantisse, 8-Bit-Exponent), was mit explizit angegeben werden kann
!
. Verwenden Sie%
für eine INTEGER- Zeichenfolge (mit Vorzeichen, 16 Bit) und für eine STRING-Zeichenfolge (1 Byte Zeichenfolgenlänge, bis zu 255 Byte Zeichendaten, binär sicher) Folgendes$
:x
- REAL (implizit)x!
- REAL (explizit)x%
- INTEGERx$
- STRINGSie können auch verwendet werden
DEFINT
,DEFREAL
undDEFSTR
mit einem einzigen Buchstaben oder einer Reihe von zwei einzelnen Buchstaben den Standardtyp für alle Variablen mit diesem Buchstaben, ähnlich wie Fortran angeben , beginnend mit .DEFSTR a
DEFINT x-z
Jetzt:
a
- STRING (implizit)i
- REAL (implizit)x
- INTEGER (implizit)x$
- STRING (explizit)Am einfachsten ist es, mit der Ganzzahl zu arbeiten. Der Maschinencode erwartet, dass der letzte Parameter als Adresse und nicht als Wert übergeben wird, weshalb
@
der Variablen ein Präfix vorangestellt wird. Die Rückgabevariable wird als einer derCALL
s-Parameter gezählt.Der Maschinencode wird von BASIC wie folgt aufgerufen (vorausgesetzt, er wird an der Adresse in den Speicher geladen
&8000
):n%
= 4Dies liefert immer das richtige Ergebnis, unabhängig vom Anfangswert von
n%
.Für eine 2-Byte-Version, bei der alle Eingaberegister erhalten bleiben:
n%
= 4Damit springt die ersten drei Bytes und gibt nur das richtige Ergebnis , wenn der Anfangswert
n%
ist0
-255
. Dies funktioniert, weil der Z80 Little-Endian ist.Der Rückgabeparameter muss vor der Übergabe initialisiert werden, andernfalls gibt BASIC einen
Improper argument
Fehler aus. Im folgenden Bild?
drucke ich (mit der Verknüpfung, seitdem ich die Demonstration auch gespielt habe!) Die Rückgabewerte unmittelbar vor und nach dem Aufruf, um die Wertänderung anzuzeigen. Ich verwende den Wert,&FFFF
weil dies die binäre Darstellung-1
für eine Ganzzahl mit Vorzeichen ist. Dies zeigt, dass das 5-Byte-Programm beide Bytes korrekt schreibt, während das 2-Byte-Programm nur das niedrige Byte schreibt und davon ausgeht, dass das hohe Byte bereits vorhanden ist&00
.quelle
A
, falls dies der Fall ist wie könnte man das eigentlich aus BASIC machen). Nicht, dass daran etwas falsch ist, aber es könnte eine interessantere Antwort sein, einer bestehenden Calliing-Konvention zu folgen.A
ist gleich unmittelbar nach derRET
Anweisung. Die Lebensdauer eines Wertes inA
ist sehr kurz, da es sich um den Akkumulator handelt. So etwas gibt es nichtx = CALL &8000, 42
. Es müsste seinCALL &8000, x, 42
, und zusätzlicher Z80-Code, aber dannx
wäre es2
nicht1
.&00
s -NOP
no-ops überschreibt . Ein weiteres Byte kann hinzugefügt werden, um die Sicherheit zu erhöhen. Ohne einen Rückgabeparameter kann jedoch nichts festgelegt werden.Java (JDK 10) , 11 Byte
Probieren Sie es online!
quelle
interface x{void f(Object...a);}
definiert werden, und dieses Lambda muss entweder in einer Variablen dieses Schnittstellentyps gespeichert oder an eine Methode übergeben werden, die diesen Schnittstellentyp erwartet obwohl in der Regel Java Lambdas in Codegolf-Herausforderungen erlaubt sind)JavaScript, 15 Byte
Die
Array.prototype.push
Funktion akzeptiert eine beliebige Anzahl von Argumenten, fügt sie ihrem Array hinzu und gibt die Größe des Arrays zurück. Daher gibt diepush
in einem leeren Array verwendete Funktion die Anzahl der Argumente zurück, die übergeben wurdenpush
.Das
.bind(0)
gibt derpush
Funktion einfach einen festenthis
Wert, damit sie in einer Variablen gespeichert werden kann. Tatsächlich kann der 7-Byte-Bezeichner[].push
wörtlich verwendet (aber nicht zugewiesen) werden, ohnebind
:quelle
JavaScript (ES6), 16 Byte
Code-Snippet anzeigen
quelle
Haskell ,
1081079594 BytesProbieren Sie es online!
Es war überraschend schwierig, damit umzugehen, aber ich hatte Spaß daran, herauszufinden, wie man etwas Triviales in imperativen Sprachen umsetzt.
quelle
f
ist optional wenn du sagstz 0
ist die funktion ohne bindung,main = print $ ((z 0) pi 0 () [] :: Int)
funktioniert also.z 0
::Int
sollte in der Byteanzahl gezählt werden, da der Typ der Antwort früher oder später wie in deklariert werden mussmain = print $ ((z 0 :: Double -> Integer -> () -> [a] -> (Int->Int->Int) -> IO () -> Int) pi 0 () [] (+) main)
. Ich denke auch, dass dies nur während der Kompilierungszeit funktioniert, so etwasfoldl(\a b->a b) (z 0) $ [1..5])::Int
kann nicht funktionieren. So oder so, das ist großartiges Zeug.s/imperative/non-curry/
Python 3 , 15 Bytes
Probieren Sie es online!
quelle
Zsh ,
75 BytesProbieren Sie es online!
quelle
f(){ echo $#; }
Brain-Flak , 6 Bytes
Meine erste Brain-Flak-Lösung, die es wert ist, veröffentlicht zu werden. Ich denke, sie ist das richtige Werkzeug für diesen Job:
Probieren Sie es online!
Erläuterung
Bei der Ausführung eines Brain-Flak-Programms enthält der linke Stapel zunächst alle Argumente. Von dort ist es einfach eine Frage von:
quelle
Wolfram Language (Mathematica) , 11 Bytes
Probieren Sie es online!
Vorgeschlagen von JungHwan Einige Einschränkungen (Eingaben müssen rechteckig sein), aber wir müssen keine willkürlichen Eingaben verarbeiten.
11 Bytes
Probieren Sie es online!
Eine weitere 11-Byte-Lösung von Martin Ender. Dies scheint ein Fehler zu sein, wenn es keinen Eingang gibt, der aber in allen Fällen den korrekten Wert zurückgibt.
12 Bytes
Probieren Sie es online!
Meine ursprüngliche Lösung.
In Mathematica
##
steht für eine unterschiedliche Anzahl von Argumenten in einer Funktion.{
und}
packt sie in eine Liste undLength@
nimmt die Länge dieser Liste.&
am Ende verwandelt sich dies in eine tatsächliche Funktion.quelle
R , 30 Bytes
Probieren Sie es online!
quelle
function(...)nargs()
ist 20 Bytes, aber mitlength(...)
war mein erster Ansatz, bis ich einenargs
ähnliche Funktion googelte .list(...)
in ein logisches zu konvertieren , damitsum()
es verwendet werden kann, aber das ist schwierig: /...length()
macht das gleiche wielength(list(...))
Bash, 12 Bytes (danke an paxdiablo für das Speichern von 4)
Kopieren und einfügen an einer Bash-Eingabeaufforderung. Führen Sie dann die Funktion n an der Eingabeaufforderung aus:
quelle
echo $#
:, 7 bytes. (wird dann jede Shell Sie verwenden , um die „./n“ Skript starten mit dh Sie bash laufen dann , wenn Sie:.?./n arg1 ... argn
es von bash interpretiert wird.)C ++ 14 (gcc) , 34 Bytes
Als generische variadische Lambda-Funktion (C ++ 14 erforderlich):
Probieren Sie es online!
Vorherige (falsche) Antwort: 32 Bytes
Es fehlte das
template<class...T>
und(p)
quelle
p
(und-w
die Warnung auszuschalten).-fpermissive
Sie die 12 Bytes für diese Option nicht kosten? Wenn es nicht Standard ISO C ++ oder GNU C ++ ist.Ruby , 12 Bytes
Probieren Sie es online!
*a
ist ein Splat der Argumente, bei dema
alle an den Proc übergebenen Argumente verbraucht werden.a.size
erhält seine Größe.quelle
Oktave , 9 Bytes
Probieren Sie es online!
Anonyme Funktion, die eine beliebige Anzahl von Argumenten annimmt (und das Los stillschweigend verwirft) und die Anzahl der Argumente über die integrierte Funktion ausgibt
nargin
. Dies funktioniert nicht in MATLAB, wo Sievarargin
beliebig viele Argumente zulassen müssten .quelle
Perl 6 , 5 Bytes
Danke @Joshua für -5 Bytes
Probieren Sie es online!
quelle
{+@_}
sub
in Perl 6 entfernen (jedoch nicht in Perl 5).Perl 5 , 9 Bytes
Probieren Sie es online!
quelle
sub
sub
, denke ich nicht. Es ist keine Funktion ohne sie.sub
ungültig betrachten, da das Ergebnis nicht aufgerufen oder einer Variablen zugewiesen werden kannPHP, 34 Bytes
quelle
function(){return func_num_args();}
(35 Bytes, siehe unten).C # .NET, 11 Bytes
Probieren Sie es online aus.
Erläuterung:
In C # wird .NET
object
für Argumente mit mehreren Typen verwendet, sodass Ganzzahlen, Zeichenfolgen, Zeichen usw. als mögliche Eingaben übergeben werden können. Beispielsweise:C # .NET kann auch eine feste Größe optionaler Argumente haben. Beispielsweise:
Und es gibt auch varargs, eine undefinierte Menge optionaler Argumente (was ich in dieser Antwort verwendet habe). Beispielsweise:
Normalerweise werden Lambdas wie folgt erstellt:
Aber leider
System.Func
unterstütztparams
varargs nicht, daher mussdelegate
stattdessen ein erstellt werden:Welches ist meine Antwort auf diese Herausforderung und kann im verknüpften TIO-Testcode gefunden werden.
Die einzige Einschränkung ist , dass eine tatsächliche Eingabe
object[]
wief(new object[]{1,2,3})
in 3 führt statt 1f(new int[]{1,2,3})
wird immer noch zu 1, weil es die interpretiertint[]
als eine einzigeobject
. Damit dasobject[]
werden Parameter als ein einzelnes Objekt zu interpretieren und kann es auf ein Objekt wie diese gegossen werden:f((object)new object[]{1,2,3})
.quelle
object[]
Parameterobject
, wie folgt aus :f((object)new object[]{1,2,3});
. Es gibt keine Möglichkeit, zwischenf(new object[]{1,2,3});
undf(1,2,3);
so weit zu unterscheiden, wie ich es finden konnte.f(1, new object[]{1,2,3})
erneut fehl . Nicht sicher, ob eine Lösung für dieses Verhalten gefunden werden kann.Dodos ,
3231 BytesProbieren Sie es online!
Verwendet Dennis 'Inkrementfunktion.
Erläuterung
Alternativ 32 Bytes ohne Rekursion in der Zielfunktion (danke @Leo )
Probieren Sie es online!
Erläuterung
quelle
C ++, 72 Bytes
Spart Bytes, indem nur mit ints gearbeitet wird.
quelle
sizeof...
.Rust, 57 Bytes
Erläuterung:
Prüfung:
quelle
PHP, 35 Bytes
manueller Eintrag
quelle
Common Lisp , 28 Bytes
Probieren Sie es online!
quelle
Addiere ++ , 3 Bytes
Probieren Sie es online!
quelle
PHP, 11 Bytes
Probieren Sie es online aus: 1 Eingang | 3 Eingänge
quelle
Batch,
5049 BytesKein eingebautes Batch, also müssen wir auf die alte Schule gehen. 1 Byte dank @IsmaelMiguel gespeichert. Ausgabe über Exit-Code oder Speicherung von 3 Bytes, wenn die Ausgabe über die globale Variable gültig ist. Beispiel für die Verwendung in einem vollständigen Programm:
quelle
:a|set r=0&for %%a in (%*)do set/ar+=1
(|
= Newline im Windows-Stil). Diese Lösung ist 38 Bytes. Um es auszuführen, machecall :a <args>
mit agoto :eof
vor der Funktion, was der Wert ist, der in der Variablen verfügbar istr
. Wenn Sie Ihre Lösung behalten möchten, entfernen Sie/a
die ersteset
und entfernen Sie diese@
.x86-Maschinencodefunktion mit 32 Bit (i386), 13 Byte
Aufrufkonvention: i386 System V (Stapelargumente), mit einem NULL-Zeiger als Sentinel / Terminator für das Ende der Argumentliste . (Clobbers EDI, entspricht sonst SysV).
C (und asm) übergeben keine Typinformationen an verschiedene Funktionen. Daher kann die OP-Beschreibung der Übergabe von Ganzzahlen oder Arrays ohne explizite Typinformationen nur in einer Konvention implementiert werden, die eine Art Struktur- / Klassenobjekt (oder Zeiger auf ein solches Objekt) übergibt ), keine ganzen Zahlen auf dem Stapel. Daher habe ich angenommen, dass alle Argumente Nicht-NULL-Zeiger sind und der Aufrufer ein NULL-Abschlusszeichen übergibt.
Eine NULL-terminierte Zeigerliste von Argumenten wird in C tatsächlich für Funktionen wie POSIX verwendet
execl(3)
:int execl(const char *path, const char *arg, ... /* (char *) NULL */);
C erlaubt keine
int foo(...);
Prototypen ohne festes Argument,int foo();
bedeutet aber dasselbe: Argumente, die nicht spezifiziert sind. (Anders als in C ++, wo es bedeutetint foo(void)
). In jedem Fall ist dies eine asm Antwort. Einen C-Compiler zu überreden, diese Funktion direkt aufzurufen, ist interessant, aber nicht erforderlich.nasm -felf32 -l/dev/stdout arg-count.asm
Einige Kommentarzeilen wurden entfernt.Die Frage zeigt, dass die Funktion in der Lage sein muss, 0 zurückzugeben, und ich entschied mich, dieser Anforderung zu folgen, indem ich den abschließenden NULL-Zeiger nicht in die Anzahl der Argumente einbezog. Dies kostet jedoch 1 Byte. (Entfernen Sie für die 12-Byte-Version die LEA und kommentieren Sie die
scasd
äußere Schleife und diexchg
, aber nicht diedec edx
. Ich habe die LEA verwendet, weil sie die gleichen Kosten wie die anderen drei Anweisungen zusammen verursacht, aber effizienter ist, sodass die Funktion geringer ist.) uops.)C-Aufrufer zum Testen :
Gebaut mit:
-fcall-used-edi
ist sogar bei -O0 erforderlich, um gcc anzuweisen, davon auszugehen, dass Funktionen nicht gespeichertedi
/ wiederhergestellt werden, da ich so viele Aufrufe in einer C-Anweisung (demprintf
Aufruf) verwendet habe, die sogar-O0
EDI verwendet hat. Es scheint sicher zu seinmain
, dass GCCs EDI von ihrem eigenen Aufrufer (im CRT-Code) unter Linux mit glibc blockieren, aber ansonsten ist es völlig falsch, mit verschiedenen kompilierten Codes zu mischen / abzugleichen-fcall-used-reg
. Es gibt keine__attribute__
Version, mit der wir die asm-Funktionen mit anderen als den üblichen benutzerdefinierten Aufrufkonventionen deklarieren könnten.Zwei andere Versionen kamen ebenfalls mit 13 Bytes an: Diese basiert auf
loopne
einem Wert, der um 1 zu hoch ist.Diese Version verwendet rep scasd anstelle einer Schleife, verwendet aber das Argument count modulo 256. (Oder begrenzt auf 256, wenn die oberen Bytes von
ecx
0 bei der Eingabe sind!)Komisch, noch eine weitere Version basierend auf
inc eax
/pop edx
/test edx,edx
/jnz
kamen 13 Bytes in an. Es ist eine Callee-Pops-Konvention, die von C-Implementierungen niemals für verschiedene Funktionen verwendet wird. (Ich habe die ret-Adresse in ecx und jmp ecx anstelle von ret eingefügt. (Oder push / ret, um den Prädiktorstapel für die Rücksprungadresse nicht zu unterbrechen.)quelle
R , 20 Bytes
Probieren Sie es online!
R hat genau dafür eine Funktion .
quelle
JavaScript, 35 Bytes
quelle
Blumenkohl , 16 Bytes
Probieren Sie es online!
quelle