มีการโต้แย้งกี่ครั้ง?


33

ใช้ภาษาที่คุณเลือกเขียนฟังก์ชันที่รับจำนวนตัวแปรที่มีข้อโต้แย้งและส่งกลับจำนวนอาร์กิวเมนต์ที่ถูกเรียกด้วย

ข้อมูลจำเพาะ:

  • ภาษาของคุณจำเป็นต้องรองรับฟังก์ชั่นการโต้แย้งแบบแปรปรวน: สิ่งที่เรียกได้ซึ่งรับจำนวนอาร์กิวเมนต์โดยพลการและส่งคืนค่า
  • พารามิเตอร์จะต้องสามารถส่งผ่านเป็นรายบุคคล ซึ่งหมายความว่าการส่งผ่านอาร์เรย์จะนับสำหรับพารามิเตอร์เดียวเท่านั้น คุณสามารถใช้อาร์เรย์ "อาร์กิวเมนต์ที่ผ่านทั้งหมด" หากภาษาของคุณรองรับ ข้อ จำกัด คือวิธีการเรียกใช้ฟังก์ชัน
  • รหัสที่เรียกฟังก์ชันนี้จะต้องไม่ถูกต้องผ่านการจำนวนของการขัดแย้งในแหล่งที่มาของ หากคอมไพเลอร์แทรกจำนวนของอาร์กิวเมนต์เป็นส่วนหนึ่งของการประชุมที่เรียกว่าได้รับอนุญาต
  • อาร์กิวเมนต์สามารถเป็นประเภทใดก็ได้ที่คุณต้องการ คุณสามารถรองรับได้เพียงประเภทเดียว (เช่นการสนับสนุนเท่านั้นที่intยังคงใช้ได้) ประเภทโดยพลการ (ประเภทของอาร์กิวเมนต์ที่ได้รับอนุญาต) หรือการรวมกันของประเภทอาร์กิวเมนต์ (เช่นอาร์กิวเมนต์แรกคือintส่วนที่เหลือเป็นสตริง)
  • ฟังก์ชันของคุณอาจมีจำนวนอาร์กิวเมนต์สูงสุด (โดยเฉพาะอย่างยิ่งเนื่องจากทรัพยากรมี จำกัด ) แต่ต้องสนับสนุนอาร์กิวเมนต์อย่างน้อย 2รายการ

ตัวอย่าง:

  • f() ผลตอบแทน 0
  • f(1)หรือf("a")ผลตอบแทน1
  • f([1, 2, 3])ส่งคืน1เนื่องจากส่งผ่านอาร์เรย์ไม่ใช่อาร์กิวเมนต์ 3 ข้อ
  • f(1, 10)หรือf(1, "a")ผลตอบแทน2

เช่นนี้คือ code-golf ทางออกที่ชนะคือทางเลือกที่ใช้จำนวนไบต์น้อยที่สุด


4
มันยังไม่ชัดเจน (อย่างเป็นกลาง) อะไรคือ "ฟังก์ชัน", "ค่าส่งคืน" หรือ "อาร์กิวเมนต์ Variadic" ตัวอย่างเช่นฟังก์ชั่น Dodos จะถือเป็น monadic หรือ variadic หรือไม่?
user202729

24
@ user202729 หากภาษาของคุณไม่รองรับฟังก์ชั่นใช้ภาษาอื่น ไม่ใช่ข้อกำหนดที่ทุกภาษาสามารถแข่งขันได้ส่วนหนึ่งของการเล่นรหัสคือการหาเครื่องมือที่เหมาะสมสำหรับงาน
Sanchises

5
@ user202729 ฉันไม่มีปัญหากับความท้าทายเป็นครั้งคราวที่มุ่งเน้นภาษาดั้งเดิม / ระดับสูงเช่นเดียวกับที่เรามีความท้าทายตามโอกาสที่เป็นไปได้ในภาษาที่ผิดปกติเท่านั้น
Sanchises

6
ไม่ทราบว่าเราต้องแก้ปัญหาที่ลังเลลักษณะภาษาที่จะมีความท้าทายที่ชัดเจน ....
Conor โอไบรอัน

5
หากภาษาของคุณไม่มีแนวคิดเกี่ยวกับการโต้แย้ง / การเรียกแบบนั้นมันก็ไม่เหมาะสมกับเกณฑ์การสนับสนุนจำนวนอาร์กิวเมนต์โดยพลการ
เกล็นสมิ ธ

คำตอบ:


15

Amstrad CPC Z80 การโทรแบบไบนารีจาก BASIC, 1 ไบต์, การเข้ารหัสฐานสิบหก

C9          : RET

(เช่นรุ่น 2 และ 5 ไบต์ดูด้านล่าง)

