ท้าทาย
ความท้าทายของคุณคือการออกแบบสำหรับล่ามภาษากระเพื่อมเหมือนซึ่งจะไปจากที่นี่มาได้รับการประกาศเกียรติคุณ: GLisp รหัสโปรแกรมสำหรับGLispจะประกอบด้วยจำนวนของนิพจน์ที่ซ้อนกันที่แสดงโดยวงเล็บในรูปแบบต่อไปนี้โดยพลการ:
(func arg1 arg2 ...)
โปรดทราบว่าล่ามจะต้องอนุญาตสำหรับอักขระช่องว่างภายนอกก่อนและหลังวงเล็บฟังก์ชั่นและข้อโต้แย้ง
ประเภท
คุณจะใช้งานสี่ประเภท, จำนวนเต็ม, รายการ, บูลีนและฟังก์ชั่น ค่าจำนวนเต็มและบูลีนสามารถแทรกอย่างชัดเจนในซอร์สโค้ดด้วยไวยากรณ์ของตัวเอง ล่ามของคุณต้องสมมติว่าการใช้อักขระตัวเลขหมายถึงจำนวนเต็ม (คุณไม่จำเป็นต้องใช้ไวยากรณ์เพื่อแทรกจำนวนเต็มลบอย่างชัดเจน) ล่ามของคุณจะต้องถือว่าtrue
และfalse
ได้รับการกำหนดค่าบูลีน ฟังก์ชั่นไม่สามารถกำหนดได้อย่างชัดเจนโดยผู้ใช้และจะส่งกลับค่าเดียวเสมอ (รายการที่มีความยาวนับเป็นค่าเดียว)
ฟังก์ชั่น
ฟังก์ชั่นต่อไปนี้จะต้องได้รับการดำเนินการและอยู่ในรูปแบบฟังก์ชั่น , arity หาก Arity n
ดำเนินการต่อโดยเครื่องหมายบวกแสดงว่าn
มีการโต้แย้งหรือมากกว่า คุณอาจสมมติว่าอาร์กิวเมนต์ทั้งหมดที่กำหนดให้กับฟังก์ชันนั้นเป็นประเภทเดียวกันเว้นแต่จะระบุไว้เป็นอย่างอื่น คุณอาจคิดว่าหากไม่มีการระบุพฤติกรรมสำหรับประเภทใบรับรองคุณอาจสมมติว่าไม่มีข้อโต้แย้งของฟังก์ชันนั้น ๆ ที่จะเป็นประเภทนั้น อาร์กิวเมนต์จะถูกอ้างถึงในแผนภาพต่อไปนี้:
(func argument1 argument2 ... argumentn)
+ , 2+
- หากอาร์กิวเมนต์ทั้งหมดเป็นประเภทจำนวนเต็มคุณต้องส่งคืนผลรวมของข้อโต้แย้ง
- ถ้าขัดแย้งทั้งหมดเป็นประเภทรายการคุณต้องกลับมาเรียงต่อกันของการขัดแย้งในการเรียงลำดับ (
arg1+arg2+ ...
) - หากอาร์กิวเมนต์ทั้งหมดเป็นประเภทBooleanคุณต้องส่งคืนตรรกะทั้งหมดของลำดับอาร์กิวเมนต์
(+ 1 2 3 4 5) -> 15
(+ (list 1 2) (list 3 4)) -> (list 1 2 3 4)
(+ true true true) -> true
- , 2+
- หากข้อโต้แย้งทั้งหมดเป็นประเภทจำนวนเต็มคุณต้องส่งกลับข้อแตกต่างของข้อโต้แย้ง (
arg1-arg2- ...
) - หากอาร์กิวเมนต์ทั้งหมดเป็นประเภทBooleanคุณต้องส่งคืนตรรกะใด ๆ ตามลำดับของอาร์กิวเมนต์
(- 8 4 3) -> 1
(- 0 123) -> -123
(- true false false true false) -> true
- หากข้อโต้แย้งทั้งหมดเป็นประเภทจำนวนเต็มคุณต้องส่งกลับข้อแตกต่างของข้อโต้แย้ง (
* , 2+
- หากข้อโต้แย้งทั้งหมดเป็นประเภทจำนวนเต็มคุณต้องส่งคืนผลิตภัณฑ์ของข้อโต้แย้ง
- หากอาร์กิวเมนต์หนึ่งเป็นประเภทรายการและอีกประเภทหนึ่งเป็นจำนวนเต็ม (คุณอาจคิดว่าสิ่งเหล่านี้จะเป็นเพียงอาร์กิวเมนต์ที่กำหนดเท่านั้น) คุณจะต้องส่งคืนรายการใหม่พร้อมกับรายการในเวลาที่
arg1
ซ้ำarg2
กัน (* 1 2 3 4 5) -> 120
(* (list 1 2 3) 2) -> (list 1 2 3 1 2 3)
/ , 2+
- หากข้อโต้แย้งทั้งหมดเป็นประเภทจำนวนเต็มคุณต้องส่งคืนผลหารของข้อโต้แย้ง (
arg/arg2/ ...
) (คุณอาจถือว่าการหารนั้นทำตามลำดับและส่วนทศนิยมในทุกขั้นตอนจะถูกตัดทอน) - หากอาร์กิวเมนต์หนึ่งเป็นประเภทรายการและอีกประเภทหนึ่งเป็นประเภทฟังก์ชั่นคุณจะต้องส่งคืนรายการผลลัพธ์หลังจากที่
arg2
ได้รับการแมปผ่านทุกค่า (/ 100 10 3) -> 3
(/ (list 1 2 3) inc) -> (list 2 3 4)
- หากข้อโต้แย้งทั้งหมดเป็นประเภทจำนวนเต็มคุณต้องส่งคืนผลหารของข้อโต้แย้ง (
% , 2
- หากอาร์กิวเมนต์ทั้งหมดเป็นประเภทจำนวนเต็มคุณต้องส่งคืนโมดูลัสของอาร์กิวเมนต์
(% 4 2) -> 0
= , 2+
- หากทั้งชนิดและค่าของอาร์กิวเมนต์ทั้งหมดเหมือนกันคุณต้องส่งคืนค่าจริง มิฉะนั้นส่งคืน false
(= 0 0 0) -> true
(= 0 false (list)) -> false
รายการ 0+
- คุณต้องส่งคืนรายการอาร์กิวเมนต์ทั้งหมดโดยไม่คำนึงถึงชนิด หากไม่มีการกำหนดอาร์กิวเมนต์คุณต้องส่งคืนรายการว่าง
(list 3 4 (list 5)) -> (list 3 4 (list 5))
inc 1
- ถ้าอาร์กิวเมนต์เป็นประเภทจำนวนเต็มคุณต้องส่งคืนค่าจำนวนเต็มเพิ่มขึ้นทีละหนึ่ง
- ถ้าอาร์กิวเมนต์เป็นประเภทรายการคุณต้องส่งคืนรายการที่หมุนตามเข็มนาฬิกาเป็นการหมุนครั้งเดียว
(inc 1) -> 2
(inc (list 1 2 3)) -> (list 3 1 2)
ธ.ค. 1
- หากอาร์กิวเมนต์เป็นประเภทจำนวนเต็มคุณต้องส่งคืนค่าจำนวนเต็มลดลงหนึ่งค่า
- ถ้าอาร์กิวเมนต์เป็นชนิดรายการคุณต้องส่งคืนรายการที่หมุนทวนเข็มนาฬิกาเป็นการหมุนครั้งเดียว
(dec 1) -> 0
(dec (list 1 2 3)) -> (list 2 3 1)
ถ้า 3
- หากมีข้อโต้แย้งสามประเภท: ถ้าค่าความจริง
arg1
เป็นจริงให้ส่งarg2
คืนarg3
(if (not (list 1)) 8 false) -> false
- หากมีข้อโต้แย้งสามประเภท: ถ้าค่าความจริง
ไม่ใช่ 1
- หากได้รับข้อโต้แย้งของชนิดใด ๆ ถ้าค่าความจริงของ
arg1
คือ False ผลตอบแทนอื่นกลับมาtrue
false
(not (list)) -> true
- หากได้รับข้อโต้แย้งของชนิดใด ๆ ถ้าค่าความจริงของ
เลน 1
- หากได้รับการโต้แย้งจากประเภทรายการกลับความยาวของ
arg1
(len (list 4 2 true (list 3) (list))) -> 5
- หากได้รับการโต้แย้งจากประเภทรายการกลับความยาวของ
ตารางความจริง:
0, (list), false -> false
โดยที่(list)
หมายถึงรายการที่ว่างเปล่า true
ทุกสิ่งทุกอย่างเป็น
ล่ามของคุณอาจเป็นโปรแกรมเต็มรูปแบบที่อ่านอินพุตต้นฉบับจาก stdin หรือไฟล์หรือฟังก์ชั่นที่รับซอร์สเป็นสตริงและส่งคืนค่าเอาต์พุต
หากเลือกแบบก่อนหน้าเอาต์พุตสำหรับจำนวนเต็มเป็นเพียงตัวเลขสำหรับBooleansคือtrue
หรือfalse
และสำหรับรายการเป็นลำดับที่คั่นด้วยช่องว่างของค่าที่อยู่ในวงเล็บ (เช่น(1 2 3 4 (5 6 7))
หมายถึง(list 1 2 3 4 (list 5 6 7))
)
หากเลือกหลังจะต้องส่งคืนค่าในประเภทที่สอดคล้องกันของภาษาที่ใช้งานหรือหากไม่มีประเภทที่คล้ายกันประเภทที่กำหนดเองอยู่ รายการสามารถกลับมาเป็นอาร์เรย์หรือพาหะถ้าภาษาที่ไม่ได้มีรายการประเภทBooleansควรจะกลับเป็นชนิดบูลีนในภาษาหรือประเภทที่กำหนดเองถ้าภาษาไม่สนับสนุนพวกเขา
กรณีทดสอบ
(list 1 2 3 (list 4 5 true)) -> (1 2 3 (4 5 true))
(/ 4000 (+ 1 2 3 4 (* 5 8))) -> 80
(+ (not (- (len (list 5 6 7)) (/ 10 3))) true) -> true
(if ( len (list ) ) 4 (if (+ (= 8 8 8) (not (list 4))) 8 5)) -> 5
ชี้แจง
- ล่ามของคุณอาจจัดการกับการป้อนข้อมูลที่ไม่ถูกต้องในวิธีที่คุณเลือก แต่มันจะต้องไม่เกิดข้อยกเว้น (แม้ว่ามันอาจพิมพ์ข้อความผิดพลาดและออกอย่างราบรื่น)
- ฟังก์ชั่นจะประเมินข้อโต้แย้งจากซ้ายไปขวาเสมอ
- อินพุตไม่ถูกต้องคืออินพุตใด ๆ ที่ไม่ถูกต้องทางไวยากรณ์ ซึ่งรวมถึง แต่ไม่ จำกัด เพียงวงเล็บเหลี่ยมที่ไม่ตรงกันการหารด้วยศูนย์และฟังก์ชั่นที่นำไปใช้บางส่วน (ยกเว้นจะได้โบนัส)
- สำหรับ
=
หากค่าใด ๆ นั้นแตกต่างกันหรือประเภทใด ๆ แตกต่างกันให้ส่งคืนfalse
โบนัส
- คะแนน * 0.8หากคุณรองรับฟังก์ชั่นที่ใช้บางส่วน ยกตัวอย่างเช่น
((+ 2) 3)
จะเป็นเช่นเดียวกับแต่ช่วยให้สิ่งต่างๆเช่น(+ 2 3)
(/ (list 1 2 3) (+ 2))
คุณอาจคิดว่าฟังก์ชั่นบางส่วนถูกนำไปใช้ถ้ามันได้รับน้อยกว่าจำนวนขั้นต่ำของการขัดแย้ง - คะแนน * 0.85หากคุณไม่ได้ประเมินอาร์กิวเมนต์ที่ใช้กับ
if
ถ้าพวกเขาจะถูกส่งกลับ
นี่คือโค้ดกอล์ฟดังนั้นล่ามที่มีจำนวนไบต์ต่ำสุดชนะ!
(+ 3 (if false 5))
อย่างไร โดยทั่วไปแล้วสิ่งที่ "คืนค่าอะไร" คืออะไร? คุณไม่ได้ระบุประเภทหน่วยใด ๆ ที่จะรับการเรียกคืน
(+ bool bool...)
ตรรกะและและ(- bool bool...)
ตรรกะหรือ? สัญกรณ์แหวนมาตรฐานจะใช้+
สำหรับ OR และ*
สำหรับและ 2. "การป้อนข้อมูลที่ไม่ถูกต้อง" มีวัตถุประสงค์เพื่อครอบคลุมกรณีเช่นนี้(/ 2 0)
ซึ่งถูกต้องตามหลักไวยากรณ์หรือไม่ 3. สำหรับ=
หากค่าไม่เหมือนกันทั้งหมดจะต้องส่งคืนfalse
หรือไม่ 4. คำจำกัดความของnot
ดูเหมือนจะย้อนกลับ 5. โทเค็นคืออะไร คุณพูดว่าล่ามจะต้องจัดการช่องว่างพิเศษ แต่คุณไม่ต้องพูดว่าช่องว่างนั้นสามารถพึ่งพาได้ สำหรับคำถามที่ซับซ้อนเช่นนี้คุณควรใช้แซนด์บ็อกซ์เพื่อตรวจสอบข้อมูลจำเพาะ
((+ 2 3) 4)
เท่ากับ9
หรือมีข้อผิดพลาด โดยเฉพาะอย่างยิ่งสำหรับฟังก์ชั่น var-arg มันไม่ชัดเจนเมื่อหนึ่งควรพิจารณาใบสมัครบางส่วน มันจะยิ่งยุ่งเหยิงไปกับสิ่งต่าง ๆ เช่น((if true (+ 2 3) (- 5)) 4)
(if (not (array 1)) 8 false) -> false
อย่างไร