พิมพ์, เพิ่ม, ลด, นามแฝง - ตีความตีความ


30

Prindeal (เด่นชัดปริญญ์-Dee-AL ) เป็นใหม่ลึกลับเขียนโปรแกรมภาษาที่มีเพียงสี่คำสั่ง: PR int , ใน crement , เด crementและอัล IAS แม้จะมีความเรียบง่าย แต่การดำเนินการทางคณิตศาสตร์ที่ซับซ้อนสามารถทำได้ใน Prindeal โดยการรวมคำสั่งทั้งสี่อย่างชาญฉลาด

งานของคุณในการแข่งขันกอล์ฟรหัสนี้คือการเขียนโปรแกรมที่สั้นที่สุดที่สามารถเรียกใช้รหัส Prindeal

ข้อมูลจำเพาะยาว แต่ฉันพยายามทำให้ชัดเจนที่สุดและฉันเชื่อว่าหากคุณใช้ความพยายามในการเรียนรู้ Prindeal คุณจะพบว่ามันดูหรูหรามาก!


การตีความหมายที่ชัดเจน

กระบวนการเตรียมการผลิต

ก่อนที่โปรแกรม Prindeal จะสามารถตีความสิ่งเหล่านี้จำเป็นต้องลบออกจากลำดับนี้:

  1. สิ่งใดก็ตามหลังจาก#สัญญาณไปยังจุดสิ้นสุดของบรรทัดที่มันเปิดอยู่รวมทั้ง#ตัวของมันเอง (นี่คือความคิดเห็น)
  2. ช่องว่างต่อท้ายในบรรทัดใด ๆ
  3. เส้นที่ว่างเปล่าโดยสิ้นเชิง

ตัวอย่างเช่นโปรแกรม 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] ...

อาจมีจำนวนอาร์กิวเมนต์โดยพลการ (รวมถึงไม่มีเลย) แต่ละข้อโต้แย้งอยู่เสมอเป็นตัวแปรหรือ (ที่เราจะเห็นเมื่อพูดถึงนามแฝงบริการ) อ้างอิงกับตัวแปร

เมื่อดำเนินการเสร็จแล้วแต่ละคำสั่งจะถูกแฟล็กเป็นความล้มเหลวหรือความสำเร็จขึ้นอยู่กับว่าเกิดข้อผิดพลาดหรือไม่ (สิ่งนี้สำคัญมากเมื่อเราใช้นามแฝง )

ตัวอินพิมพ์ , การเพิ่มขึ้นและลดลงเป็นงบแบบฟอร์มดังกล่าวข้างต้น นี่คือสิ่งที่พวกเขาทำ:

  1. พิมพ์มีชื่อคำสั่งpและรับหนึ่งอาร์กิวเมนต์ มันพิมพ์ชื่อของตัวแปรที่ส่งผ่านและความคุ้มค่า (ในทศนิยม) คั่นด้วย "=" แล้วขึ้นบรรทัดใหม่ มันถูกตั้งค่าสถานะเป็นความสำเร็จเสมอ

    ตัวอย่างเช่นโปรแกรม Prindeal

    p _MyVariable_321
    p screaming_hairy_armadillo
    

    จะส่งออก

    _MyVariable_321 = 0
    screaming_hairy_armadillo = 0
    

    เพราะตัวแปรทั้งหมดเริ่มต้นที่ 0 (จำเป็นต้องเว้นวรรคก่อนและหลังเครื่องหมายเท่ากับ)

  2. incrementมีชื่อคำสั่งiและรับหนึ่งอาร์กิวเมนต์ มันเพิ่มค่าของตัวแปรที่ส่งผ่านโดย 1. มันถูกตั้งค่าสถานะเคยเป็นที่ประสบความสำเร็จ ..

    ตัวอย่างเช่นโปรแกรม

    i alpaca
    p alpaca
    i alpaca
    p alpaca
    

    จะส่งออก

    alpaca = 1
    alpaca = 2
    

    โปรดสังเกตว่าการalpacaเพิ่มขึ้นจาก 0 เป็น 1 แม้ว่าจะไม่เคยมีการเข้าถึงมาก่อน

  3. 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 ฉันใช้การบวกและการคูณคุณสามารถทำการลบหรือหารได้หรือไม่?


โอ้มนุษย์ฉันคิดว่าครั้งหนึ่งฉันจะออกจาก Pyth ตามลำพังและดึงเสียงกระเพื่อม! คำถามเดียว - ฟังก์ชั่นและตัวแปรอาศัยอยู่ในเนมสเปซที่ต่างกันใช่ไหม? ดังนั้นฉันสามารถเพิ่มขึ้นได้pแล้วp pซึ่งจะพิมพ์ 1 ได้ไหม
orlp

@ หรือแก้ไขถูกต้อง (มีข้อสังเกตบางประการเกี่ยวกับสิ่งนั้นในนั้น)
งานอดิเรกของ Calvin

2
ฉันไม่สามารถเป็นคนเดียวที่คิดว่า PRNDL เมื่อฉันเห็นชื่อภาษา
Downgoat

มีจำนวนอาร์กิวเมนต์สูงสุดที่จะถูกส่งผ่านไปยังคำสั่ง aliased หรือไม่?
Zach Gates

คำตอบ:


9

Pyth, 162 136 ไบต์

JfTmchcd\#).zKHW<ZlJI!e=T@J~+Z1=@Tk)=k0 .x=J+]h=Nm.xL@Tskd@K=NhT+]+tN0>J~Z0,=Y.x@H=eT0?qN\pps[Td\=dYb)?xGN?qN\iXHThY?YXTH_1=k1XKT:JZ=+Z3

สาธิต.