เมื่อเข้าสู่การโทรจำนวนพารามิเตอร์ที่ส่งผ่านจะอยู่ในการAลงทะเบียน โค้ดจะส่งคืนทันที ไม่มีแนวคิดของค่าตอบแทนใน Z80 เพียงเข้าและออกจากรัฐ ค่าเป็นเพียง "มี" เข้าถึงได้ในการลงทะเบียนเนื่องจากรหัสไม่มีการเปลี่ยนแปลงเงื่อนไขการป้อนข้อมูลยกเว้นPC(ตัวนับโปรแกรม) และSP(ตัวชี้สแต็ก) อย่างไรก็ตามค่าในAไม่สามารถเข้าถึงได้โดย BASIC และถูกเขียนทับเกือบจะในทันที

ตัวอย่าง:

CALL &8000, "Hello", "World"

A = 2

CALL &8000, 42

A = 1

CALL &8000

A = 0


ตามคำขอนี่คือรหัสบางส่วนที่ทำให้ค่าสามารถเข้าถึงได้ในภาษาเบสิก ฉันประหลาดใจมากที่พบว่าสามารถทำได้ใน 5 ไบต์เท่านั้น:

รหัสเครื่อง:

12          : LD   (DE), A
13          : INC  DE
AF          : XOR  A
12          : LD   (DE), A
C9          : RET

ในรายการ:

  • AF - การลงทะเบียนตัวสะสมและแฟล็ก (ถือว่าเป็นรีจิสเตอร์ 8 บิตสองตัว)
    • A มีจำนวนพารามิเตอร์ที่ส่งผ่านสูงสุดถึง 32 พารามิเตอร์
    • Fผมไม่แน่ใจว่าสิ่งที่อยู่ใน แต่ดูเหมือนว่ามันมีธง RESET เพื่อยกเว้นสองธงไม่ได้กำหนดซึ่งมีทั้ง0 ธง (ศูนย์) ตั้งถ้ามีไม่มีพารามิเตอร์ผ่าน1Z1
  • BC
    • B- 32 ลบจำนวนพารามิเตอร์ ( A+ B= 32)
    • C - &FF
  • DE - ที่อยู่ของพารามิเตอร์สุดท้ายหรือที่อยู่การโทรหากไม่มีการส่งผ่านพารามิเตอร์
  • HL - ที่อยู่ของไบต์แรกหลังจากคำสั่งโทเค็น BASIC ที่ถูกดำเนินการในปัจจุบัน (ไม่ว่าจะเป็นโปรแกรมหรือในโหมดคำสั่งทันที)
  • IX - ที่อยู่สแต็กของตัวชี้ไปยังพารามิเตอร์สุดท้าย
  • IY - &0000

รหัส

  1. Loa Ds อยู่ที่ชี้ไปตามDEที่มีค่าในA
  2. INCrements DE
  3. XORs A(กับA), การให้&00
  4. Lo Dค่าในAที่อยู่ที่ชี้ไปตามDE
  5. RETโกศ

เมื่อออก:

  • Aถูกทำลาย (มันเสมอ&00)
  • DE ถูกทำลาย (มักสูงกว่าทางเข้าเสมอ)
  • การลงทะเบียนอื่น ๆ ทั้งหมดจะถูกเก็บรักษาไว้

พื้นฐาน

Amstrad basic มีเพียงสามชนิดของข้อมูลรวมถึงอาร์เรย์ที่เรียบง่าย โดยค่าเริ่มต้นตัวแปรพื้นฐานทั้งหมดเป็นจริง (ลายเซ็นต์, mantissa 32 บิต, เลขยกกำลัง 8 บิต) ซึ่งสามารถทำให้ชัดเจน!ได้ สำหรับการใช้ INTEGER (เซ็นชื่อ, 16 บิต) %และสำหรับความยาวของสตริง STRING (1 ไบต์, ข้อมูลอักขระสูงสุด 255 ไบต์, ความปลอดภัยไบนารี) ใช้$:

  • x - REAL (โดยนัย)
  • x! - REAL (ชัดเจน)
  • x% - จำนวนเต็ม
  • x$ - STRING

นอกจากนี้คุณยังสามารถใช้DEFINT, DEFREALและDEFSTRมีตัวอักษรเดียวหรือช่วงของสองตัวอักษรเดียวเพื่อระบุชนิดเริ่มต้นสำหรับตัวแปรทั้งหมดเริ่มต้นด้วยตัวอักษรที่คล้ายกับ FORTRAN

  • DEFSTR a
  • DEFINT x-z

ขณะนี้:

  • a - STRING (โดยนัย)
  • i - REAL (โดยนัย)
  • x - จำนวนเต็ม (โดยนัย)
  • x$ - STRING (ชัดเจน)

ประเภทที่ง่ายที่สุดในการทำงานคือจำนวนเต็ม รหัสเครื่องคาดว่าพารามิเตอร์สุดท้ายจะส่งผ่านตามที่อยู่ไม่ใช่ค่าซึ่งเป็นสาเหตุที่@นำหน้าตัวแปร ตัวแปรส่งคืนถูกนับเป็นหนึ่งในCALLพารามิเตอร์ s

รหัสเครื่องจะถูกเรียกดังต่อไปนี้จาก BASIC (สมมติว่ามันโหลดลงในหน่วยความจำตามที่อยู่&8000):

CALL &8000, "Hello", "World", 42, @n%

