Prindeal (เด่นชัดปริญญ์-Dee-AL ) เป็นใหม่ลึกลับเขียนโปรแกรมภาษาที่มีเพียงสี่คำสั่ง: PR int , ใน crement , เด crementและอัล IAS แม้จะมีความเรียบง่าย แต่การดำเนินการทางคณิตศาสตร์ที่ซับซ้อนสามารถทำได้ใน Prindeal โดยการรวมคำสั่งทั้งสี่อย่างชาญฉลาด
งานของคุณในการแข่งขันกอล์ฟรหัสนี้คือการเขียนโปรแกรมที่สั้นที่สุดที่สามารถเรียกใช้รหัส Prindeal
ข้อมูลจำเพาะยาว แต่ฉันพยายามทำให้ชัดเจนที่สุดและฉันเชื่อว่าหากคุณใช้ความพยายามในการเรียนรู้ Prindeal คุณจะพบว่ามันดูหรูหรามาก!
การตีความหมายที่ชัดเจน
กระบวนการเตรียมการผลิต
ก่อนที่โปรแกรม Prindeal จะสามารถตีความสิ่งเหล่านี้จำเป็นต้องลบออกจากลำดับนี้:
- สิ่งใดก็ตามหลังจาก
#
สัญญาณไปยังจุดสิ้นสุดของบรรทัดที่มันเปิดอยู่รวมทั้ง#
ตัวของมันเอง (นี่คือความคิดเห็น) - ช่องว่างต่อท้ายในบรรทัดใด ๆ
- เส้นที่ว่างเปล่าโดยสิ้นเชิง
ตัวอย่างเช่นโปรแกรม Prindeal
p cat #The next line has 7 trailing spaces.
p dog
#p mouse
จะถูกประมวลผลล่วงหน้าเป็น
p cat
p dog
จากที่นี่ไปเราจะถือว่าขั้นตอนการประมวลผลล่วงหน้านี้เสร็จสิ้นแล้ว
ตัวแปร
เราจำเป็นต้องกำหนดตัวแปรอย่างรวดเร็วก่อนที่จะแสดงวิธีการใช้งาน
ตัวแปร (และการอ้างอิงถึงตัวแปร) คือสิ่งที่ส่งผ่านไปยังอาร์กิวเมนต์ของคำสั่ง Prindeal ตัวแปรเป็นโกลบอลเสมอดังนั้นการแก้ไขตัวแปรไม่ว่าจะเกิดขึ้นที่ไหนจะถูกสะท้อนทุกที่
แต่ละตัวแปรมีจำนวนเต็มความแม่นยำโดยไม่ลบ (0, 1, 2, 3, ... ) ตัวแปรไม่จำเป็นต้องเริ่มต้นล่วงหน้า - พวกเขามักจะเริ่มต้นด้วยค่า 0ในครั้งแรกที่พวกเขาจะใช้หรือเรียก
ชื่อตัวแปรอาจจะเป็นสตริงใด ๆ ที่ไม่ว่างเปล่าของ Alphanumerics และขีดที่ไม่ได้เริ่มต้นด้วยหลัก - [a-zA-Z_][0-9a-zA-Z_]*
ในregex พวกเขาเป็นกรณีที่สำคัญดังนั้นspiny_lumpsuck3r
และSpiny_lumpsuck3r
เป็นตัวแปรที่แตกต่างกัน
การกระทำ
Prindeal เป็นภาษาการเขียนโปรแกรมที่จำเป็น เมื่อโปรแกรม Prindeal รันคำสั่งจะถูกดำเนินการจากบนลงล่างตามลำดับจากนั้นโปรแกรมจะสิ้นสุดลง
ทุกบรรทัดที่ไม่มีการเยื้องในโปรแกรม Prindeal เป็นคำสั่งที่เกี่ยวข้องกับการดำเนินการของคำสั่งเดียวซึ่งอาจหรืออาจจะไม่โต้แย้ง
บรรทัดที่เยื้องจะเกิดขึ้นหลังจากคำสั่งaliasเท่านั้น โดยเฉพาะอย่างยิ่งสามบรรทัดที่เยื้องกับช่องว่างเดียวเกิดขึ้นหลังจากคำสั่งaliasทุกคำ และถือว่าเป็นส่วนหนึ่งของคำสั่งนั้น ดังนั้นคำสั่งนามแฝงจึงมีความยาวสี่บรรทัด (พวกเขาอาจเป็นหนึ่งบรรทัดสี่เป็นเพียงอ่านได้มากขึ้น)
ที่ไม่ใช่นามแฝงงบ
ด้วยข้อยกเว้นของaliasทุกคำสั่งในโปรแกรม Prindeal มีรูปแบบ:
[command name] [argument 1] [argument 2] [argument 3] ...
อาจมีจำนวนอาร์กิวเมนต์โดยพลการ (รวมถึงไม่มีเลย) แต่ละข้อโต้แย้งอยู่เสมอเป็นตัวแปรหรือ (ที่เราจะเห็นเมื่อพูดถึงนามแฝงบริการ) อ้างอิงกับตัวแปร
เมื่อดำเนินการเสร็จแล้วแต่ละคำสั่งจะถูกแฟล็กเป็นความล้มเหลวหรือความสำเร็จขึ้นอยู่กับว่าเกิดข้อผิดพลาดหรือไม่ (สิ่งนี้สำคัญมากเมื่อเราใช้นามแฝง )
ตัวอินพิมพ์ , การเพิ่มขึ้นและลดลงเป็นงบแบบฟอร์มดังกล่าวข้างต้น นี่คือสิ่งที่พวกเขาทำ:
พิมพ์มีชื่อคำสั่ง
p
และรับหนึ่งอาร์กิวเมนต์ มันพิมพ์ชื่อของตัวแปรที่ส่งผ่านและความคุ้มค่า (ในทศนิยม) คั่นด้วย "=" แล้วขึ้นบรรทัดใหม่ มันถูกตั้งค่าสถานะเป็นความสำเร็จเสมอตัวอย่างเช่นโปรแกรม Prindeal
p _MyVariable_321 p screaming_hairy_armadillo
จะส่งออก
_MyVariable_321 = 0 screaming_hairy_armadillo = 0
เพราะตัวแปรทั้งหมดเริ่มต้นที่ 0 (จำเป็นต้องเว้นวรรคก่อนและหลังเครื่องหมายเท่ากับ)
incrementมีชื่อคำสั่ง
i
และรับหนึ่งอาร์กิวเมนต์ มันเพิ่มค่าของตัวแปรที่ส่งผ่านโดย 1. มันถูกตั้งค่าสถานะเคยเป็นที่ประสบความสำเร็จ ..ตัวอย่างเช่นโปรแกรม
i alpaca p alpaca i alpaca p alpaca
จะส่งออก
alpaca = 1 alpaca = 2
โปรดสังเกตว่าการ
alpaca
เพิ่มขึ้นจาก 0 เป็น 1 แม้ว่าจะไม่เคยมีการเข้าถึงมาก่อนdecrementมีชื่อคำสั่ง
d
และรับหนึ่งอาร์กิวเมนต์ ถ้าตัวแปรที่ส่งผ่านไม่ใช่ศูนย์ค่าของมันจะลดลงทีละ 1 และคำสั่งที่ถูกตั้งค่าสถานะเป็นความสำเร็จ ถ้าตัวแปรที่ส่งผ่านเป็น 0 แล้วไม่มีอะไรจะทำและคำสั่งที่ถูกตั้งค่าสถานะเป็นความล้มเหลวตัวอย่างเช่นโปรแกรม
i malamute p malamute d malamute #success p malamute d malamute #failure p malamute d akita #failure p akita
จะส่งออก
malamute = 1 malamute = 0 malamute = 0 akita = 0
ขอให้สังเกตว่า decrementing ตัวแปรที่มีค่า 0 เป็นวิธีเดียวที่จะก่อให้เกิดความล้มเหลว
นามแฝงคำชี้แจงและคำสั่งนามแฝง
นามแฝงคำสั่งมีไวยากรณ์พิเศษและมีประสิทธิภาพมากที่สุดเพราะมันสามารถนำมาใช้ในการกำหนดคำสั่งใหม่ นามแฝงชื่อคำสั่งa
และชื่อแทนคำสั่งมีรูปแบบ:
a [name of new command]
[statement A]
[statement B]
[statement C]
ซึ่งแต่ละคน[statement X]
เป็นตัวแทนใด ๆ ที่ไม่ใช่ชื่อแทน[command name] [argument 1] [argument 2] [argument 3] ...
คำสั่งอะไรบางอย่างคือมีรูปแบบ
ชื่อของคำสั่ง aliased [name of new command]
อาจเป็นสตริงที่ไม่ว่างของตัวอักษรผสมตัวเลขและเครื่องหมายขีดล่างที่ไม่ได้ขึ้นต้นด้วยตัวเลข - [a-zA-Z_][0-9a-zA-Z_]*
ใน regex
(นี่คือชื่อชุดเดียวกับตัวแปร แต่คำสั่งและตัวแปรที่ใช้นามแฝงนั้นเป็นสิ่งต่าง ๆ ที่ใช้ในสถานที่ต่างกันตัวแปรอาจตั้งชื่อเหมือนกับคำสั่งที่ไม่มีผลร้าย)
เมื่อคำสั่งaliasถูกเรียกใช้งานคำสั่งใหม่จะถูกเพิ่มไว้ข้างp
i
d
a
คำสั่งสี่ต้นฉบับ คำสั่งใหม่สามารถใช้เป็น[command name]
คำสั่ง in และเรียกใช้พร้อมอาร์กิวเมนต์เช่นเดียวกับคำสั่งnoniasiasอื่น ๆ
เมื่อคำสั่งที่มีชื่อคำสั่ง aliased ถูกเรียกใช้คำสั่งอีกสองคำสั่งจากคำสั่งaliasดั้งเดิมจะถูกเรียกใช้
[statement A]
ทำงานอยู่เสมอ[statement B]
จะทำงานถ้า[statement A]
เป็นความสำเร็จ[statement C]
จะทำงานหาก[statement A]
มีความล้มเหลว
งบ A, B, และ C มักจะวิ่งอย่างเกียจคร้านนั่นคือพวกมันจะถูกประเมินทันทีที่มีการดำเนินการ
เมื่อเสร็จแล้วรันคำสั่ง aliased ถูกตั้งค่าสถานะเดียวกับที่ประสบความสำเร็จหรือความล้มเหลวของธงเป็นคำสั่ง B หรือ C แล้วแต่จำนวนใดคนหนึ่งถูกประหารชีวิต ( คำสั่งaliasเองไม่จำเป็นต้องถูกแฟล็กเนื่องจากไม่สามารถเกิดขึ้นได้ภายในตัวเอง)
ตัวอย่างนามแฝง 1
สมมติว่าเราต้องการคำสั่งใหม่ที่เพิ่มตัวแปร
frog
สองครั้ง คำสั่ง alias นี้บรรลุผล:a increment_frog_twice i frog i frog d frog
Statement A (
i frog
) ถูกเรียกใช้เสมอและตั้งค่าสถานะเป็นความสำเร็จ เสมอดังนั้นคำสั่ง B (i frog
) จะถูกเรียกใช้เสมอและตัวแปรfrog
จะเพิ่มขึ้น 2 ข้อincrement_frog_twice
คำสั่งจะถูกตั้งค่าสถานะเป็นความสำเร็จเสมอเนื่องจากคำสั่ง B จะทำงานเสมอและ B ความสำเร็จ คำสั่ง C (d frog
) ไม่เคยถูกเรียกใช้ดังนั้นเอาท์พุทไป
a increment_frog_twice i frog i frog d frog p frog increment_frog_twice p frog
อยากจะเป็น
frog = 0 frog = 2
เราสามารถสรุปตัวอย่างนี้เพื่อให้ตัวแปรใด ๆสามารถเพิ่มขึ้นได้สองครั้งโดยให้อาร์กิวเมนต์คำสั่ง aliased
ภายในคำสั่งaliasจำนวนเต็มบวก 1, 2, 3, ฯลฯ แสดงถึงอาร์กิวเมนต์ที่ 1, 2, 3 และอื่น ๆ ที่ส่งผ่านไปยังคำสั่ง aliased (อาร์กิวเมนต์เหล่านี้อาจเป็นตัวแปรธรรมดาหรืออ้างอิงถึงตัวแปรเอง) ตัวเลขเหล่านี้สามารถปรากฏได้เฉพาะในอาร์กิวเมนต์ของคำสั่ง A, B และ C ในคำสั่งalias มันไม่สมเหตุสมผลสำหรับพวกเขาที่จะปรากฏที่อื่น
ตัวอย่างนามแฝง 2
นี่เป็นการสรุปตัวอย่างสุดท้าย - ตัวแปรใด ๆ ที่ถูกส่งเข้าไป
increment_twice
จะเพิ่มขึ้น 2 เนื่องจาก1
เป็นการอ้างอิงถึงอาร์กิวเมนต์แรกที่ผ่านเข้ามา:a increment_twice i 1 i 1 d 1 #never reached p toad increment_twice toad p toad
ผลลัพธ์ของโปรแกรมนี้จะเป็น
toad = 0 toad = 2
จากนั้นเราสามารถนามแฝงคำสั่งอื่นที่มีสองอาร์กิวเมนต์และเรียก
increment_twice
ทั้งสอง:a increment_twice i 1 i 1 d 1 #never reached a increment_both_twice increment_twice 1 increment_twice 2 d 1 #never reached increment_both_twice platypus duck p platypus p duck
ผลลัพธ์ที่นี่จะเป็น
platypus = 2 duck = 2
สิ่งสำคัญคือต้องตระหนักว่าคำสั่ง aliased สามารถเรียกซ้ำได้เนื่องจากนี่คือที่ซึ่งพลังที่แท้จริงของพวกเขาอยู่ ตัวอย่างเช่นเราสามารถสร้างคำสั่งที่ตั้งค่าตัวแปรใด ๆ ที่ส่งผ่านเป็น 0:
ตัวอย่างนามแฝง 3
set_to_zero
คำสั่งจะใช้เวลาหนึ่งโต้แย้งและการตั้งค่าของตัวแปร 0 และถูกตั้งค่าสถานะเป็นความสำเร็จเมื่อทำ:a set_to_zero d 1 set_to_zero 1 i _dummy_ i oryx i oryx i oryx p oryx set_to_zero oryx p oryx
ผลลัพธ์ของโปรแกรมนี้จะเป็น
oryx = 3 oryx = 0
สิ่งที่เกิดขึ้นคือเมื่อ
set_to_zero oryx
มีการเรียกใช้d 1
ลดจำนวนสำเร็จoryx
จาก 3 เป็น 2 จากนั้นset_to_zero 1
จะถูกเรียกใช้ซึ่งเหมือนกับการโทรset_to_zero oryx
อีกครั้ง ดังนั้นกระบวนการซ้ำจนd 1
เป็นความล้มเหลวในการหยุดการเรียกซ้ำและเพิ่มขึ้น_dummy_
ตัวแปรเพื่อให้ประสบความสำเร็จเป็นที่ผลิต
ท้าทาย
เขียนโปรแกรมที่สามารถเรียกใช้รหัส Prindeal ได้ตามที่อธิบายไว้ข้างต้น ใช้รหัส Prindeal ผ่านทาง stdin, บรรทัดคำสั่งหรือเป็นไฟล์ข้อความ พิมพ์เอาต์พุตของโปรแกรม Prindeal ไปยัง stdout หรือทางเลือกที่ใกล้เคียงที่สุดในภาษาของคุณ
หรือคุณสามารถเขียนฟังก์ชั่นที่ใช้ในรหัสเป็นสตริงและพิมพ์หรือส่งคืนสตริงเอาต์พุต
นอกจากนี้คุณสามารถสมมติได้ว่า:
- รหัส Prindeal ที่ป้อนจะประกอบด้วยบรรทัดใหม่และASCII ที่พิมพ์ได้และ (เป็นทางเลือก) ที่ลงท้ายด้วยบรรทัดว่าง
- รหัสที่ป้อนจะถูกต้อง Prindeal - รูปแบบที่ดีและถูกต้องทางไวยากรณ์
- การรันโค้ดจะไม่สร้างลูปที่ไม่มีที่สิ้นสุดหรือการอ้างอิงที่ไม่ถูกต้องไปยังคำสั่งที่ไม่ได้กำหนดไว้หรือมีการขัดแย้งที่ไม่ได้รับ
- ชื่อคำสั่ง
p
,i
,d
และa
จะไม่ถูก aliased มากกว่า (คุณอาจไม่คิดว่าตัวแปรจะไม่มีชื่อเหล่านี้)
นอกจากนี้ไม่สำคัญว่าค่าตัวแปรของคุณไม่ใช่จำนวนเต็มที่มีความแม่นยำตามอำเภอใจจริง ๆ เพราะจะมีการทดสอบเฉพาะตัวเลขที่น้อยกว่า 1,000 รายการเท่านั้น และก็ไม่เป็นไรหากภาษาของคุณมีข้อ จำกัด การเรียกซ้ำ (เช่นPython ) ที่โปรแกรม Prindeal ที่ซับซ้อนอาจพบได้ตราบใดที่โปรแกรมทดสอบด้านล่างใช้งานได้
โปรแกรมทดสอบ
นี่คือโปรแกรม Prindeal ขนาดใหญ่ที่สร้างการดำเนินการของการบวกการคูณและการยกกำลังด้วยการใช้ตัวแปรจำลอง (เริ่มต้นด้วย_
การประชุม) และนามแฝงผู้ช่วยหลายคน:
#Command Definitions:
a s #flag as a success
i _
d _
d _
a f #flag as a failure
d _
d _
d _
a z #1 = zero
d 1
z 1
s
a n #1 = one
z 1
i 1
s
a move #2 += 1, 1 = zero
moveH 1 2
move 1 2
s
a moveH #move helper
d 1
i 2
f
a dupe #2 += 1, 3 += 1, 1 = zero
dupeH1 1 2 3
dupe 1 2 3
s
a dupeH1 #dupe helper
d 1
dupeH2 2 3
f
a dupeH2 #dupe helper
i 1
i 2
s
a copy #2 = 1
z 2
copyH 1 2
s
a copyH #copy helper
dupe 1 2 _copy
move _copy 1
s
a addTo #1 += 2
copy 2 _add
#testing comments #
move _add 1#in weird places # just because #
s
#it's a g##d idea
###
a add #1 = 2 + 3
#its a good idea
z 1
addH 1 2 3
s
##
#
a addH #add helper
#this is a comment
addTo 1 2 #as is this
addTo 1 3
s
a mul #1 = 2 * 3
mulH1 1 2
mulH2 1 3
s
a mulH1 #mul helper
z 1
copy 2 _mul
s
a mulH2 #mul helper
mulH3 1 2
mulH2 1 2
s
a mulH3 #mul helper
d _mul
addTo 1 2
f
a mulBy #1 *= 2
mul _mulBy 1 2
copy _mulBy 1
s
a pow #1 = 2^3
powH1 1 3
powH2 1 2
s
a powH1 #pow helper
n 1
copy 2 _pow
s
a powH2 #pow helper
powH3 1 2
powH2 1 2
s
a powH3 #pow helper
d _pow
mulBy 1 2
f
#Running Tests:
p A
p B
p C
n A #A = 1
n B #B = 1
add C A B #C = A + B = 1 + 1 = 2
p ____
p A
p B
p C
add B A C #B = A + C = 1 + 2 = 3
p ____
p A
p B
p C
mul d B C #d = B * C = 3 * 2 = 6
p ____
p d
mulBy d B #d = d * B = 6 * 3 = 18
p ____
p d
d A #A = A - 1 = 1 - 1 = 0
mulBy d A #d = d * A = 18 * 0 = 0
p ____
p d
pow A C B #A = C ^ B = 2 ^ 3 = 8
p ____
p A
p B
p C
pow A B C #A = B ^ C = 3 ^ 2 = 9
p ____
p A
p B
p C
pow C A B #C = A ^ B = 9 ^ 3 = 729
p ____
p A
p B
p C
(หากคุณกำลังเล่นกับรหัสนี้โปรดทราบว่าคำสั่งหลายคำสั่งจะล้มเหลวหากมีการให้ตัวแปรเดียวกันหลายครั้งเป็นอาร์กิวเมนต์ซึ่งสามารถแก้ไขได้อย่างง่ายดาย แต่รหัสที่ได้จะยาวกว่า)
ล่าม Prindeal ของคุณควรสามารถสร้างผลลัพธ์ที่แน่นอนได้:
A = 0
B = 0
C = 0
____ = 0
A = 1
B = 1
C = 2
____ = 0
A = 1
B = 3
C = 2
____ = 0
d = 6
____ = 0
d = 18
____ = 0
d = 0
____ = 0
A = 8
B = 3
C = 2
____ = 0
A = 9
B = 3
C = 2
____ = 0
A = 9
B = 3
C = 729
เกณฑ์การให้คะแนน
รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ Tiebreaker ไปที่การส่งก่อนหน้า
บราวนี่โบนัส: เขียนโปรแกรมสุดเจ๋งใน Prindeal ฉันใช้การบวกและการคูณคุณสามารถทำการลบหรือหารได้หรือไม่?
p
แล้วp p
ซึ่งจะพิมพ์ 1 ได้ไหม