ใช้อักขระ 26 ตัวโดยการอินไลน์ตัวแปรและเปลี่ยนจากIและEใช้โฟลว์คอนโทรลตาม?และเป็น.xโฟลว์ควบคุมตาม

เป็นครั้งแรกที่ฉันไม่มีตัวแปรใน Pyth ทุกตัวแปรเดียวใน Pyth ( bdkGHNTYและJK) มีการใช้งานและฉันต้องการใช้bเป็นบรรทัดใหม่ โชคดีที่ฉันสามารถใช้Nหมายถึงสองสิ่งที่แตกต่างอย่างสิ้นเชิงในส่วนต่าง ๆ ของโปรแกรมและดังนั้นจึงยังใช้งานได้

Ungolfed (ทำงานด้วย -m):

JfTmchcd\#).z
KH
W<ZlJ
  I!e=T@J~+Z1
    =@Tk)
  =k0
     .x
      =J+]h=Nm.xL@Tskd@K=NhT+]+tN0>J~Z0
      ,
        =Y.x@H=eT0
        ?qN\p
          ps[Td\=dYb)
          ?xGN
            ?qN\i
              XHThY
              ?Y
                XTH_1
                =k1
            XKT:JZ=+Z3

3
ฉันรักที่ฉันยังคงไม่สามารถบอกได้ว่ามันจะทำยังไงกับมันที่ไม่ดี ...
Jerry Jeremiah

สรุปได้ว่า Pyth นั้นไม่สมบูรณ์ทัวริง ...
Erik the Outgolfer

8

Python 2, 600 584 397 373 ไบต์

นี่คือทางออกอ้างอิงของฉัน golfed ทุกคนยินดีที่จะปรับปรุงหรือปฏิบัติตามตรรกะในคำตอบของตนเองตราบเท่าที่มีการระบุแหล่งที่มา

ส่วนที่เรียบร้อยเกี่ยวกับมันคือไม่มีการเรียกซ้ำดังนั้นมันจะไม่มีปัญหากับการ จำกัด การเรียกซ้ำของ Python ตัวอย่างเช่นโปรแกรม Prindeal Countup ของ Spสามารถรันได้อย่างไม่มีกำหนด

p=filter(len,[l.split('#')[0].split()for l in input().split('\n')]);m={};v={};i=0
while i<len(p):
 s=p[i]
 if'('in`s`:s=s[f]
 n,f=s[0],0
 if n in m:a,b,c=([s[int(g)]if g.isdigit()else g for g in t]for t in m[n]);p=[a,(b,c)]+p[i+1:];i=0;continue
 s=s[1]
 q=v.get(s,0)
 if'd'>n:m[s]=p[i+1:i+4];i+=3
 elif'i'<n:print s,'=',q
 elif'd'<n:v[s]=q+1
 elif q:v[s]-=1
 else:f=1
 i+=1


'p _MyVariable_321\np screaming_hairy_armadillo'มันเป็นโปรแกรมที่ใช้ในโปรแกรมสตริงที่ยกมามีการขึ้นบรรทัดใหม่หนีเช่น

ฉันเอาคำแนะนำการเล่นกอล์ฟต่าง ๆ จากคำตอบของSpและPietu ขอบคุณเพื่อน :)


6

Python 3, 345 336 335 328 ไบต์

a=0
A={}
V={}
def f(l):
 if l[0]in"d p i":c,u=l;U=V[u]=V.get(u,0)+"pi".find(c);S=U<0;V[u]+=S;c<"p"or print(u,"=",U)
 else:d=lambda q:[w.isdigit()and l[int(w)]or w for w in A[l[0]][q]];S=f(d(1+f(d(0))))
 return S
for z in open("P"):
 l=z.split("#")[0].split()
 if"a "==z[:2]:a,s,*x=3,l[1]
 elif l*a:x+=l,;a-=1;A[s]=x
 elif l:f(l)

(-6 ไบต์ขอบคุณ @orlp)

ยังคงเล่นกอล์ฟ Pถือว่าโปรแกรมที่ถูกเก็บไว้ในไฟล์ชื่อ

การวางสายเข้าfในแลมบ์ดาdจะช่วยประหยัดได้ไม่กี่ไบต์ แต่มันจะทำให้กรณีทดสอบสุดท้ายมีความลึกสูงสุดในการเรียกซ้ำ

โปรแกรม Prindeal บางโปรแกรม

โปรแกรมลบไร้ประโยชน์

นี่คือโปรแกรมลบไร้ประโยชน์ มันไร้ประโยชน์เพราะแม้ว่ามันจะถูกลบอย่างเหมาะสม แต่มันก็ไม่ได้กลับสู่ความสำเร็จ / ความล้มเหลวตามนั้น

ผลลัพธ์ควรเป็น:

a = 15
b = 6
__________ = 0
a = 9
b = 6

Countup

a helper
 p 1
 countup 1
 i success

a countup
 i 1
 helper 1
 d failure

countup n

นับขึ้นไปและพิมพ์nตลอดไป อาจทำหน้าที่ทดสอบความเร็วของล่าม (ระวังการติดตามย้อนกลับบนคีย์บอร์ดขัดจังหวะ)


2
ทุกคนในคำถามนี้พลาดกอล์ฟนี้ฉันไม่เข้าใจว่าทำไม และทุกรูปแบบของมันจะถูกแทนที่ด้วยง่ายl[:(l+"#").find("#")] l.split('#')[0]
orlp

@ orlp มุ่งเน้นไปfindที่ฉันลืมคุณได้splitแม้ว่า#จะไม่ได้มี ขอบคุณ :)
Sp3000

6

JavaScript (ES6), 273 258

แก้ไขข้อผิดพลาดคงที่และเพิ่มชุดทดสอบจริง