n% = 4

n%นี้มักจะให้ผลที่ถูกต้องโดยไม่คำนึงถึงค่าเริ่มต้นของ

สำหรับรุ่น 2 ไบต์ที่เก็บรักษาการลงทะเบียนทั้งหมด:

CALL &8003, "Hello", "World", 42, @n%

n% = 4

นี้ข้ามสามไบต์แรกและเพียง แต่ช่วยให้ผลที่ถูกต้องถ้าค่าเริ่มต้นของการn%เป็น-0 255วิธีนี้ใช้งานได้เพราะ Z80 นั้นเป็น endian น้อย

พารามิเตอร์การส่งคืนจะต้องเริ่มต้นก่อนที่จะผ่านมิฉะนั้น BASIC จะโยนImproper argumentข้อผิดพลาด ในภาพด้านล่างฉันกำลังพิมพ์ (ด้วยช็อตคัต?เนื่องจากฉันเล่นกอล์ฟสาธิตด้วย!) ค่าส่งคืนก่อนและหลังการโทรเพื่อแสดงการเปลี่ยนแปลงค่า ฉันกำลังใช้ค่า&FFFFเพราะนั่นคือการแทนเลขฐานสองของ-1จำนวนเต็มที่ลงนาม นี้แสดงให้เห็นว่าโปรแกรม 5 ไบต์ได้อย่างถูกต้องเขียนทั้งไบต์ขณะที่โปรแกรม 2 &00ไบต์เพียงเขียนไบต์ต่ำและสันนิษฐานว่าไบต์สูงอยู่แล้ว

enter image description here


ดังนั้นแบบแผนการโทรที่คุณใช้ค่าส่งคืนเป็นอย่างไร ถ้ามันไม่ส่งคืนพวกเขาในการสะสมหรือเลยคำตอบของคุณคือการประดิษฐ์แบบแผนการโทรที่กำหนดเองซึ่งแก้ปัญหาให้คุณได้ (โดยการเพิ่มรีจิสเตอร์กลับแทนที่จะส่งผ่านตัวชี้ที่คุณสามารถจัดเก็บAได้ วิธีที่คุณสามารถทำได้จาก BASIC) ไม่ใช่ว่ามีอะไรผิดปกติกับสิ่งนั้น แต่มันอาจเป็นคำตอบที่น่าสนใจมากขึ้นในการทำตามแผนการประชุมที่มีอยู่
Peter Cordes

@PeterCordes ทั้ง Amstrad BASIC และ Z80 ไม่มีแนวคิดเรื่องขอบเขต ค่าทั้งหมดเป็นค่าส่วนกลางและสามารถเข้าถึงได้ทันทีจนกว่าจะถูกทำลาย ค่าของAเหมือนกันทันทีหลังจากการRETเรียนการสอน อายุการใช้งานของค่าในAสั้นมากเนื่องจากเป็นค่าสะสม x = CALL &8000, 42ไม่มีสิ่งดังกล่าวเป็นเป็น มันจะต้องมีCALL &8000, x, 42และรหัส Z80 พิเศษ แต่แล้วxจะไม่2 1
CJ Dennis

ฉันคิดว่ามันดีถ้าคุณรวมเอาท์พุทหาเรื่องในการนับมิฉะนั้นมีคำสั่งลดลง 1 ไบต์ไม่ได้มี? ฉันสนใจที่จะเห็นรุ่นที่ใช้งานได้จริงจาก BASIC แทนที่จะเป็นเรื่องเล็กน้อย
Peter Cordes

1
@PeterCordes เรียบร้อยแล้ว! โอ้ฉันลืมที่จะพูดไม่เรียกมันโดยที่ไม่มีพารามิเตอร์เพราะมันจะเขียนทับคำสั่งสองคำแรกของตัวเองด้วย&00s - NOPno-ops สามารถเพิ่มไบต์อื่นเพื่อให้ปลอดภัยยิ่งขึ้น แต่แน่นอนว่าไม่มีพารามิเตอร์ส่งคืนจะไม่สามารถตั้งค่าอะไรได้
CJ Dennis

32

Java (JDK 10) , 11 ไบต์

a->a.length

ลองออนไลน์!


29
การตีชวาจาวาสคริปต์เป็นเรื่องยากที่จะสังเกตเห็น
คนที่แต่งตัวประหลาดสุ่ม

3
@Therandomguy สิ่งนี้ต้องการสิ่งที่ต้องการinterface x{void f(Object...a);}กำหนดและแลมบ์ดานี้ต้องถูกเก็บไว้ในตัวแปรของประเภทอินเตอร์เฟสหรือถูกส่งผ่านไปยังวิธีการที่คาดว่าจะเป็นประเภทอินเตอร์เฟสดังนั้นฉันจึงไม่แน่ใจว่าจะนับสำหรับความท้าทายนี้ (แม้ แต่มักจะ lambdas java มีที่ได้รับอนุญาตในความท้าทาย codegolf)
SamYonnou

3
@ SamYonnou ไม่มีความแตกต่างกับ lambdas อื่น ๆ และอย่างที่คุณพูดถึงlambdas นั้นใช้ได้
Olivier Grégoire

@ OlivierGrégoireฉันรู้ว่า lambdas ได้รับอนุญาตประเด็นของฉันคือเมื่อเทียบกับ JavaScript เช่นคุณต้องมีรหัสพิเศษมากขึ้นในการตั้งค่าแม้ว่าคุณจะใช้สิ่งที่ต้องการ REPL และหลีกเลี่ยงความต้องการหลัก / วิธีการ ( ความจำเป็นในการอินเตอร์เฟซที่จะกำหนดไว้เป็นสิ่งที่แตกต่างจากจาวาสคริปต์)
SamYonnou

@ OlivierGrégoire: ฉันรู้จัก Java บ้าง แต่ก็ยังไม่ทันรู้ตัวเลย ฉันสนใจที่จะเห็นความคิดเห็นของ Sam เกี่ยวกับสิ่งที่หม้อไอน้ำกำลังถูกกวาดใต้พรมในคำตอบของจาวาที่ทำให้มันสั้นจริง ๆ ฉันยอมรับมันควรได้รับอนุญาต (แม้ว่ามันจะให้บางสิ่งบางอย่างที่คุณไม่ได้รับด้วยฟังก์ชั่นจาวาที่ถูกต้องดังนั้นมันไม่ได้เป็นเพียงแค่การลดจำนวนต้นแบบที่ให้คุณนับจำนวนในตัว) นอกจากนั้นยังน่าสนใจในการตอบกลับ "Java beating JS"
Peter Cordes

25

JavaScript ขนาด 15 ไบต์

[].push.bind(0)

Array.prototype.pushฟังก์ชั่นใช้เวลาจำนวนของการขัดแย้งใด ๆ เพิ่มลงในอาร์เรย์และผลตอบแทนขนาดของอาร์เรย์ ดังนั้นฟังก์ชั่นที่ใช้บนอาร์เรย์ที่ว่างเปล่ากลับจำนวนของข้อโต้แย้งที่จ่ายให้กับpushpush

f = [].push.bind(0)

f(10,2,65,7)
> 4

f()
> 0

.bind(0)เพียงแค่ให้pushฟังก์ชั่นการแก้ไขthisค่าเพื่อที่จะสามารถเก็บไว้ในตัวแปร ในความเป็นจริงตัวระบุขนาด 7 ไบต์[].pushสามารถใช้งานได้อย่างแท้จริง (แต่ไม่ได้กำหนด) โดยไม่ต้องbind:

[].push(10,2,65,7)
> 4

[].push()
> 0


18

Haskell , 108 107 95 94 ไบต์

class T r where z::Int->r
instance T Int where z=id
instance T r=>T(a->r)where z n _=z$n+1
z 0

ลองออนไลน์!

นี่เป็นเรื่องยากที่จะทำงาน แต่ฉันก็สนุกที่ได้พยายามหาวิธีที่จะนำสิ่งที่น่าสนใจไปใช้ในภาษาที่จำเป็น


ประณามคุณเอาชนะฉันไป fเป็นตัวเลือกถ้าคุณบอกว่าz 0เป็นฟังก์ชั่นโดยไม่ต้องมีผลผูกพันดังนั้นmain = print $ ((z 0) pi 0 () [] :: Int)งาน
อัง

และโดยที่ฉันหมายความว่าประเภททำงานเมื่อใช้เป็นฟังก์ชั่นที่ไม่ระบุชื่อดังนั้นคุณสามารถลบทุกอย่างออกจากแถวสองแถวสุดท้ายยกเว้นz 0
Angs

ดีมากขอบคุณ! ปรากฎว่าฉันทำสิ่งผิดปกติเมื่อฉันทดสอบฟังก์ชั่นนิรนาม ลองตัวอย่างของคุณแล้วใช้งานได้ดี
user9549915

ผมคิดว่าควรจะนับในการนับไบต์เนื่องจากชนิดของคำตอบที่จะต้องมีการประกาศไม่ช้าก็เร็วเหมือนใน::Int main = print $ ((z 0 :: Double -> Integer -> () -> [a] -> (Int->Int->Int) -> IO () -> Int) pi 0 () [] (+) main)ฉันยังคิดว่ามันใช้งานได้เฉพาะในช่วงเวลารวบรวมดังนั้นสิ่งที่ชอบfoldl(\a b->a b) (z 0) $ [1..5])::Intไม่สามารถทำงานได้ ไม่ว่าจะด้วยวิธีใดนี่เป็นสิ่งที่ยอดเยี่ยม
อัง

2
s/imperative/non-curry/
user202729


12

Zsh , 7 5 ไบต์

<<<$#

ลองออนไลน์!