ไม่นับการเว้นวรรคนำหน้าและการขึ้นบรรทัดใหม่

แน่นอนสามารถเล่นกอล์ฟได้อีกเล็กน้อย

เหนื่อยเกินกว่าจะเขียนคำอธิบายในตอนนี้ฉันคิดว่ามันเป็นตัวอย่างที่ดีของการใช้การปิดเพื่อรักษาค่าชั่วคราว (พารามิเตอร์) ที่ยังมีชีวิตอยู่

ทดสอบการเรียกใช้ตัวอย่างบนเบราว์เซอร์ที่สอดคล้องกับ EcmaScript 6 (ไม่ใช่ Chrome ไม่ใช่ MSIE โดยเฉพาะฉันทดสอบบน Firefox, Safari 9 แล้ว)

F=p=>(
  p=p.match(/^[^#\n]+/gm).filter(r=>r.trim(o='',v=[])),
  s={
    '':_=>1,
    p:a=>o+=a+` = ${v[a]||0}\n`,
    i:a=>v[a]=-~v[a],
    d:a=>v[a]&&v[a]--,
    a:(n,j)=>s[n]=(u,t,a)=>x(p[!x(p[j+1],0,a,1)+j+2],0,a,1)
  },
  p.map(x=(r,i,w,l,a=r.split(/ +/).slice(l).map(x=>-x?w[x]:x))=>s[a[0]](a[1],i,a)),
  o
)

// TEST

$('#O tr').each(function() {
  var $cells = $(this).find('td')
  var prg = $cells.eq(0).text()
  console.log(prg)
  var output = F(prg)
  $cells.eq(1).text(output)
})
#O td { vertical-align:top; white-space: pre; border: 1px solid #888; font-family:monospace }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
<tr><th>Program</th><th>Outpout</th></tr>
<tbody id=O>  
<tr><td>p _MyVariable_321
p screaming_hairy_armadillo</td><td></td></tr>
<tr><td>i alpaca
p alpaca
i alpaca
p alpaca</td><td></td></tr>
<tr><td>i malamute
p malamute
d malamute    #success
p malamute
d malamute    #failure
p malamute
d akita       #failure
p akita</td><td></td></tr>
<tr><td>a increment_frog_twice
 i frog
 i frog
 d frog
p frog
increment_frog_twice
p frog</td><td></td></tr>
<tr><td>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</td><td></td></tr>
<tr><td>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</td><td></td></tr>
<tr><td>#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  
</td><td></td></tr>
</tbody>
</table>


ฉันได้เพิ่มความคิดเห็นเพิ่มเติมในโปรแกรมทดสอบและดูเหมือนว่าพวกเขาทำให้รหัสของคุณไม่ทำงาน
งานอดิเรกของ Calvin

@ Calvin's อดิเรกแรกแพทช์ด่วน
edc65

3

C # 6, 653 ไบต์

นี่คือรายการของฉันอยู่ท่ามกลางทะเล Python ...

class P{string[]l;string r="";Dictionary<string,int>v=new Dictionary<string,int>();Dictionary<string,int>s=new Dictionary<string,int>();public string R(string t){l=t.Split('\n');for(int i=0;i<l.Length;i++){var z=l[i].Split(' ');if(z[0]=="a"){s.Add(z[1],i);i+=3;}else E(i, null);}return r;}bool E(int n,string[]p){var z=l[n].Split(' ');var a=z.Skip(1).Select(x=>Char.IsDigit(x[0])?p[int.Parse(x)-1]:x).ToArray();if(a.Length>0&&!v.ContainsKey(a[0]))v[a[0]]=0;if (z[0]=="p")r+=$"{a[0]} = {v[a[0]]}\n";else if(z[0]=="i")v[a[0]]++;else if(z[0]=="d")if(v[a[0]]>0)v[a[0]]--;else return false;else{var y=s[z[0]];return E(y+1,a)?E(y+2,a):E(y+3,a);}return true;}}

ขยายและแสดงความคิดเห็น:

class Prindeal
{
    string[] lines;
    string result = "";
    Dictionary<string, int> variables = new Dictionary<string, int>();
    Dictionary<string, int> statements = new Dictionary<string, int>();

    public string Run(string text)
    {
        lines = text.Split('\n');

        for (int i = 0; i < lines.Length; i++)
        {
            // Split on spaces to get the statement and any arguments
            var z = lines[i].Split(' ');

            // Are we defining a new statement?
            if (z[0] == "a")
            {
                // Add to the statements dictionary, step over definition statements
                statements.Add(z[1], i);
                i += 3;
            }
            else
            {
                // Execute the statement
                Execute(i, null);
            }
        }

        return result;
    }

    bool Execute(int lineNumber, string[] parameters)
    {
        // Split on spaces to get the statement and any arguments
        var z = lines[lineNumber].Split(' ');

        // Parse the arguments - if it's a number, get the corresponding 
        // parameter from the calling statement
        var arguments = z.Skip(1).Select(
            x => Char.IsDigit(x[0]) ? 
            parameters[int.Parse(x) - 1] : 
            x)
            .ToArray();

        // If the first argument isn't already in the variables dict, add it
        if (arguments.Length > 0 && !variables.ContainsKey(arguments[0])) variables[arguments[0]] = 0;

        // Print statement, using string interpolation
        if (z[0] == "p")
            result += $"{arguments[0]} = {variables[arguments[0]]}\n";
        // Increment statement
        else if (z[0] == "i")
            variables[arguments[0]]++;
        // Decrement statement
        else if (z[0] == "d")
            if (variables[arguments[0]] > 0)
                variables[arguments[0]]--;
            else
                return false;
        else
        {
            // Get the line number to jump to
            var y = statements[z[0]];

            // Execute A ? B : C
            return Execute(y + 1, arguments) ? Execute(y + 2, arguments) : Execute(y + 3, arguments);
        }

        // If we reach this point, it's from a 'p', 'i' or 'd' statement which has succeeded
        return true;
    }
}

หากต้องการใช้ให้ยกตัวอย่างคลาสและเรียกใช้R()เมธอดตัวอย่างเช่น:

string prindealText = new StreamReader("prindeal.txt").ReadToEnd();
Console.WriteLine(new P().R(prindealText));

3

เสียงกระเพื่อมสามัญ 758 646 619

(progn(set-macro-character #\#(get-macro-character #\;))(setf(readtable-case *readtable*):invert)(#3=defun v(s)(if(boundp s)(eval s)0))(#3# i(s)(set s(1+ (v s))))(#3# d(s)(and(plusp(v s))(set s(1-(v s)))))(#3# p(s)(format t"~A = ~A~%"s(v s)))(defmacro a(n . p)`(#3#,(cadr n)(&rest g)(if,@p)))(#3# k(s)(typecase s(integer`(nth,(1- s)g))(symbol `',s)(t(list*(car s)(mapcar 'k(cdr s))))))(#3# r()(prog(l p q)$(setf p()l(make-string-input-stream(or(read-line()()())(return))))@(when(setf p(read l()()))(push p q)(go @))(if q(return(k(reverse q)))(go $))))(do ((x(r)(r)))((not x))(eval(if(eq(car x)'a)`(,@x,(r),(r),(r))x))))

ใส่สิ่งนี้ในfile.lispและโทรเช่นsbcl --script file.lisp; อินพุตถูกอ่านจากอินพุตสตรีมมาตรฐาน

รุ่นนี้จะแยกวิเคราะห์supersetของ Prindeal: ไม่มีปัญหาไม่มากคุณสามารถเข้าถึงทั้งหมด Common เสียงกระเพื่อมจากแหล่ง Prindeal ฉันพิจารณาคุณลักษณะนี้ของผู้บุกรุก

แสดงความคิดเห็นรุ่น

;; copy-readtable is only used during development, so that I do not 
;; mess with my running environment. The real code starts with the
;; progn below, which is superfluous of course inside a let.
(let ((*readtable* (copy-readtable)))

  ;; I use PROGN in the golfed version so that I can have the whole
  ;; program as a unique tree. This allows me to define reader 
  ;; variables like #3=defun in order to gain a few bytes by writing
  ;; #3# instead of defun. Reader variables are removed in
  ;; this human-friendly version.
  (progn
    ;; Let # point to the same reader function as ;
    ;; Of course, ; is still usable as a comment delimiter
    (set-macro-character #\#
                         (get-macro-character #\;))

    ;; :invert does what is necessary to enable case-sensitive reading
    ;; and printing of symbols
    (setf (readtable-case *readtable*) :invert)

    ;; value of symbol, or zero
    (defun v(s)(if(boundp s)(eval s)0))

    ;; increment
    (defun i(s)(set s(1+ (v s))))

    ;; decrement
    (defun d(s)(and(plusp(v s))(set s(1-(v s)))))

    ;; print
    (defun p(s)(format t"~A = ~A~%"s(v s)))

    ;; alias: wrap an "if" inside a "defun".
    ;; YES, that means you can redefine ANY lisp function with "a" !
    ;; A safer version would properly intern symbols in a dedicated package.
    ;;
    ;; Notice the G variable.  We take advantage of the "unhygienic"
    ;; (what a bad adjective) nature of macros to create a context
    ;; where G is bound to the argument list. The same G is referenced
    ;; implicitely later.
    (defmacro a(n . p)`(defun,(cadr n)(&rest g)(if,@p)))

    ;; Canonicalize expressions:
    ;;
    ;; - if s is a symbol, return s quoted. All functions manipulate
    ;; symbols in order to allow the undeclared use of variables. With
    ;; symbols, we can check for boundness.
    ;;
    ;; - if s is an integer, then we are inside an alias definition. The
    ;; integer is replaced by an access to the s'th element of the
    ;; implicit argument list G using (nth (1- s) g). G will be bound
    ;; when the expressions is injected in the defun corresponding to
    ;; the alias, or else an error will be signaled: either because G
    ;; is unbound, or because you defined a variable named G which is
    ;; by construction not a list. Since we do not sanitize properly
    ;; the input, you could bind G globally to a list, but that would be
    ;; nasty.
    ;; 
    ;; - Finally, if s is a list, apply k to all but the first
    ;; elements of s.  The first element is a symbol but we do not
    ;; need to quote it because we want to call the function
    ;; associated with the symbol. Due to the Lisp-2-ness
    ;; of Common Lisp, functions and variables can coexist
    ;; with the same name.
    ;;
    (defun k(s)(typecase s
                 (integer`(nth,(1- s)g))
                 (symbol`',s)
                 (t(list*(car s)(mapcar #'k(cdr s))))))

    ;; Reader function
    (defun r()
      (prog (l ; current line, as an input-stream reading a string
             p ; current read form
             q ; whole line and return value, as a list
             )

         ;; PROG includes an implicit TAGBODY. Below, $ and @ are
         ;; labels for GO statements (gotos).

       $ (setf
          ;; emtpy p
          p ()

          ;; Read a whole line and if we do not fail, build an input
          ;; stream to read from it.
          l (make-string-input-stream
             (or (read-line()()()) ;; try to read a line,
                 (return)          ;; but return from prog if we reach
                                   ;; the end of file.
                 )))
       @ (when (setf p (read l()()))
           ;; Read a lisp expression, put it in p and if p is not nil
           ;; push it into q.  A nil could happen at the end of the
           ;; line or if someone (you know who) inserted an empty list
           ;; in the file being read.
           ;; 
           ;; Thanks to the readtable which now handles comments
           ;; and spaces for us, nothing needs to be done here to
           ;; preprocess the input.

           (push p q) (go @))

         ;; If we read an empty line, q can be nil. In this case, go
         ;; back to $ and read another line. If q is not nil, reverse
         ;; it (we pushed, remember), canonicalize it and return the
         ;; result.
         (if q (return(k(reverse q))) (go $)))
      )

    ;; Read/eval loop.  When reading "(a name)", we read the three
    ;; next lines and append them to the first so that it builds a
    ;; call the the alias definition macro a. Otherwise, just eval x.
    (do((x(r)(r))((not x))
      (eval (if (eq(car x'a))
                `(,@x,(r),(r),(r))
                x)))))

ตัวอย่าง

~$ sbcl --script file.lisp < testfile

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

หากเราแทนที่evalด้วยprintในวง read / eval เราจะเห็นสิ่งที่ถูกประเมิน:

(a 's (i '_) (d '_) (d '_)) 
(a 'f (d '_) (d '_) (d '_)) 
(a 'z (d (nth 0 g)) (z (nth 0 g)) (s)) 
(a 'n (z (nth 0 g)) (i (nth 0 g)) (s)) 
(a 'move (moveH (nth 0 g) (nth 1 g)) (move (nth 0 g) (nth 1 g)) (s)) 
(a 'moveH (d (nth 0 g)) (i (nth 1 g)) (f)) 
(a 'dupe (dupeH1 (nth 0 g) (nth 1 g) (nth 2 g))
   (dupe (nth 0 g) (nth 1 g) (nth 2 g)) (s)) 
(a 'dupeH1 (d (nth 0 g)) (dupeH2 (nth 1 g) (nth 2 g)) (f)) 
(a 'dupeH2 (i (nth 0 g)) (i (nth 1 g)) (s)) 
(a 'copy (z (nth 1 g)) (copyH (nth 0 g) (nth 1 g)) (s)) 
(a 'copyH (dupe (nth 0 g) (nth 1 g) '_copy) (move '_copy (nth 0 g)) (s)) 
(a 'addTo (copy (nth 1 g) '_add) (move '_add (nth 0 g)) (s)) 
(a 'add (z (nth 0 g)) (addH (nth 0 g) (nth 1 g) (nth 2 g)) (s)) 
(a 'addH (addTo (nth 0 g) (nth 1 g)) (addTo (nth 0 g) (nth 2 g)) (s)) 
(a 'mul (mulH1 (nth 0 g) (nth 1 g)) (mulH2 (nth 0 g) (nth 2 g)) (s)) 
(a 'mulH1 (z (nth 0 g)) (copy (nth 1 g) '_mul) (s)) 
(a 'mulH2 (mulH3 (nth 0 g) (nth 1 g)) (mulH2 (nth 0 g) (nth 1 g)) (s)) 
(a 'mulH3 (d '_mul) (addTo (nth 0 g) (nth 1 g)) (f)) 
(a 'mulBy (mul '_mulBy (nth 0 g) (nth 1 g)) (copy '_mulBy (nth 0 g)) (s)) 
(a 'pow (powH1 (nth 0 g) (nth 2 g)) (powH2 (nth 0 g) (nth 1 g)) (s)) 
(a 'powH1 (n (nth 0 g)) (copy (nth 1 g) '_pow) (s)) 
(a 'powH2 (powH3 (nth 0 g) (nth 1 g)) (powH2 (nth 0 g) (nth 1 g)) (s)) 
(a 'powH3 (d '_pow) (mulBy (nth 0 g) (nth 1 g)) (f)) 
(p 'A) 
(p 'B) 
(p 'C) 
(n 'A) 
(n 'B) 
(add 'C 'A 'B) 
(p '____) 
(p 'A) 
(p 'B) 
(p 'C) 
(add 'B 'A 'C) 
(p '____) 
(p 'A) 
(p 'B) 
(p 'C) 
(mul 'd 'B 'C) 
(p '____) 
(p 'd) 
(mulBy 'd 'B) 
(p '____) 
(p 'd) 
(d 'A) 
(mulBy 'd 'A) 
(p '____) 
(p 'd) 
(pow 'A 'C 'B) 
(p '____) 
(p 'A) 
(p 'B) 
(p 'C) 
(pow 'A 'B 'C) 
(p '____) 
(p 'A) 
(p 'B) 
(p 'C) 
(pow 'C 'A 'B) 
(p '____) 
(p 'A) 
(p 'B) 
(p 'C)

Macroexpansion

หากเราเลือกนิยามนามแฝงต่อไปนี้:

(a 'powH2 (powH3 (nth 0 g) (nth 1 g)) (powH2 (nth 0 g) (nth 1 g)) (s))

... เราสามารถดูการอ้างอิงไปยังตัวแปรที่มีชื่อgซึ่งไม่พบในขอบเขตคำศัพท์ แต่หลังจาก macroexpansion นี่คือโค้ดจริงที่กำลังถูกประเมิน:

(defun powH2 (&rest g)
  (if (powH3 (nth 0 g) (nth 1 g))
      (powH2 (nth 0 g) (nth 1 g))
      (s))) 

ตอนนี้gอ้างถึงรายการอาร์กิวเมนต์ของฟังก์ชั่นที่ถูกกำหนดไว้


2

Python 2, 486 ไบต์

นี่เป็นทางออกอ้างอิงที่ฉันเล่นกอล์ฟมากขึ้น (ปัจจุบัน -98 ไบต์)

import sys;sys.setrecursionlimit(2000)
def r(s):
 n=s[0]
 if n in A:f=lambda i:r([s[int(t)]if'0'<t[0]<':'else t for t in A[n][i]]);return f(1+(f(0)or 0))
 k=s[1]
 if'i'<n:print k,'=',V.get(k,0)
 elif'd'<n:V[k]=-~V[k]if k in V else 1
 elif'a'<n:
    if~-(k in V)or V[k]<1:return 1
    V[k]-=1
 else:A[k]=s[2:]
A={};V={};c=filter(bool,([l,l[:l.find('#')]]['#'in l]for l in input().split('\n')))
while c:
 s=c[0].split();c=c[1:]
 if'a'!=s[0]:r(s)
 else:r(['a',s[1]]+map(str.split,c[:3]));c=c[3:]

การเปลี่ยนแปลง (ที่ฉันจำได้):

  • การแปลงบูลีน - จำนวนเต็มแบบอัตโนมัติ ( [l,l[:l.find('#')]]['#'in l])
  • ตั้งหรือเพิ่มขึ้นในหนึ่งคำสั่ง ( V[k]=-~V[k]if k in V else 1)
  • นามแฝงเพิ่มเติมสำหรับนิพจน์ที่ยาวขึ้น ( k=s[1])
  • ไม่มีตัวนับในลูปหลักทำให้ล้างรายการอินพุตแทน
  • printเพิ่มช่องว่างโดยอัตโนมัติ ( print k,'=',V.get(k,0))
  • ตรวจสอบตัวเลข 1-9 ( '0'<t[0]<':')
  • พลิกค่าส่งกลับrประมาณเพื่อบันทึกreturns
  • การลบการทำซ้ำของการแบ่งและการแยก ( map(str.split,c[:3])))

1

Python 3, 1322 ไบต์

แข็งแรงเล่นกอล์ฟ:

import re,sys;sys.setrecursionlimit(2000);F,L=filter,list
class P:
 N,O,F=0,{},{}
 def __init__(S,c):
  S.B,S.E={"p":S.P,"i":S.I,"d":S.D,"a":S.L},dict(enumerate(F(None,[i.split('#')[0].rstrip()for i in c.splitlines()])))
  while S.N in S.E:S.X(S.E[S.N])
 def V(S, v, y, z=0):
  if re.match("[\w_][\d\w_]*",v):
   if not v in y:
    if z is not None:y[v]=z
    else:return False
   return True
  return False
 def A(S):S.N+=1
 def P(S,v):
  if S.V(v,S.O):print("{0} = {1}".format(v, S.O[v]));return True
  return False
 def I(S,v):
  if S.V(v, S.O):S.O[v]+=1;return True
  return False
 def D(S,v):
  if S.V(v,S.O)and S.O[v]>0:S.O[v]-=1;return True
  return False
 def L(S,v):
  e=[]
  if S.V(v,S.F,e):
   for i in range(3):S.A();e.append(S.E[S.N].lstrip())
   return True
  return False
 def C(S,c,v):
  def R(Z,v):
   for i in re.findall("\s(\d+)", Z):Z=Z.replace(" %s"%i," %s"%v[int(i)-1])
   return Z
  Q,m,f=map(lambda l:R(l,v),S.F[c])
  if S.X(Q,False):return S.X(m,False)
  return S.X(f,False)
 def X(S,Z,C=True):
  u=re.match("\s?([\w_][\d\w_]*)\s?([\w_][\d\w ]*)?",Z)
  if u:
   c,v=map(lambda i:''if i is None else i,u.groups());v=L(F(None,v.split(' ')))
   if S.V(c,S.F,None):
    T=S.C(c, v)
    if C:S.A()
   elif S.V(c,S.B,None):
    T=S.B[c](*v)
    if C:S.A()
   else:return False
   return T
  return False

Ungolfed:

import re

class Prindeal:
    iline = 0
    local = {}
    udef = {}
    content  = {}

    def __init__(self, c):
        self.built = {
            "p": self.print,
            "i": self.increment,
            "d": self.decrement,
            "a": self.alias,
        }
        self.content = dict(enumerate(filter(None, [i.split('#')[0].rstrip()for i in c.splitlines()])))
        while self.iline in self.content:
            self.execute_line(self.content[self.iline])

    def validate_name(self, varname, stack, default=0):
        if re.match("[\w_][\d\w_]*", varname):
            if not varname in stack:
                if default is not None:
                    stack[varname] = default
                else:
                    return False
            return True
        return False

    def advance_stack(self):
        self.iline += 1

    def print(self, varname):
        if self.validate_name(varname, self.local):
            print("{0} = {1}".format(varname, self.local[varname]))
            return True
        return False

    def increment(self, varname):
        if self.validate_name(varname, self.local):
            self.local[varname] += 1
            return True
        return False

    def decrement(self, varname):
        if self.validate_name(varname, self.local) and self.local[varname] > 0:
            self.local[varname] -= 1
            return True
        return False

    def alias(self, aliasname):
        indexed_lines = []
        if self.validate_name(aliasname, self.udef, indexed_lines):
            for i in range(3):
                self.advance_stack()
                indexed_lines.append(self.content[self.iline].lstrip())
            return True
        return False

    def execute_alias(self, cmd, variables):
        def parse_args(line, variables):
            for i in re.findall("\s(\d+)", line):
                line = line.replace(" %s" % i, " %s" % variables[int(i) - 1])
            return line
        init, success, failure = map(lambda l: parse_args(l, variables), self.udef[cmd])
        if self.execute_line(init, False):
            return self.execute_line(success, False)
        return self.execute_line(failure, False)

    def execute_line(self, line, cont=True):
        valid_execution = re.match("\s?([\w_][\d\w_]*)\s?([\w_][\d\w ]*)?", line)
        if valid_execution:
            cmd, variables = map(lambda i: '' if i is None else i, valid_execution.groups())
            variables = list(filter(None, variables.split(' ')))
            if self.validate_name(cmd, self.udef, None):
                temp = self.execute_alias(cmd, variables)
                if cont:
                    self.advance_stack()
            elif self.validate_name(cmd, self.built, None):
                temp = self.built[cmd](*variables)
                if cont:
                    self.advance_stack()
            else:
                return False
            return temp
        return False

การใช้งาน:

P(c)

cเนื้อหาข้อความอยู่ที่ไหน

ตัวอย่าง:

ยอมรับสตริงสายเดี่ยว:

  • P("p cat")
  • P("p dog\ni dog\np dog")

ยอมรับสายที่มีหลายแถว:

P("""
p dog
i dog
p dog
""")

หรือ:

P("""p dog
i dog
p dog""")

เป็นต้น

หมายเหตุ:

ทำงานได้อย่างถูกต้องสำหรับกรณีทดสอบทั้งหมด แต่ถึงขีด จำกัด การเรียกซ้ำใน:

pow C A B   #C = A ^ B = 9 ^ 3 = 729

sys.setrecursionlimit(2000)ดังนั้น


1
มันจะใช้จำนวนไบต์ไม่มากนัก แต่คุณไม่สามารถใช้ sys.setrecursionlimit () เพื่อให้มันทำงานได้อย่างถูกต้องกับ pow alias ใช่ไหม
Corwin

ฉันทำได้ แต่ OP ระบุว่าภาษาเช่น Python (ที่มีข้อ จำกัด การเรียกซ้ำ) ได้รับการยอมรับตามที่เป็น อย่างไรก็ตามฉันจะเพิ่มการแก้ไขหากได้รับการร้องขอจาก OP @Corwin
Zach Gates

ยุติธรรมพอสมควร คิดถึงว่าในสเป็ค @ZachGates
Corwin

1

Python - 695 688 ไบต์

def p(v):print v,"=",w.get(v,0)
def i(v):w[v]=w.get(v,0)+1
def d(v):
 if v in w:
<TAB>w[v]-=1
<TAB>if not w[v]:del w[v]
 else:return 1
def a(n,b,d,h):
 def g(*a):
<TAB>i=1;f=b;s=d;t=h
<TAB>for v in a:v=q+v+q;k=q+j(i)+q;f=c(f,k,v);s=c(s,k,v);t=c(t,k,v);i+=1
<TAB>y=u(t,e)if u(f,e)else u(s,e);i=1;return y
 e[n]=g
q="'";w=x={};u=eval;e={'a':a,'d':d,'i':i,'p':p};import sys;l=sys.stdin.readlines();r="";j=str;c=j.replace;sys.setrecursionlimit(2000)
for h in l:
 h = h.strip()
 if not h:continue
 l = h.split();f=l[0];n=f+"("
 if "#" in f:continue
 for g in l[1:]:
<TAB>b=g.find("#")+1
<TAB>if b:g=g[:b-1]
<TAB>if g:n+="'%s',"%g
<TAB>if b:break
 if x:x-=1;d+='"%s)",'%n
 else:x=(f=="a")*3;d=n
 if not x:d+=")\n";r+=d
exec r in e

<TAB> เป็นอักขระแท็บตัวอักษร


1

C ++, 1111 ไบต์

อันนี้คือ C ++ - เป็นสำนวนที่ฉันสามารถทำได้
นั่นหมายถึงการเพิ่ม C ++ - ish และ C-ish ที่น้อยลง
นั่นหมายความว่ามันใหญ่กว่าโปรแกรม C ที่เทียบเท่า
ฉันคิดว่า C ++ rivals Java สำหรับไลบรารีมาตรฐาน verbose
มันรวบรวมกับ VS2013 และ g ++ 4.9.2 (ด้วย -std = c ++ 11)

#include<array>
#include<iostream>
#include<map>
#include<regex>
#include<sstream>
#include<stack>
#define B std::
#define a first
#define b second
#define c(s);else if(x.a==s)
#define d(n)B getline(B cin,r##n)
#define e(n)r##n=B regex_replace(r##n,q,"$1");
#define f(n)do{d(n);e(n)}while(r##n.empty());
#define g B string
#define h B istream_iterator<g>
#define i p.top().a
#define j p.empty()
#define k B pair
#define u continue;
#define w B back_inserter
typedef B vector<g>s;typedef B array<g,3>A;typedef k<k<long,A>,s>t;B map<g,A>m;B map<g,long>n;B stack<t>p;B regex q("^ *(.*?) *(#.*)?$");int main(){g r0,r1,r2,r3;while(d(0)){e(0)if(r0.empty())u p.push(t{{0,{{r0,"",""}}},{}});bool z;while(!j){k<g,s>x;B istringstream ss(i.b[i.a]);ss>>x.a;B copy(h(ss),h(),w(x.b));s o;B transform(B begin(x.b),B end(x.b),w(o),[](g y){int v=atoi(y.c_str());return v>0?p.top().b[v-1]:y;});z=true;if(0)c("")c("p")B cout<<o[0]<<" = "<<n[o[0]]<<B endl c("i")n[o[0]]++c("d")n[o[0]]-=(z=n[o[0]])c("a"){f(1)f(2)f(3)m.insert(B make_pair(o[0],A{{r1,r2,r3}}));}else{p.push(t{{0,m[x.a]},o});u}while(!j&&i.a)p.pop();if(!j)i.a+=1+!z;}}}

ด้านล่างเป็นต้นฉบับ หากใครสามารถคิดวิธีที่จะทำให้มันสำนวนมากขึ้นและสั้นลงในเวลาเดียวกันโปรดแจ้งให้เราทราบ

#include <array>
#include <iostream>
#include <map>
#include <regex>
#include <sstream>
#include <stack>

typedef std::vector<std::string> List;
typedef std::pair<std::string, List> Statement;
typedef std::array<std::string, 3> Alias;
typedef std::pair<long, Alias> IndexedAlias;
typedef std::pair<IndexedAlias, List> Item;

std::map<std::string, Alias> aliases;
std::map<std::string, long> variables;
std::stack<Item> stack;
std::regex re("^ *(.*?) *(#.*)?$");

int main()
{
    std::string line, line1, line2, line3;
    while (std::getline(std::cin, line)) // control-Z to exit
    {
        line = std::regex_replace(line, re, "$1");
        if (line.empty()) continue;
        stack.push(Item{ { 0, { { line, "", "" } } }, {} });

        bool flag;
        while (!stack.empty())
        {
            Statement statement;
            std::istringstream ss(stack.top().first.second[stack.top().first.first]);
            ss >> statement.first;
            std::copy(std::istream_iterator<std::string>(ss), std::istream_iterator<std::string>(), std::back_inserter(statement.second));

            List arguments;
            std::transform(std::begin(statement.second), std::end(statement.second), std::back_inserter(arguments),
                [](std::string arg){ int i = atoi(arg.c_str()); return i > 0 ? stack.top().second[i - 1] : arg; });

            flag = true;
            if (statement.first == "")
                ;
            else if (statement.first == "p")
                std::cout << arguments[0] << " = " << variables[arguments[0]] << std::endl;
            else if (statement.first == "i")
                variables[arguments[0]]++;
            else if (statement.first == "d")
                variables[arguments[0]] -= (flag = variables[arguments[0]]);
            else if (statement.first == "a")
            {
                do { std::getline(std::cin, line1); line1 = std::regex_replace(line1, re, "$1"); } while (line1.empty());
                do { std::getline(std::cin, line2); line2 = std::regex_replace(line2, re, "$1"); } while (line2.empty());
                do { std::getline(std::cin, line3); line3 = std::regex_replace(line3, re, "$1"); } while (line3.empty());
                aliases.insert(std::make_pair(arguments[0], Alias{ { line1, line2, line3 } }));
            }
            else
            {
                stack.push(Item{ { 0, aliases[statement.first] }, arguments });
                continue;
            }

            while (!stack.empty() && stack.top().first.first) stack.pop();
            if (!stack.empty()) stack.top().first.first += 1 + !flag;
        }
    }

    std::cout << "-- Variables --" << std::endl;
    std::transform(std::begin(variables), std::end(variables), std::ostream_iterator<std::string>(std::cout, "\n"),
        [](std::map<std::string, long>::value_type pair){ std::ostringstream ss; ss << pair.first << " = " << pair.second; return ss.str(); });
    std::cout << "-- Aliases --" << std::endl;
    std::transform(std::begin(aliases), std::end(aliases), std::ostream_iterator<std::string>(std::cout, "\n"),
        [](std::map<std::string, Alias>::value_type pair){ std::ostringstream ss; ss << pair.first << " = [1]:" << pair.second[0] << " [2]:" << pair.second[1] << " [3]:" << pair.second[1]; return ss.str(); });
    std::cout << "---------------" << std::endl;

    return 0;
}

0

Haskell, 1009

ฉันพยายามอย่างดีที่สุดเพื่อเล่นกอล์ฟ รหัสที่ไม่ดีของฉันประกอบด้วยอักขระมากกว่า 3,000 ตัว ณ จุดนี้ฉันจำไม่ได้ว่าทุกฟังก์ชั่นกำลังทำอะไรอยู่ดังนั้นการตีกอล์ฟให้มากขึ้นหมายถึงการเดาว่าอะไรจะทำให้พังและสิ่งที่จะไม่เกิดขึ้น

import qualified Data.Map as M
import Control.Monad.State.Lazy
import Data.List
type A=M.Map String
data P=P(A Int)(A([String]->StateT P IO Int))
a f=evalStateT f(P M.empty$M.fromList[("i",\(b:_)->(+1)%b),("d",\(b:_)->pred%b),("p",\(b:_)->i b>>= \v->liftIO(putStrLn$b++"="++show v)>>q 1)])
e(k:l)=do{(P v a)<-get;put.P v$M.insert k(m l)a;q 1}
g t s f= \a->t a>>= \b->if b>0then s a else f a
f%k=f<$>i k>>= \v->if v<0then k#0>>q 0else k#v>>q 1
i k=get>>= \(P v _)->q$M.findWithDefault 0 k v
k#v=get>>= \(P b a)->put$P(M.insert k v b)a
l k=get>>= \(P _ a)->q$a M.!k
f s=let(f:a)=r s in($a)<$>l f>>=id
m(t:s:f:_)=g(k t)(k s)(k f)
k s=let(f:b)=r s in\a->($(map((\y z->if all(\c->c>'/'&&c<':')z then y!!(read z-1)else z)a)b))<$>l f>>=id
n=dropWhileEnd(==' ').takeWhile(not.(=='#')).dropWhile(==' ')
o[]=[]
o(l:ls)|(head.r$l)=="a"=(l:take 3 ls):(o$drop 3 ls)|1>0=[l]:o ls
p s|length s>1=e$(n.tail.head$s):tail s|1>0=f.head$s
q=return
main=join$a.(\s->mapM_ p(o.filter(not.null).map n.lines$s))<$>getContents
r=words
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.