แม้ว่ามันควรจะถูกห่อ:f(){ echo $#; }
muru

8
@muru ดูดีเหมือนโปรแกรมเต็มสำหรับฉัน
Neil

แม้ว่าตอนนี้ฉันเห็นแล้วว่า OP ต้องการเพียงแค่ฟังก์ชั่นเท่านั้น ...
Neil

2
@ เชลล์สคริปต์สคริปต์ทำหน้าที่เหมือนกับฟังก์ชัน OP ไม่ชัดเจนในสิ่งที่ฟังก์ชั่นฉันอ้างว่าการส่งของฉันเป็นเพียงฟังก์ชั่นที่บันทึกไว้ในดิสก์
Pavel

9

Brain-Flakขนาด 6 ไบต์

โซลูชัน Brain-Flak ครั้งแรกของฉันมีค่าสำหรับการโพสต์ฉันคิดว่ามันเป็นเครื่องมือที่เหมาะสมสำหรับงานนี้:

([]<>)

ลองออนไลน์!

คำอธิบาย

เมื่อรันโปรแกรม Brain-Flak ขั้นแรกสแต็กด้านซ้ายจะมีอาร์กิวเมนต์ทั้งหมด จากตรงนั้นมันเป็นเพียงเรื่องของ:

(      -- push the following..
 []    --   height of the stack (ie. # of arguments)
   <>  -- ..to the other stack  (toggles to the other stack)
)      --
       -- the right stack now contains the # of arguments which
       -- gets printed implicitly

7

ภาษา Wolfram (Mathematica)ขนาด 11 ไบต์

Tr[1^{##}]&

ลองออนไลน์!

แนะนำโดย JungHwan Min ข้อ จำกัด บางอย่าง (อินพุตต้องเป็นรูปสี่เหลี่ยมผืนผ้า) แต่เราไม่จำเป็นต้องจัดการอินพุตโดยพลการ

11 ไบต์

Length@!##&

ลองออนไลน์!

อีกโซลูชัน 11 ไบต์แนะนำโดย Martin Ender ดูเหมือนว่าจะเกิดข้อผิดพลาดเมื่อไม่มีอินพุตเดียว แต่ก็ยังส่งคืนค่าที่ถูกต้องในทุกกรณี

12 ไบต์

Length@{##}&

ลองออนไลน์!

ทางออกเดิมของฉัน

ใน Mathematica ##หมายถึงจำนวนอาร์กิวเมนต์ต่าง ๆ ในฟังก์ชัน {และ}ตัดคำเหล่านั้นในรายการและLength@ใช้ความยาวของรายการนี้ &ในตอนท้ายจะทำให้สิ่งนี้กลายเป็นฟังก์ชั่นจริง


7

R , 30 ไบต์

function(...)length(list(...))

ลองออนไลน์!


1
function(...)nargs()คือ 20 ไบต์ แต่การใช้length(...)เป็นวิธีเริ่มต้นของฉันจนกว่าฉันจะได้nargsฟังก์ชันแบบเหมือน
จูเซปเป้

@Giuseppe อืมฉันพยายามแปลงlist(...)เป็นตรรกะดังนั้นsum()สามารถนำมาใช้ แต่นั่นเป็นเรื่องยาก: /
JAD

1
ฮ่าฮ่าอย่าพยายาม
ล่อลวง

1
@RoryT โอ้จริงแล้วเอกสาร R บอกว่ารวมกัน Nevermind: D
JAD

2
...length() ทำสิ่งเดียวกันกับlength(list(...))
จูเซปเป้

7

Bash ขนาด 12 ไบต์ (ขอบคุณ paxdiablo สำหรับการบันทึก 4)

n()(echo $#)

คัดลอกและวางที่พรอมต์ bash จากนั้นเรียกใช้ฟังก์ชัน n จากพรอมต์:

$ n
0
$ n 46 gr 3443 dad
4
$ n 4fwj23 wrw jdwj 00998 34 eyt q3 vg wq j qw
11

2
ยินดีต้อนรับสู่ PPCG!
Martin Ender

คุณสามารถบอกได้ไหมว่ามันเป็นสคริปต์ "./n" และไม่ใช่ฟังก์ชั่น? แล้วมันก็เป็นเพียง: echo $#7 ไบต์ (จะเป็นเชลล์ที่คุณใช้เพื่อเปิดสคริปต์ "./n" ด้วยเช่นคุณรัน bash แล้วเมื่อคุณ: ./n arg1 ... argnมันจะถูกตีความโดย bash)
Olivier Dulac

@Olivier Dulac ความท้าทายพูดได้ชัดว่าฟังก์ชั่น
Wastrel

7

C ++ 14 (gcc) , 34 ไบต์

เป็นฟังก์ชั่นแลมบ์ดา variadic ทั่วไป (ต้องใช้ C ++ 14):

[](auto...p){return sizeof...(p);}

ลองออนไลน์!

คำตอบก่อนหน้า (ไม่ถูกต้อง): 32 ไบต์

มันหายไปtemplate<class...T>และ(p)

int f(T...p){return sizeof...p;}

6
C ++ 14, C ++ 11 ไม่มี lambdas ทั่วไป
เควนติน

1
คุณสามารถเพิ่มค่าสถานะอนุญาตให้ลบวงเล็บได้p (และ-wปิดการเตือน)
nwp

@nwp: -fpermissiveคุณไม่ต้องเสียค่าใช้จ่าย 12 ไบต์สำหรับตัวเลือกนั้นใช่ไหม หากไม่ใช่มาตรฐาน ISO C ++ หรือ GNU C ++
Peter Cordes

@PeterCordes มันอาจเป็นไปได้และมีจุดมุ่งหมายเพื่อหลีกเลี่ยงการแก้ปัญหา 0 ไบต์ขนาดเล็กสำหรับทุกสิ่งโดยการส่งโปรแกรมผ่านทางบรรทัดคำสั่ง ฉันไม่ได้คิดเกี่ยวกับเรื่องนี้ที่นี่เพราะดูเหมือนว่าจะไม่เหมาะสม
nwp

แก้ไข @Quentin -> C ++ 14
Bierpfurz


5

ระดับแปดเสียง 9 ไบต์

@()nargin

ลองออนไลน์!

ฟังก์ชั่นที่ไม่ระบุชื่อการจำนวนของการขัดแย้งใด ๆ (และเงียบทิ้งจำนวนมาก) narginและเอาท์พุทจำนวนของการขัดแย้งผ่านในตัว สิ่งนี้ไม่สามารถใช้งานได้ใน MATLAB ซึ่งคุณจะต้องvararginอนุญาตให้มีข้อโต้แย้งมากมาย


5

Perl 6 , 5 ไบต์

ขอบคุณ@Joshuaสำหรับ -5 ไบต์

{+@_}

ลองออนไลน์!


คุณสามารถทำได้{+@_}
Joshua

@Joshua> _> จริงขอบคุณ
เท่านั้น

คุณสามารถลบsubใน Perl 6 (ไม่ได้อยู่ใน Perl 5)
nwellnhof

@nwellnhof โอ้โห Perl 6 แตกต่างจาก Perl 5> _>
ASCII เท่านั้นเท่านั้น

4

Perl 5 , 9 ไบต์

sub{~~@_}

ลองออนไลน์!


การค้นหาคำตอบทั่วทั้งไซต์อย่างรวดเร็วดูเหมือนจะบ่งบอกว่าคุณสามารถออกจากsub
ASCII เท่านั้น

2
Protip: TIO ให้คุณคัดลอกในรูปแบบโพสต์ PPCG (ESC, S, G)
เท่านั้น

@ ASCII เท่านั้นโอ้ดีมากขอบคุณ! :) สำหรับการออกไปsubฉันไม่คิดอย่างนั้น มันไม่ใช่ฟังก์ชั่นที่ไม่มีมัน
Chris

@ ASCII เท่านั้นฉันจะพิจารณาคำตอบอย่างไม่subถูกต้องเนื่องจากผลลัพธ์ไม่ใช่สิ่งที่คุณสามารถโทรหาหรือมอบหมายให้กับตัวแปรได้
Ton Hospel

4

PHP, 34 ไบต์

function(...$a){return count($a);}

ทำได้ดีนี่! ทางเลือกสำหรับ PHP 5.6 และเก่ากว่าคือfunction(){return func_num_args();}(35 ไบต์โพสต์ด้านล่าง)
Ismael Miguel

@IsmaelMiguel หนึ่งนี้ยังทำงานใน PHP 5.6
axiac

1
คุณควรจะกล่าวถึงนี้จะทำงานเฉพาะใน PHP 5.6 และใหม่กว่า
axiac

@axiac คุณพูดถูกฉันไม่ดี กำลังคิดเกี่ยวกับ PHP5.5
Ismael Miguel

4

C # .NET, 11 ไบต์

a=>a.Length

ลองออนไลน์

คำอธิบาย:

ใน C # .NET objectใช้สำหรับอาร์กิวเมนต์ที่มีหลายประเภทโดยอนุญาตให้หนึ่งผ่านจำนวนเต็มสตริงอักขระ ฯลฯ เป็นอินพุตที่เป็นไปได้ ตัวอย่างเช่น:

// Can be called like: `F(2)`, `F("test")`, `F('a')`, etc.
void F(object arg){ ... }

C # .NET สามารถมีขนาดอาร์กิวเมนต์ที่เลือกได้ ตัวอย่างเช่น:

// Can be called like: `F()`, `F(2)`, `F("test")`, `F('a')`, etc.
void F(object arg = null){ ... }

และก็มี varargs ซึ่งเป็นจำนวนอาร์กิวเมนต์ที่ไม่จำเป็นซึ่งไม่ได้กำหนด (ซึ่งเป็นสิ่งที่ฉันใช้ในคำตอบนี้) ตัวอย่างเช่น:

// Can be called like: `F()`, `F(2)`, `F(2, "test", 'a')`, etc.
void F(params object[] args){ ... }

โดยปกติแลมบ์ดาจะถูกสร้างเช่นนี้:

System.Func<object[], int> F f = a=>a.Length;
// A call like `f(new object[]{2, "test", 'a'))` will return 3 (size of the input array)

แต่น่าเสียดายที่System.Funcไม่รองรับparamsvarargs ดังนั้นฉันจะต้องสร้างdelegateแทน:

delegate int F(params object[] args);
F f = a=>a.Length;
// A call like `f()` will return 0, and `f(2, "test", 'a')` will return 3

คำตอบของฉันสำหรับความท้าทายนี้คืออะไรและสามารถพบได้ในรหัสทดสอบ TIO ที่เชื่อมโยง


ข้อ จำกัด เพียงอย่างเดียวคือการป้อนที่เกิดขึ้นจริงobject[]เช่นf(new object[]{1,2,3})จะมีผลใน 3 แทน 1. f(new int[]{1,2,3})จะยังคงส่งผลใน 1 เพราะมันตีความเป็นหนึ่งเดียวint[] objectจะมีพารามิเตอร์ที่จะตีความว่าเป็นวัตถุเดียวเช่นกันที่จะสามารถออกเสียงลงไปยังวัตถุเช่นนี้:object[]f((object)new object[]{1,2,3})


ฉันต้องบอกว่าถ้ามีคำตอบที่เคยทำให้ฉันสนับสนุนรวมถึงแลมบ์ดาที่เกี่ยวข้องกับแลมบ์ดาในคำตอบ C # มันน่าจะเป็นอันนี้ ... แต่มันเป็นทางออกที่ถูกต้องแน่นอน
Kamil Drakari

@KamilDrakari บางทีมันอาจไม่ชัดเจนว่าฉันทำอะไรโดยไม่เปิด TIO-link ดังนั้นฉันจึงได้เพิ่มคำอธิบาย
Kevin Cruijssen

1
@Taemyr ฉันพยายามหาวิธีแก้ปัญหา แต่โชคไม่ดีที่ไม่มีผู้ใดสำหรับ C # .NET ยกเว้นใด ๆ หล่อobject[]พารามิเตอร์เช่นนี้object f((object)new object[]{1,2,3});ไม่มีทางแยกความแตกต่างระหว่างf(new object[]{1,2,3});และf(1,2,3);เท่าที่ฉันสามารถหาได้
Kevin Cruijssen

1
สิ่งนี้จะจัดการกับพารามิเตอร์อาเรย์อย่างถูกต้องเพื่อให้ได้จุดโทษจำนวนมาก อาจมีโครงสร้างที่กระชับกว่าที่สามารถจัดการได้ แต่มันใช้งานได้ในการทดสอบของฉัน
Kamil Drakari

1
@ KamilDrakari อืม แต่มันก็ล้มเหลวf(1, new object[]{1,2,3})อีกครั้ง ไม่แน่ใจว่าจะหาวิธีแก้ปัญหาสำหรับพฤติกรรมนี้ได้หรือไม่
Kevin Cruijssen

4

Dodos, 32 31 bytes

f
	dot i f dab
i
	
	dip dot dab

Try it online!

Uses Dennis' increment function.

Explanation

f                     # definition of f - target function
        dot i f dab   # sum of j(f(all args but first)). recurses until it has 0 args
i                     # definition of i - returns (arg, 1) given 1 arg
                      # arg
        dip dot dab   # 1 (dot dab on list of length 1 returns 0, dip returns |0 - 1|)

Alternatively, 32 bytes without recursion in target function (thanks @Leo)

	dot i
i
	dip dot dab dot
	i dab

Try it online!

Explanation

        dot i             # anonymous function: sum of i(args)
                          # here this becomes implicit main
i                         # definition of i - returns a list with all arguments replaced with 1
        dip dot dab dot   # 1 (dab dot returns empty list, dot returns 0, dip returns |0 - 1|
        i dab             # list concatenated with i(all args but first)

Here's another same-length solution Try it online! I can't seem to understand why yours works though, could you add an explanation please?
Leo

Hey, you added an explanation to my solution! I wanted one for yours, I know how mine works xD
Leo

1
@Leo sorry for late reply, idek what I'm doing, just copied Dennis' function, will try to understand asap. I had no idea how dodos works so I figured out what yours did first
ASCII-only

No worries, it was just a funny situation :)
Leo

@Leo ok so does my explanation make sense? (note: I'm on mobile so feel free to edit it to make it better lol)
ASCII-only


3

Rust, 57 bytes

macro_rules!f{()=>{0};($($x:expr),+)=>{[$($x),+].len()};}

Explanation:

macro_rules! f {         // define a macro called f
    () => {0};           // when called without arguments, expand to 0
    ($($x:expr),+) => {  // when called with 1 or more comma seperated arguments
        [                // rust uses [a, b, c] to make an array
            $($x),+      // expand to the arguments seperated with a comma
        ]                
        .len()           // take the length of that.
    };
}

Test:

fn main() {
    println!("{:?}", f!());                // prints 0
    println!("{:?}", f!(4));               // prints 1
    println!("{:?}", f!(5, 2));            // prints 2
    // works with anything, as long as you dont mix things
    println!("{}", f!("", "a", "hello"));  // prints 3
}




2

PHP, 11 bytes

<?=$argc-1;

Try it online: 1 input | 3 inputs


I'm not so sure about this one (and it's validity) since it is the count of arguments passed to call PHP.
Ismael Miguel

@IsmaelMiguel, see this consensus.
Shaggy

1
The question explicitly requires a function that returns the number, does not display it: "...write a function that takes a variable number of arguments and returns the number of arguments."
axiac

1
Re-quoting the question: "Using your language of choice, write a function that takes a variable number of arguments and returns the number of arguments it was called with.". Your code doesn't contain functions.
Ismael Miguel

@IsmaelMiguel, if that were indeed the case then many other solutions would also be invalidated. The norm is to allow solutions to be programmes or functions.
Shaggy

2

Batch, 50 49 bytes

set n=0
for %%a in (%*)do set/an+=1
exit/b%n%

No 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:

@echo off
call:c %*
echo %ERRORLEVEL%
exit/b
:c
set n=0
for %%a in (%*)do set/an+=1
exit/b%n%

I believe that this answer is answer goes (somewhat) against the rules. Batch has something somewhat close to functions. You can do something similar to :a|set r=0&for %%a in (%*)do set/ar+=1 (| = windows-style newline). This solution is 38 bytes. To execute it, do call :a <args> with a goto :eof before the function, being the value available inside the variable r. If you want to keep your solution, remove the /a on the first set, and remove those @.
Ismael Miguel

@IsmaelMiguel Like this? (Note: I didn't include the function name in the byte count, but I did include the function return, which seems reasonable, as there needs to be one somewhere.)
Neil

Yes, that's exactly it. Nice catch with the exit code! I was surprised to see that exitcodes can be larger than 255. An example is the list provided by Symantec: symantec.com/connect/articles/…
Ismael Miguel

2

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, but int foo(); means the same thing: args unspecified. (Unlike in C++ where it means int 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.

24                       global argcount_pointer_loop
25                       argcount_pointer_loop:
26                               .entry:
28 00000000 31C0             xor   eax, eax  ; search pattern = NULL
29 00000002 99               cdq             ; counter = 0
30 00000003 89E7             mov   edi, esp
31                       ;    scasd           ; edi+=4; skip retaddr
32                       .scan_args:
33 00000005 42               inc   edx
34 00000006 AF               scasd            ; cmp eax,[edi] / edi+=4
35 00000007 75FC             jne  .scan_args
36                       ;    dec   edx       ; correct for overshoot: don't count terminator
37                       ;    xchg  eax,edx
38 00000009 8D42FE           lea   eax, [edx-2]    ; terminator + ret addr
40 0000000C C3               ret

size = 0D               db $ - .entry

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 the xchg, but not the dec 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:

nasm -felf32 -l /dev/stdout arg-count.asm | cut -b -28,$((28+12))- &&
 gcc -Wall -O3 -g -std=gnu11 -m32 -fcall-used-edi arg-count.c arg-count.o -o ac &&
 ./ac

-fcall-used-edi is required even at -O0 to tell gcc to assume that functions clobber edi without saving/restoring it, because I used so many calls in one C statement (the printf call) that even -O0 was using EDI. It appears to be safe for gcc's main 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.

#include <stdio.h>

int argcount_rep_scas();       // not (...): ISO C requires at least one fixed arg
int argcount_pointer_loop();   // if you declare args at all
int argcount_loopne();

#define TEST(...) printf("count=%d = %d = %d   (scasd/jne) | (rep scas) | (scas/loopne)\n", \
        argcount_pointer_loop(__VA_ARGS__), argcount_rep_scas(__VA_ARGS__), \
        argcount_loopne(__VA_ARGS__))

int main(void) {
    TEST("abc", 0);
    TEST(1, 1, 1, 1, 1, 1, 1, 0);
    TEST(0);
}

Two other versions also came in at 13 bytes: this one based on loopne returns a value that's too high by 1.

45                       global argcount_loopne
46                       argcount_loopne:
47                           .entry:
49 00000010 31C0             xor   eax, eax  ; search pattern = NULL
50 00000012 31C9             xor   ecx, ecx  ; counter = 0
51 00000014 89E7             mov   edi, esp
52 00000016 AF               scasd           ; edi+=4; skip retaddr
53                       .scan_args:
54 00000017 AF               scasd
55 00000018 E0FD             loopne  .scan_args
56 0000001A 29C8             sub   eax, ecx
58 0000001C C3               ret

size = 0D = 13 bytes               db $ - .entry

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!)

63                       ; return int8_t maybe?
64                       global argcount_rep_scas
65                       argcount_rep_scas:
66                               .entry:
67 00000020 31C0             xor   eax, eax
68                           ;    lea   ecx, [eax-1]
69 00000022 B1FF             mov   cl, -1
70 00000024 89E7             mov   edi, esp
71                       ;    scasd              ; skip retaddr
72 00000026 F2AF             repne scasd        ; ecx = -len - 2 (including retaddr)
73 00000028 B0FD             mov   al, -3
74 0000002A 28C8             sub   al, cl       ; eax = -3 +len + 2
75                       ;    dec   eax
76                       ;    dec   eax
77 0000002C C3               ret

size =  0D = 13 bytes         db $ - .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).




โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.