เขียนล่ามราคา 99


99

99 (เด่นชัด "เก้าสิบเก้า") เป็นภาษาการเขียนโปรแกรมลึกลับใหม่ล่าสุด(เพื่อไม่ให้สับสนกับ99โน้ตตัวเอียง) งานของคุณในการท้าทายนี้คือการเขียนล่ามให้กับ99ที่สั้นที่สุด การส่งที่มีจำนวนไบต์น้อยที่สุดจะเป็นผู้ชนะ Tiebreaker จะไปยังการส่งที่โพสต์ก่อน

เนื่องจากคำถามนี้มีความลึกมากกว่าปกติเล็กน้อยและฉันอยากเห็นคำตอบที่ดีฉันจะมอบรางวัล 250 ตัวแทนให้กับคำตอบที่ฉันโปรดปราน (ไม่จำเป็นต้องเป็นผู้ชนะ)

99 Spec

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

ขึ้นบรรทัดใหม่พื้นที่และ 9เป็นอักขระสามตัวเท่านั้นที่มีความสำคัญในโปรแกรม99 อักขระอื่น ๆ ทั้งหมดจะถูกละเว้นอย่างสมบูรณ์ นอกจากนี้ช่องว่างต่อท้ายในแต่ละบรรทัดจะถูกละเว้นและช่องว่างหลายช่องในแถวจะถูกอ่านเป็นหนึ่งช่องว่าง ("Newline" หมายถึงการเข้ารหัสตัวแบ่งบรรทัดทั่วไปไม่สำคัญว่าล่ามของคุณใช้ภาษาใด)

ดังนั้นโปรแกรมนี้:

   9      BLAH        99   9a9bb9c9
9 this line and the next have 6 trailing spaces 9      
      

เหมือนกับโปรแกรมนี้:

 9 99 9999
9 9

ตัวแปร

ตัวแปรใน99ทั้งหมดมีชื่อที่ถูก9โยงอย่างน้อยหนึ่งรายการเข้าด้วยกัน ( 9+ใน regex) ตัวอย่างเช่น9,99และ9999999999เป็นตัวแปรที่แตกต่างกัน โดยธรรมชาติแล้วมีจำนวน จำกัด (ยกเว้นข้อ จำกัด ของหน่วยความจำ)

ค่าของตัวแปรแต่ละตัวเป็นจำนวนเต็มความแม่นยำที่ลงนามแล้ว โดยค่าเริ่มต้นแต่ละตัวแปรจะถูกกำหนดให้เป็นตัวแทนตัวเลขของตัวเอง ดังนั้นถ้ามันถูกกำหนดใหม่ค่าของตัวแปร9คือหมายเลข 9 และค่าของตัวแปร99คือหมายเลข 99 และอื่น ๆ คุณอาจคิดว่ามันเป็นการรักษาตัวแปรเป็นตัวเลขธรรมดาจนกว่าพวกมันจะถูกกำหนดอย่างชัดเจน

ฉันจะใช้Vเพื่ออ้างถึงชื่อตัวแปรโดยพลการด้านล่าง
ตัวอย่างของแต่ละคนVจะถูกแทนที่ด้วย9, 99, 999, 9999ฯลฯ

งบ

มีห้าประเภทคำสั่งแตกต่างกันในมี99 แต่ละบรรทัดในโปรแกรม99มีคำสั่งเดียวทั้งหมด

ไวยากรณ์ที่อธิบายไว้ที่นี่ถือว่าอักขระที่ไม่เกี่ยวข้องทั้งหมดได้ถูกลบออกช่องว่างต่อท้ายทั้งหมดได้ถูกลบออกและลำดับทั้งหมดของช่องว่างหลายรายการถูกแทนที่ด้วยช่องว่างเดียว

1. ไม่มีการดำเนินงาน


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

2. เอาท์พุท

V

ตัวแปรเดี่ยวVบนบรรทัดพิมพ์ตัวแปรนั้นไปที่ stdout

หากVมีจำนวนคี่9's ( 9, 999ฯลฯ ) ดังนั้นค่าจำนวนเต็มVหารด้วย 9 จะถูกพิมพ์ (ทศนิยม)

หากVมีจำนวนเป็น9's ( 99, 9999ฯลฯ ) อักขระ ASCII ที่มีรหัสVหารด้วย 9 จะมีการพิมพ์ mod 128 (นั่นคือ(V / 9) % 128ค่าตั้งแต่ 0 ถึง 127)

ตัวอย่าง : โปรแกรม

9
9999

1Wจะพิมพ์ บรรทัดแรกพิมพ์1เพราะ 9/9 คือ 1. พิมพ์บรรทัดที่สองWเพราะ 9999/9 คือ 1111 และ 1111 mod 128 เป็น 87 และ 87 Wเป็นรหัสอักขระสำหรับ

โปรดทราบว่าตัวแบ่งบรรทัดจะไม่ถูกพิมพ์ระหว่างโทเค็นเอาท์พุท \nจะต้องพิมพ์อย่างชัดเจนเพื่อการขึ้นบรรทัด

3. อินพุต

 V

ตัวแปรเดียวVบนบรรทัดที่มีช่องว่างนำข้อมูลจาก stdin และเก็บไว้ในตัวแปรนั้น

หากVมีจำนวนคี่จาก9นั้นผู้ใช้อาจพิมพ์จำนวนเต็มใด ๆ ที่ลงนามและVจะถูกตั้งค่าเป็น 9 เท่าของค่านั้น

หากVมีจำนวนเท่า9กันผู้ใช้อาจพิมพ์ด้วยอักขระ ASCII ใดก็ได้และVจะถูกตั้งค่าเป็น 9 เท่าของรหัสอักขระ

ตัวอย่าง : กำหนด-57และAเป็นอินพุตโปรแกรมนี้

 9
9
 99
99

-57Aจะเอาท์พุท ภายในตัวแปร9จะมีค่า -513 และ99จะมีค่า 585

ล่ามของคุณอาจสันนิษฐานว่าอินพุตมีความถูกต้องทางไวยากรณ์เสมอ

4. การมอบหมาย

ข้อความนี้อาจยาวโดยพลการ มันเป็นตัวแปรสองตัวหรือมากกว่าในบรรทัดคั่นด้วยช่องว่าง:

V1 V2 V3 V4 V5 ...

สิ่งนี้กำหนดให้กับผลรวมของดัชนีที่มีค่าเท่ากันลบด้วยผลรวมของดัชนีที่มีคี่ (ไม่รวม) การบ้านเป็นค่าไม่ใช่การอ้างอิงV1VVV1

มันสามารถแปลเป็นภาษาส่วนใหญ่เป็น V1 = V2 - V3 + V4 - V5 + ...มันอาจจะแปลในภาษามากที่สุด

ดังนั้นหากมีเพียงสองตัวแปรนั่นคือการกำหนดปกติ:

V1 V2V1 = V2

หากมีสามข้อก็เป็นการลบ:

V1 V2 V3V1 = V2 - V3

และเครื่องหมาย+/ -ยังคงสลับไปมาด้วยตัวแปรเพิ่มเติมแต่ละตัว:

V1 V2 V3 V4V1 = V2 - V3 + V4

ตัวอย่าง : โปรแกรมนี้จะแสดงผล1110123:

999           Prints triple-nine divided by nine (111).
999 9 9       Assigns triple-nine to zero (nine minus nine).
999           Prints triple-nine divided by nine (0)
9 999 9       Assigns single-nine to negative nine (zero minus nine).
999 999 9     Adds nine to triple-nine (really subtracts negative nine).
999           Prints triple-nine divided by nine (1).
999 999 9     Adds nine to triple-nine (really subtracts negative nine).
999           Prints triple-nine divided by nine (2).
999 999 9     Adds nine to triple-nine (really subtracts negative nine).
999           Prints triple-nine divided by nine (3).

5. ไปที่ (กระโดดถ้าศูนย์ทั้งหมด)

ข้อความนี้อาจยาวโดยพลการ มันเป็นตัวแปรสองตัวหรือมากกว่าในบรรทัดคั่นด้วยช่องว่างโดยมีช่องว่างนำหน้า :

 V1 V2 V3 V4 V5 ...

หากค่าบางอย่างนอกเหนือจากนั้นไม่ใช่ค่าศูนย์ฟังก์ชันจะทำงานเหมือนกับไม่มีค่า ตัวชี้คำสั่งถูกย้ายไปยังบรรทัดถัดไปตามปกติV1

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

โปรดทราบว่าไม่หารด้วย 9 ที่นี่ และเนื่องจากมันเป็นไปไม่ได้ที่จะมีตัวแปรเป็นค่าที่ไม่ใช่ตัวคูณของ 9 เพียงแค่หมายเลขบรรทัดที่เป็นทวีคูณของ 9 เท่านั้นที่สามารถข้ามไปได้V1

ตัวอย่าง:

โปรแกรมนี้จะพิมพ์1ตลอดไป:

9          Prints single-nine divided by nine (always 1).
99 9 9     Assigns double-nine to zero.
 99 99     Jumps to line zero (top line) if double-nine is zero.

โปรแกรมนี้

99999999                                              Print G.
999 99                                                Set triple-nine to ninety-nine.
9999999999 9999999999 9999999999 99 99 9 9 999 999    Set 10-nine to zero.
99999999999 9999999999                                Set 11-nine to zero.





999                                                   Print triple-nine's value divided by nine. (This is the ninth line.)
99999999                                              Print G.
999 999 9                                             Subtract nine from triple-nine.
 99999 999                                            Jump to line 5-nines if triple-nine is zero (ends program).
 9 99999999999 9999999999                             Jump to line nine if 10-nine and 11-nine are zero (always jumps).

จะส่งออกตัวเลข 11 ถึง 1 ตามลำดับการลดลงล้อมรอบด้วยG's:

G11G10G9G8G7G6G5G4G3G2G1G

รายละเอียดเพิ่มเติม

ล่ามในอุดมคติจะเรียกใช้จากบรรทัดคำสั่งด้วยชื่อไฟล์โปรแกรม99เป็นอาร์กิวเมนต์ I / O จะทำทันทีในบรรทัดคำสั่ง

อย่างไรก็ตามคุณอาจเพียงแค่เขียนฟังก์ชั่นล่ามที่ใช้ในโปรแกรมเป็นสตริงเช่นเดียวกับรายการโทเค็นอินพุต (เช่น["-57", "A"]) ฟังก์ชั่นควรพิมพ์หรือคืนค่าสตริงออก

วิธีที่แตกต่างกันเล็กน้อยในการใช้ล่ามและการจัดการ I / O นั้นใช้ได้ถ้าตัวเลือกเหล่านี้เป็นไปไม่ได้ในภาษาของคุณ


โบนัส:เขียนอะไรเจ๋ง ๆ ใน99และฉันยินดีที่จะใส่ไว้ในโพสต์นี้เป็นตัวอย่าง


หวังว่าคุณจะสนุกกับการท้าทายที่99 ของฉัน ! : D


9
ฉันพิจารณาการ upvoting แต่คะแนนปัจจุบันของคุณคือ 9 ...
wchargin

30
@WChargin ดูเหมือนว่าตอนนี้คุณจะต้องลองให้ได้ 99.
trlkly

5
แน่นอนมีโบนัสสำหรับตัวเองโฮสติ้ง (เขียน99ล่าม99 ) ไม่?
Gabe

5
@Gabe คำตอบเช่นนั้นอาจจะได้รับรางวัล แต่ถ้านั่นเป็นคำตอบเดียวสิ่งที่จะตีความล่าม? ;)
งานอดิเรกของ Calvin

1
@Optimizer มันใช้งานได้: pastebin.com/raw.php?i=h73q58FN
coredump

คำตอบ:


16

CJam, 157 ไบต์

{:I;_N" 9"+--N/:P:,$W=){1a*Ab}%:V;{PT):T(=:LS%_{LS#\:,_,({(\{V=}%@{V-1@{2$*+0@-\}*\;t:V;}{:|T@V=9*?:T;}?}{~\{_V=\1&!{128%c}*o}{VIW):W=it:V;}?}?}R?Tg)TP,<*}g}

ลองออนไลน์:

คำอธิบาย

พยายามจัดรูปแบบนี้ด้วยการเยื้องที่เหมาะสมและความคิดเห็นอาจใช้เวลาตลอดไปดังนั้นฉันจะให้สรุปอัลกอริทึม

รหัสนี้เป็นบล็อกซึ่งเป็นฟังก์ชันแบบอะนาล็อกไปยังนิรนามของ CJam บล็อกคาดว่าสตริงโปรแกรมและรายการอินพุตบนสแต็กเมื่อเรียกใช้งาน

การเริ่มต้นประกอบด้วยสามขั้นตอน ก่อนบันทึกรายการอินพุต จากนั้นตัวละครทุกตัวในโปรแกรมที่ไม่มีความหมายจะถูกลบออกและผลลัพธ์จะแบ่งออกเป็นรายการบรรทัดและบันทึกไว้ ในที่สุดรายการตัวแปรจะเริ่มต้นได้ รายการนี้แมปตัวแปรแต่ละตัวซึ่งจัดทำดัชนีตามความยาวชื่อกับค่าที่หารด้วย 9 (ตัวแปรไม่สามารถเก็บค่าที่ไม่ใช่ตัวคูณ 9 และการดำเนินการทั้งหมดยกเว้นได้รับประโยชน์จากการเปลี่ยนแปลงนี้) รายการถูกเตรียมใช้งานจนถึงความยาวของบรรทัดที่ยาวที่สุดซึ่งเป็นขอบเขตบนของชื่อ varaible ที่ยาวที่สุดที่มีอยู่ นอกจากนี้ยังมีการเริ่มต้นโดยนัยเล็กน้อยเนื่องจากค่าตัวแปรเริ่มต้น: หมายเลขบรรทัดคือ 0 และดัชนีอินพุตคือ -1

ตัวแปลถูกนำมาใช้อย่างที่คาดไว้นั่นคือลูปที่อ่านบรรทัดถัดไปเพิ่มหมายเลขบรรทัดและดำเนินการบรรทัดขณะที่หมายเลขบรรทัดชี้ไปที่บรรทัดที่มีอยู่ การแยกวิเคราะห์บรรทัดแรกตรวจสอบว่าบรรทัดไม่ว่างจากนั้นแยกสาขาตามว่า arity เป็น 1 หรือ> 1 แล้วแยกสาขาตามว่ามีพื้นที่นำหน้าหรือไม่ สาขาทั้งสี่จำลองการดำเนินการสี่ (ไม่รวม op) ในลักษณะที่ตรงไปตรงมาส่วนใหญ่แม้ว่าจะเล่นกอล์ฟอย่างจริงจังเหมือนทุกสิ่งทุกอย่าง บางทีการปรับให้เหมาะสมของบันทึกย่อคือเนื่องจากลำดับอินพุตที่ถูกต้องควรสร้างองค์ประกอบประเภทที่โปรแกรมคาดหวังไว้เสมอฉันเลยละเว้นการแยกเคสสำหรับอินพุตตามความยาวของชื่อตัวแปร เป็นเพียงการสันนิษฐานว่าองค์ประกอบที่อ่านจากรายการอินพุตเป็นชนิดที่คาดหวัง


15
+1 ค่อนข้างสั้น ทีนี้คุณสามารถเขียนล่าม CJam เป็น99 ได้ไหม? ;-)
coredump

9
@coredump * shudders *
Runer112

ประณามฉันทำได้เพียง 195 ครั้งจากนั้นฉันก็หมดความหวังและยอมแพ้: P
เครื่องมือเพิ่มประสิทธิภาพ

สิ่งนี้ไม่ใช้โมดูโลที่ถูกต้องเมื่อพิมพ์ค่าลบ นี้สามารถแก้ไขได้โดยการแทนที่ด้วย128% 128,=
Martin Ender

26

Python 3, 421 414 410 404 388 395 401 ไบต์

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

import sys,re
v,i,c,g,L={},0,[re.sub('( ?)[^9]+','\\1',l).rstrip().split(' ')for l in open(sys.argv[1])],lambda i:v.get(i,int(i)//9),len
while-1<i<L(c):
 d=c[i];l=L(d);e,*f=d;i+=1
 if l>1:
  x,*y=f
  if e:w=list(map(g,f));v[e]=sum(w[::2])-sum(w[1::2])
  elif l==2:j=input();v[x]=int(j)if L(x)%2 else ord(j)
  elif~-any(g(j)for j in y):i=g(x)*9
 elif e:w=g(e);print(w if L(e)%2 else chr(w%128),end='')

Ungolfed:

import sys, re

# Intialise variable table.
vars_ = {}
get_var = lambda i: vars_.get(i, int(i)//9)

# Parse commands.
commands=[re.sub('( ?)[^9]+','\\1',l).rstrip().split(' ') for l in open(sys.argv[1])]

# Run until the current instruction index is out of bounds.
index=0
while 0 <= index < len(commands):
    # Get the current command and increment the index.
    command = commands[index]
    l = len(command)
    first = command[0]
    index += 1

    if l > 1:
        # Handle the "assignment" command.
        if first:
            operands = [get_var(i) for i in command[1:]]
            vars_[first] = sum(operands[0::2]) - sum(operands[1::2])
        # Handle the "input" command.
        elif l==2:
            inp = input()
            vars_[command[1]] = int(inp) if len(command[1]) % 2 else ord(inp)
        # Handle the "goto" command.
        elif not any(get_var(i) for i in command[2:]):
            index = get_var(command[1]) * 9
    # Handle the "output" command.
    elif first:
        val = get_var(first)
        print(val if len(first) % 2 else chr(val % 128),end='')

สวยมากเพียงแค่การติดตั้งสเป็คที่แท้จริงลงไปไกลเท่าที่ฉันจะหาได้

เรียกใช้จากบรรทัดคำสั่งโดยการจัดหาไฟล์ซอร์สโค้ด 99 ไฟล์เป็นอาร์กิวเมนต์เพียงตัวเดียว (เช่นตัวอย่างล่าสุดจาก OP):

> python3 ninetynine.py countdown.txt
G11G10G9G8G7G6G5G4G3G2G1G
>

เป็นโบนัสเพิ่มเติมต่อไปนี้คือการใช้งาน "99 ขวด" ใน99 : http://pastebin.com/nczmzkFs


1
@DLosc: เกี่ยวกับจุดแรกของคุณ: ฉันก็ว่าelseหลังจากตัวเลขสามารถลบออกได้ แต่เมื่อฉันลองก่อนหน้านี้ฉันได้รับข้อผิดพลาดทางไวยากรณ์ เคล็ดลับอื่น ๆ ของคุณชื่นชมมาก!
Mac

3
@coredump: วิธีการเขียนข้อมูลจำเพาะแต่ละตัวแปรจะมีค่าที่หารด้วยเก้าเสมอ ฉันพบว่ามันกระชับมากขึ้นเพื่อให้ตัวแปรสามารถรับค่าใด ๆและคูณ / หารด้วยเก้าเท่าตามต้องการ (โดยเฉพาะอย่างยิ่งในgotoรูทีนและเมื่อรับค่าเริ่มต้นของตัวแปร) เท่าที่ผู้ใช้ภาษามีความกังวลก็ไม่ได้สร้างความแตกต่าง
Mac

2
ไม่ใช่ของelseตัวเองเพียงแค่ช่องว่างหน้ามัน 3*n+1if n%2else n//2เช่น
DLosc

1
@DLosc: ขอโทษฉัน misspoke - elseฉันไม่แน่นอนหมายถึงพื้นที่ที่ไม่ได้เป็น ตัวอย่างเช่นฉันพยายามแทนที่print(w if L(e)%2 else chr(w%128))ด้วยprint(w if L(e)%2else chr(w%128))และได้รับข้อยกเว้นทางไวยากรณ์
Mac

1
แปลก - ฉันทดสอบบนideone.comแล้วใช้งานได้ แต่คุณพูดถูกมันไม่ได้ทำงานในล่าม Python3 จริง (3.4.0 บน Ubuntu) เคล็ดลับนี้โพสต์ชี้แจง: หมายเลขตามด้วยโทเค็นตัวอักษรทำงานโดยทั่วไป แต่ไม่ใช่สำหรับโทเค็นที่ขึ้นต้นด้วยeหรือEและ (จากความคิดเห็น) ไม่ใช่สำหรับ0orทั้งสอง
DLosc

16

เสียงกระเพื่อมสามัญ1180 857 837 836 ไบต์

ฉันรู้ว่านี่จะไม่ชนะ แต่ฉันก็สนุกกับการเล่นกอล์ฟนี้ ฉันจัดการเพื่อลบ 343 ไบต์ซึ่งเป็นล่ามมากกว่า99 รายการที่เขียนใน CJam

ยิ่งฉันพยายามบีบอัดมากเท่าไหร่ฉันก็ยิ่งพยายามเกลี้ยกล่อมคอมไพล์Lisp ให้สั้นลงเท่านั้นมันยิ่งสั้นในการคอมไพล์โค้ดมากกว่าที่จะลองตีความมันในทันที

(defmacro g(g &aux a(~ -1)> d x q(m 0)r v(n t)c(w 0)? u z)(flet((w(n p)(intern(format()"~a~a"p n))))(#1=tagbody %(case(setf c(ignore-errors(elt g(incf ~))))(#\  #2=(when(> w 0)(pushnew w v)(if u()(setq ?(oddp w)))(#5=push(w w'V)u)(setf w 0))(setf z t))(#\9(incf w)(setf >(or >(and n z))z()n()))((#\Newline())#2#(#5#(when u(setf u(reverse u)a(pop u))(if >(if u`(when(every'zerop(list,@u))(setf @,a)(go ^))`(setf,a,(if ?'(read)'(char-code(read-char)))))(if u`(setf,a,(do(p m)((not u)`(-(+,@p),@m))(#5#(pop u)p)(#5#(if u(pop u)0)m)))`(princ,(if ? a`(code-char(mod,a 128)))))))r)(incf m)(setf ?()u()z()>()n t)))(if c(go %))$(decf m)(setq d(pop r))(if d(#5# d x))(when(=(mod m 9)0)(#5#(w #3=(/ m 9)'L)x)(#5#`(,#3#(go,(w #3#'L)))q))(if(>= m 0)(go $)))`(let(@,@(mapcar(lambda(n)`(,(w n'V),(/(1-(expt 10 n))9)))v))(#1#,@x(go >)^(case @,@q)>))))
  • การวิเคราะห์คำศัพท์และการสร้างโค้ดถูกอินเตอร์ลีฟ: ฉันไม่เก็บการเป็นตัวแทนภายใน แต่ประมวลผลแต่ละบรรทัดโดยตรง
  • มีเพียงหนึ่งเดียวที่tagbodyจะทำการลูป 2:

     (... (tagbody % ... (go %) $ ... (go $)) result)
    
  • มีการประกาศตัวแปรท้องถิ่น &aux

  • อย่าสร้างการปิด แต่ให้ตีความรหัสโดยตรง
  • เป็นต้น

Ungolfed แสดงความคิดเห็น

(defmacro parse-99
    (string &aux
              (~ -1) ; current position in string
              a      ; first variable in a line 
              >      ; does current line starts with a leading space?
              d      ; holds a statement during code generation
              x      ; all statements (labels + expressions)
              q      ; all generated case statements 
              (m 0)  ; count program lines (first increases, then decreases) 
              r      ; list of parsed expressions (without labels)
              v      ; set of variables in program, as integers: 999 is 3
              (n t)  ; are we in a new line without having read a variable? 
              c      ; current char in string 
              (w 0)  ; currently parsed variable, as integer 
              ?      ; is first variable odd? 
              u      ; list of variables in current line, as integers
              z)     ; is the last read token a space?
  (flet((w(n p)
          ;; produce symbols for 99 variables
          ;; e.g. (10 'V) => 'V10
          ;;      (4 'L)  => 'L4
          (intern(format()"~a~a"p n))))
    (tagbody
     parse
       (case (setf c
                   ;; read current char in string,
                   ;; which can be NIL if out-of-bounds
                   (ignore-errors(aref string (incf ~))))

         ;; Space character
         (#\Space
          #2=(when(> w 0)
               (pushnew w v)            ; we were parsing a variable, add it to "v"
               (if u()(setq ?(oddp w))) ; if stack is empty, this is the first variable, determine if odd
               (push(w w'V)u)           ; add to stack of statement variable
               (setf w 0))              ; reset w for next variable

          ;; Space can either be significant (beginning of line,
          ;; preceding a variable), or not. We don't know yet.
          (setf z t))

         ;; Nine
         (#\9
          (incf w) ; increment count of nines
          (setf >(or >(and n z)) ; there is an indent if we were
                                 ; starting a newline and reading a
                                 ; space up to this variable (or if we
                                 ; already know that there is an
                                 ; indent in current line).
                ;; reset z and n
                z()n()))

         ;; Newline, or end of string
         ((#\Newline())
          #2#  ;; COPY-PASTE the above (when(> w 0)...) statement,
               ;; which adds previously read variable if necessary.

          ;; We can now convert the currently read line.
          ;; We push either NIL or a statement into variable R.

          (push(when u
                     (setf u (reverse u) ; we pushed, we must reverse
                           a (pop u))    ; a is the first element, u is popped
                     (if >
                         ;; STARTS WITH LEADING SPACE
                         (if u
                             ;; JUMP
                             `(when(every'zerop(list,@u))(setf @,a)(go ^))

                             ;; READ
                             `(setf,a,(if ?'(read)'(char-code(read-char)))))

                         ;; STARTS WITH VARIABLE
                         (if u

                             ;; ARITHMETIC
                             `(setf,a,(do(p m) ; declare p (plus) and m (minus) lists

                                         ;; stopping condition: u is empty
                                         ((not u)
                                          ;; returned value: (- (+ ....) ....)
                                          `(-(+,@p),@m))

                                        ;; alternatively push
                                        ;; variables in p and m, while
                                        ;; popping u

                                        (push(pop u)p)

                                        ;; first pop must succeed, but
                                        ;; not necessarly the second
                                        ;; one.  using a zero when u
                                        ;; is empty covers a lot of
                                        ;; corner cases.

                                        (push(if u (pop u) 0) m)))

                             ;; PRINT
                             `(princ,(if ? a`(code-char(mod,a 128)))))))
               r)
          ;; increase line count
          (incf m)
          ;; reset intermediate variables
          (setf ?()u()z()>()n t)))

       ;; loop until end of string
       (if c (go parse))


     build
       ;;; Now, we can add labels in generated code, for jumps

       ;; decrease line count M, which guards our second loop
       (decf m)

       ;; Take generated statement from R
       (setq d(pop r))

       ;; we pop from R and push in X, which means X will eventually
       ;; be in the correct sequence order. Here, we can safely
       ;; discard NIL statements.

       ;; We first push the expression, and THEN the label, so that
       ;; the label ends up being BEFORE the corresponding statement.
       (if d(push d x))

       ;; We can only jump into lines multiple of 9
       (when (=(mod m 9)0)
         ;; Push label
         (push(w #3=(/ m 9)'L)x)
         ;; Also, build a case statement for the jump table (e.g. 2(go L2))
         (push`(,#3#(go,(w #3#'L)))q))
       ;; loop
       (if(>= m 0)(go build)))

    ;; Finally, return the code
    `(let(@ ; target of a jump instruction

          ;; other variables: V3 represents 999 and has a default value of 111
          ,@(mapcar(lambda(n)`(,(w n'V),(/(1-(expt 10 n))9)))v))

       ;; build a tagbody, inject statements from X and case statements from Q
       ;; label ^ points to jump table : we go to ^ each time there is a JUMP
       ;; label > is the end of program

       ;; note that if the case does not match any authorized target
       ;; address, we simply end the programs.
       (tagbody,@x(go >)^(case @,@q)>))))

เราใช้อินพุต / เอาต์พุตมาตรฐานระหว่างการประเมินผลหมายความว่าเราใช้มาตรฐานreadและprincฟังก์ชั่น ดังนั้นรหัสผลลัพธ์สามารถทำให้สามารถเรียกใช้งานได้บนบรรทัดคำสั่งดังที่แสดงด้านล่าง

อินพุตไม่ถูกสุขลักษณะสมบูรณ์เมื่อเรียกใช้โปรแกรม99โปรแกรม: สันนิษฐานว่าผู้ใช้รู้ว่าคาดหวังค่าชนิดใด

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

จากการสังเกตการณ์ที่ชาญฉลาดจาก Macซึ่งเราไม่จำเป็นต้องหารและคูณด้วย 9 ในแต่ละครั้งเวอร์ชันปัจจุบันจะไม่หารหรือคูณด้วย 9 ระหว่างการดำเนินการ

ตัวอย่าง

หากเราแทนที่defmacroด้วยdefunเราจะเห็นรหัสที่สร้างขึ้น ตัวอย่างเช่น:

(g
"99999999                                              Print G.
999 99                                                Set triple-nine to ninety-nine.
9999999999 9999999999 9999999999 99 99 9 9 999 999    Set 10-nine to zero.
99999999999 9999999999                                Set 11-nine to zero.





999                                                   Print triple-nine's value divided by nine. (This is the ninth line.)
99999999                                              Print G.
999 999 9                                             Subtract nine from triple-nine.
 99999 999                                            Jump to line 5-nines if triple-nine is zero (endsprogram).
 9 99999999999 9999999999                             Jump to line nine if 10-nine and 11-nine are zero (alwa

")

นี่คือรหัสผลลัพธ์:

(LET (@
      (V5 11111)
      (V11 11111111111)
      (V1 1)
      (V10 1111111111)
      (V2 11)
      (V3 111)
      (V8 11111111))
  (TAGBODY
   L0
    (PRINC (CODE-CHAR (MOD V8 128)))
    (SETF V3 (- (+ V2) 0))
    (SETF V10 (- (+ V3 V1 V2 V10) V3 V1 V2 V10))
    (SETF V11 (- (+ V10) 0))
   L1
    (PRINC V3)
    (PRINC (CODE-CHAR (MOD V8 128)))
    (SETF V3 (- (+ V3) V1))
    (WHEN (EVERY 'ZEROP (LIST V3)) (SETF @ V5) (GO ^))
    (WHEN (EVERY 'ZEROP (LIST V11 V10)) (SETF @ V1) (GO ^))
    (GO >)
   ^
    (CASE @ (0 (GO L0)) (1 (GO L1)))
   >))

เมื่อดำเนินการพิมพ์ "G11G10G9G8G7G6G5G4G3G2G1G"

บรรทัดคำสั่ง

เราสามารถสร้างปฏิบัติการได้โดยการทิ้งแกนและระบุtoplevelฟังก์ชั่น กำหนดไฟล์ที่ชื่อboot.lispที่คุณใส่defmacroแล้วเขียนดังต่อไปนี้:

(defun main()(parse-99 <PROGRAM>))
(save-lisp-and-die "test-99" :executable t :toplevel #'main)

การรันsbcl --load boot.lispให้เอาต์พุตต่อไปนี้:

$ sbcl --load boot.lisp 
This is SBCL 1.2.8.32-18c2392, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
[undoing binding stack and other enclosing state... done]
[saving current Lisp image into test-99:
writing 5824 bytes from the read-only space at 0x20000000
writing 3120 bytes from the static space at 0x20100000
writing 55771136 bytes from the dynamic space at 0x1000000000
done]

จากนั้นรันโปรแกรมที่รวบรวม99 :

$ time ./test-99
G11G10G9G8G7G6G5G4G3G2G1G
real    0m0.009s
user    0m0.008s
sys     0m0.000s

99 ขวด

หากคุณสนใจนี่คือรหัสที่รวบรวมสำหรับโปรแกรม 99 ขวดที่เขียนด้วยคำตอบของ Mac : http://pastebin.com/ZXe839CZ (นี่เป็นเวอร์ชั่นเก่าที่เรามีjmpและติดendป้ายแลมบ์ดาและเลขคณิตที่สวยกว่า)

นี่คือการดำเนินการกับเวอร์ชันใหม่เพื่อพิสูจน์ว่ายังใช้งานได้: http://pastebin.com/raw.php?i=h73q58FN


6

TI-84 พื้นฐาน (สคริปต์เครื่องคิดเลข), 376 373 377 381 ไบต์

หากใช้กับเครื่องคิดเลข TI-84 คุณจะสามารถใช้ในการทดสอบมาตรฐาน ... ดังนั้นจึงมีประโยชน์;)

รุ่นระบบปฏิบัติการขั้นต่ำ - 2.53MP (MathPrint) เนื่องจาก sigma ผลรวม

#Get input from STDIN
:Ans+":"->Str0
#Initialize instruction pointer
:1->I
#Initialize variable set
:DelVar L1999->dim(L1
#Strip out those pesky non-newline/space/9 characters
:For(J,1,length(Ans
:sub(Str0,J,1
:If not(inString(": 9",Ans
:sub(Str0,1,J-1)+sub(Str0,J+1,length(Str0)-J->Str0
:End
#Main interpreting loop
:While I<length(Str0
:sub(Str0,I+1,inString(Str0,":",I+1)-I-1->Str1
:DelVar A" "=sub(Ans,1,1->A
:inString(Str0,":",I+1->I
:If A
:sub(Str1,2,length(Str1)-1->Str1
:End
:length(Str1->L
#0 is Output, 1 is Input, 2 is Assignment, 3 is Goto
:2A+inString(Str1," ->B
:If not(Ans
:Disp L1(L
:If Ans=1
:Then
:Input C
:C->L1(L
:End
#Get those delimited variables
:If B>1
:Then
:"{"+Str1->Str2
:While inString(Ans," 
:inString(Ans," 
:sub(Str2,1,Ans-1)+sub(Str2,Ans+1,length(Str2)-Ans->Str2
:End
:log(expr(Ans)+1->L2
:End
:If B=2
#Gotta expand that -+ pattern
:Ans(2->L1(Ans(1
;Love that summation Σ
:If B=3 and Σ(L2(K),K,2,dim(L2
:Then
:DelVar IFor(K,0,9L2(1
:inString(Str0,":",I+1->I
:End
:End

แนวทางปฏิบัติของ PS ASCII นั้นไม่สามารถทำได้อย่างแน่นอน แต่ใน TI-Basic :นั้นเป็นบรรทัดใหม่ ดังนั้นการขึ้นบรรทัดใหม่ทั้งหมดในรหัสหมายความว่าไม่จำเป็นต้องใช้:หรือ#ที่จุดเริ่มต้นของแต่ละบรรทัด โทเค็นเริ่มต้น:และ#แยกความแตกต่างระหว่างความคิดเห็นและรหัส

การถ่ายโอนข้อมูล Hex ต้นฉบับ (376 ไบต์)

49 3f bb 54 5d 20 39 39 39 04 b5 5d 20 3f 72 04 aa 09 3f d3 4a 2b 31 2b bb 2b 72 3f bb 0c aa 09 2b 4a 2b 31 3f ce b8 bb 0f 2a 3e 29 39 2a 2b 72 3f bb 0c aa 09 2b 31 2b 4a 71 31 11 70 bb 0c aa 09 2b 4a 70 31 2b 72 71 4a 04 aa 09 3f d4 3f d1 49 6b bb 2b aa 09 3f bb 0c aa 09 2b 49 70 31 2b bb 0f aa 09 2b 2a 3e 2a 2b 49 70 31 11 71 49 71 31 04 aa 20 3f bb 54 41 2a 29 2a 6a bb 0c 72 2b 31 2b 31 04 41 3f bb 0f aa 09 2b 2a 3e 2a 2b 49 70 31 04 49 3f ce 41 3f bb 0c aa 20 2b 32 2b bb 2b aa 20 11 71 31 04 aa 20 3f d4 3f bb 2b aa 20 04 4c 3f 32 41 70 bb 0f aa 20 2b 2a 29 04 42 3f ce b8 72 3f de 5d 20 10 4c 11 83 39 3f ce 72 6a 31 3f cf 3f dc 43 3f 39 43 04 5d 20 10 4c 3f d4 3f ce 42 6c 31 3f cf 3f 2a 08 2a 70 aa 20 04 aa 01 3f d1 bb 0f 72 2b 2a 29 3f bb 0f 72 2b 2a 29 3f bb 0c aa 01 2b 31 2b 72 71 31 11 70 bb 0c aa 01 2b 72 70 31 2b bb 2b aa 01 11 71 72 04 aa 01 3f d4 3f c0 bb 2a 72 11 70 31 04 5d 01 3f d4 3f ce 42 6a 32 3f 72 10 32 04 5d 20 10 72 10 31 3f ce 42 6a 33 40 ef 33 5d 01 10 4b 11 2b 4b 2b 32 2b b5 5d 01 3f cf 3f bb 54 49 d3 4b 2b 30 2b 5d 01 10 31 3f bb 0f aa 09 2b 2a 3e 2a 2b 49 70 31 04 49 3f d4 3f d4 2e 76

แก้ไข # 1 - เพิ่มประสิทธิภาพ 3 ไบต์โดยใช้การสังเกตของ Mac แก้ไข # 2 & # 3 - แก้ไขข้อบกพร่องที่ Runer112 แก้ไข


11
เป็นที่จะใช้ในสถานการณ์ที่เครียดเช่นการทดสอบมาตรฐานที่ง่ายคือว่าสิ่งที่ฉันได้รับการออกแบบ99สำหรับ
งานอดิเรกของ Calvin

1
ฉันขอแนะนำให้ใช้ตัวละครที่แตกต่างเช่น#สำหรับความคิดเห็นได้ไหม? (หมายเหตุ: ความคิดเห็นในรหัสจริงจะถูกนำมาใช้เป็นบรรทัดที่มีเพียงสตริงที่ไม่
เปิดเผย

8
คุณเคยลองใช้มันจริงเหรอ? ฉันยังไม่ได้ แต่จากการดูอีกเล็กน้อยฉันได้เห็นสิ่งที่ดูเหมือนจะเป็นข้อบกพร่องอย่างน้อยครึ่งโหล ตัวอย่างเช่น: ตัวแปรที่ไม่ได้เริ่มต้นด้วยค่าของพวกเขาAnsอินพุตจะถูกเขียนทับดังนั้นAns->Str0ในบรรทัดที่ 6 จะเกิดข้อผิดพลาดมีหลายอินสแตนซ์ที่อาร์กิวเมนต์ความยาวของsub()คำสั่งอาจเป็นศูนย์ซึ่งทำให้เกิดข้อผิดพลาดAnsในบรรทัดที่ 11 จะเป็นสตริง ดังนั้นAns-Jจะเกิดข้อผิดพลาด ... และฉันเพียงมองที่เกี่ยวกับช่วงครึ่งปีแรกของโปรแกรม
Runer112

1
@Timtech ที่ยังคงมีปัญหาอื่น ๆ แม้ว่า ดังที่ฉันได้กล่าวไปแล้วว่าการขาด I / O ของตัวละครขาดการเริ่มต้นตัวแปรและหลายอินสแตนซ์ที่sub()คำสั่งสามารถมีความยาวเป็นศูนย์และเกิดข้อผิดพลาด และเมื่อการsub()ร้องขอได้รับการแก้ไขฉันกลัวว่ามันอาจเปิดเผยปัญหาเพิ่มเติม
Runer112

1
@Timtech ฉันหมายถึงสิ่งนี้: "โดยค่าเริ่มต้นตัวแปรแต่ละตัวจะถูกกำหนดให้เป็นตัวแทนตัวเลขของตัวเองดังนั้นถ้ามันถูกกำหนดใหม่ค่าของตัวแปร9คือหมายเลข 9 และค่าของตัวแปร99คือหมายเลข 99 และอื่น ๆ " และสตริงของความยาว 0 สามารถผลิตได้โดยวิธีการเช่นแต่ก็จัดเรียงของข้อผิดพลาดที่พื้นไม่มีคำสั่งสตริงการจัดการสามารถใช้หรือผลิตสตริงที่ว่างเปล่ารวมทั้ง"" sub()
Runer112

5

C 426 458 481 497

แก้ไขฉันอาจจะไปไกล แต่ใช้งานได้กับ Visual C: ลบ stdio.h โดยใช้ int แทนไฟล์ * สำหรับ fopen และ getc

แก้ไข 2ขั้นตอนการดำเนินการจัดลำดับใหม่ถ่วงมากขึ้นบันทึก 32 ตัวอักษร

B[99999],*r,*i[9999],V[999],v,w,m,n;unsigned p,s;
main(b,a)char*a[];{r=i[0]=B;m=fopen(a[1],"r");
do if(w=getc(m),n+=w==57,w<33){
if(n){for(v=1,b=n;--b;)v=v*10+1;V[n]=v;*r++=p?-n:n;b=n=0;};
w-32?(*r=p=0,b=i[++s]=++r):(p=b,b=0);}while(w>=0);
while(p<s)if(w=0,r=i[p++],v=*r++)
if(m=v>0,*r){for(;b=*r++;m=-m)w=w+m*V[b]|!m*V[b];m?V[v]=w:(p=w?p:9*V[-v]);
}else~v&1?!m?V[-v]=getchar():putchar(V[v]&127):m?printf("%d",V[v]):scanf("%d",V-v);
}

โปรแกรมคอนโซลแบบสแตนด์อะโลนชื่อโปรแกรมที่ใช้ในบรรทัดคำสั่งและอินพุต / เอาต์พุตผ่านคอนโซล

K&R แบบเก่าชนิดเริ่มต้น int สำหรับ vars และพารามิเตอร์ส่วนกลาง สมมติว่า EOF ถูกกำหนดเป็น -1 (เหมือนในทุกการใช้งาน C ที่ฉันทราบ)

คอมไพล์ด้วยคำเตือนกับโครงการ Visual Studio 2010 (คอนโซล Win32 C ++, คอมไพล์เป็น C) คอมไพล์บน Ideone แต่ไม่สามารถทำงานได้ตามที่ต้องการไฟล์

ขั้นตอนแรกซอร์สโค้ดจะอ่านและแยกแต่ละบรรทัดจะถูกเก็บไว้เป็นลำดับของจำนวนเต็มตามจำนวน 9s หากมีช่องว่างนำหน้าหมายเลขแรกจะเป็นลบ ดังนั้น:9 BLAH 99 9a9bb9c9 ( 9 99 9999) กลายเป็น-1,2,4 มีทางลัด - ไม่ถูกกฎหมายดังนั้น: รหัส ASCII ทั้งหมดที่น้อยกว่า '' จะถูกพิจารณาว่าเป็นบรรทัดใหม่

ในขั้นตอนนี้ตัวแปรที่ใช้ทั้งหมดจะถูกกำหนดค่าเริ่มต้น

ขั้นตอนการดำเนินการเป็นไปตามข้อกำหนดไม่มีการบันทึกบันทึกหมายเลขที่จัดเก็บหารด้วย 9

สามารถอ่านรหัสเดียวกันได้มากขึ้น (ฉันหวังว่า) การเว้นวรรคและการขึ้นบรรทัดใหม่

B[99999],*r,*i[9999],V[999],v,w,m,n;
unsigned p,s;
main(b,a)char*a[];
{
  r=i[0]=B;
  m=fopen(a[1],"r");
  do if(w=getc(m),n+=w==57,w<33)
  {
     if(n){for(v=1,b=n;--b;)v=v*10+1;V[n]=v;*r++=p?-n:n;b=n=0;};
     w-32?(*r=p=0,b=i[++s]=++r):(p=b,b=0);
  }
  while (w>=0);
  while (p<s)
    if (w = 0, r = i[p++], v = *r++)
        if (m = v > 0, *r){
            for(; b = *r++; m = -m)
                w = w + m*V[b] | !m*V[b];
            m ? V[v]=w : (p = w ? p : 9*V[-v]);
        } else
            ~v & 1 
            ? !m ? V[-v] = getchar() : putchar(V[v] & 127)  
            : m ? printf("%d", V[v]) : scanf("%d", V - v);
}

1
ทำงานร่วมกับ GCC 4.8.2 ได้เช่นกัน รวบรวมเป็น C99!
EMBLEM

4

Haskell, 550 ไบต์

import Data.List.Split
import System.Environment
a#b=takeWhile(/=a)b
(!)=map
main=do(f:_)<-getArgs;readFile f>>=e.(p!).lines
p l=(if ' '#l<'9'#l then[0]else[])++length!(wordsBy(/='9')l)
e l=(\x->div(10^x-1)9)%l where
 _%[]=return()
 v%([]:r)=v%r
 v%([n]:r)=putStr(if odd n then show(v n)else[toEnum$v n`mod`128])>>v%r
 v%([0,n]:r)=do i<-getLine;u n(if odd n then read i else fromEnum$head i)v%r
 v%((0:n:m):r)|any(/=0)(v!m)=v%r|v n<0=v%[]|1<2=v%drop(9*v n)l
 v%((n:m):r)=u n(sum$zipWith(*)(v!m)(cycle[1,-1]))v%r
u n i v= \x->if x==n then i else v x

ตัวอย่างการรันด้วยโปรแกรม "countdown" ที่เก็บไว้ในไฟล์ i.99

$ ./99 i.99
G11G10G9G8G7G6G5G4G3G2G1G

เวอร์ชันที่ไม่ถูกปรับแต่ง:

import Data.List.Split
import System.Environment

-- The main function takes the first command line argument as a file name,
-- reads the content, splits it into lines, parses each line and evaluates
-- the list of parsed lines.
main = do
 (f:_)<-getArgs
 readFile f >>= eval.map parse.lines

-- each line is coverted into a list of integers, which represent the number
-- of 9s (e.g. "999 99 9999" -> [3,2,4]). If there's a space before the first
-- 9, a 0 is put in front of the list (e.g. " 9 9 999" -> [0,1,1,3]).
parse l = (if takeWhile (/=' ') l < takeWhile (/='9') l then [0] else [])
   ++ map length (wordsBy(/='9') l)

-- The work is done by the helper function 'go', which takes two arguments
--   a) a functions which takes an integer i and returns the value of the
--      variable with i 9s (e.g: input: 4, output: value of 9999). To be
--      exact, the value divided by 9 is returned.
--   b) a list of lines to work on
-- 'eval' starts the process with a function that returns i 1s for every i and
-- the list of the parsed input. 'go' checks which statement has to be
-- executed for the next line and calls itself recursively
eval list = go (\x -> div (10^x-1) 9) list
   where
   go _ []                  = return ()
   go v ([]:r)              = go v r
   go v ([n]:r)             = putStr (if odd n then show(v n) else [toEnum (v n`mod`128)]) >> go v r
   go v ([0,n]:r)           = do i<-getLine ; go (update n (if odd n then read i else fromEnum$head i) v) r
   go v ((0:n:m):r)
      | any (/=0) (map v m) = go v r
      | v n < 0             = go v []
      | otherwise           = go v (drop (9*v n) list)
   go v ((n:m):r)           = go (update n (sum $ zipWith (*) (map v m) (cycle[1,-1])) v) r

-- updates a function for retrieving variable values.
-- n = position to update
-- i = new value
-- v = the function to update
update n i v = \x->if x==n then i else v x

4

JavaScript (ES6) 340 352

ฟังก์ชั่นที่มี 2 พารามิเตอร์

  • รหัสโปรแกรมเป็นสตริงหลายบรรทัด
  • อินพุตเป็นอาร์เรย์

พารามิเตอร์ทางเลือกที่สาม (ค่าเริ่มต้น 10k) คือจำนวนการทำซ้ำสูงสุด - ฉันไม่ชอบโปรแกรมที่ทำงานตลอดไป

JSFiddleเพื่อทดสอบ

I=(c,i,k=1e5,
  V=v=>v in V?V[v]:v/9 // variable getter with default initial value
)=>(c=>{
 for(p=o='';--k&&p<c[L='length'];)
   (v=(r=c[p++].split(' '))[S='shift']())? // no leading space
      r[r.map(t=>w-=(m=-m)*V(t),w=0,m=1),0]?V[v]=w // Assign
      :o+=v[L]&1?V(v):String.fromCharCode(V(v)&127) // Output
   : // else, leading space
    (v=r[S]())&&
       (r[0]?r.some(t=>V(t))?0:p=9*V(v) // Goto
       :(t=i[S](),V[v]=v[L]&1?t:t.charCodeAt()) // Input
    )
})(c.replace(/ (?=[^9])|[^9\s]/g,'').split('\n'))  // code cleaning
||o

4

q / k, 490 469

M:mod;T:trim;R:read0;S:set;s:" "
f:(rtrim')(f:R -1!`$.z.x 0)inter\:"9 \n"
k)m:{@[x;&M[!#x;2];-:]}
b:{}
k)p:{1@$$[1=M[#x;2];(K x)%9;"c"$M[(K x)%9;128]];}
k)i:{S[(`$T x);$[1=M[#T x;2];9*"J"$R 0;*9*"i"$R 0]]}
k)K:{$[#!:a:`$x;.:a;"I"$x]}
k)v:{(S).(`$*:;+/m@K'1_)@\:T's\:x}
k)g:{$[&/0=C:K'c:1_J:s\:T x;n::-1+K@*J;|/~0=C;;(d<0)|(d:*C)<#f;exit 0]}
k)r:{`b`p`i`v`g@*&(&/x=s;q&1=c;(e~s)&1=C;(q:e~"9")&1<c:#s\:x;((e:*x)~s)&1<C:#s\:1_x)}
k)n:0;while[~n>#o:(r')f;(o n)f n;n+:1]
\\

.

$ q 99.q countdown.txt -q
G11G10G9G8G7G6G5G4G3G2G1G

สคริปต์เป็นส่วนผสมของ q และ k ดังนั้นก่อนอื่นฉันจะกำหนดคำหลัก q สองสามข้อที่ฉันต้องการใช้หลาย ๆ ครั้งในฟังก์ชัน k (โดยทั่วไปคือแมโคร #define)

M:mod;T:trim;R:read0;S:set

f อ่านไฟล์ที่ส่งเข้าสู่โปรแกรมและลบอักขระที่ไม่จำเป็นออก

q)f
"99999999"
"999 99"
"9999999999 9999999999 9999999999 99 99 9 9 999 999"
"99999999999 9999999999"
""
""
""
""
""
"999"
"99999999"
"999 999 9"
" 99999 999"
" 9 99999999999 9999999999"

m ใช้ list / vector และเพิ่มดัชนีคี่ด้วย -1

q)m 1 2 3 4 5
1 -2 3 -4 5

b เป็นเพียงฟังก์ชั่นที่ว่างเปล่าใช้สำหรับบรรทัดที่ไม่มี op

p เป็นฟังก์ชั่นการพิมพ์

Kเป็นฟังก์ชันที่ตรวจสอบตัวแปร ถ้าตัวแปรนั้นมีอยู่มันจะส่งคืนมันมิฉะนั้นก็แค่คืนค่าตัวอักษร

//999 not defined, so just return 999
q)K "999"
999
//Set 999 to 9
q)v "999 9"
//K now returns 9
q)K "999"
9

v เป็นฟังก์ชั่นที่ได้รับมอบหมาย

g เป็นฟังก์ชั่น goto

r รับสายและตัดสินใจว่าจะต้องใช้การดำเนินการใด

และในที่สุดฉันก็แค่วนซ้ำfรายการของสตริงด้วยnตัววนซ้ำ ฟังก์ชัน goto จะอัปเดตnตามความจำเป็น


3

Perl, 273 266 255 244 238

เพิ่มตัวแบ่งบรรทัดเพื่อความชัดเจน

open A,pop;
for(@c=<A>){
y/ 9//cd;s/ +/ /g;s/ $//;
$p="((99)+|9+)";$a='+';
s/^ $p$/$1='$2'?ord<>:<>/;
s/^$p$/print'$2'?chr$1%128:$1/;
s/^ $p /\$_=$1*011unless/&&y/ /|/;
s/ /=/;s/ /$a=-$a/ge;
s!9+!${x.$&}=$&/9;"\$x$&"!eg}
eval$c[$_++]until/-/|$_>@c

ชื่อโปรแกรมที่ใช้ในบรรทัดคำสั่ง:

$ perl 99.pl 99beers.99

แต่ละบรรทัดของโปรแกรมจะถูกแปลงเป็นโค้ด Perl ตัวอย่างเช่น:

print'$x99'?chr$x99999999%128:$x99999999
$x999=$x99
$x9999999999=$x9999999999-$x9999999999+$x99-$x99+$x9-$x9+$x999-$x999
$x99999999999=$x9999999999





print''?chr$x999%128:$x999
print'$x99'?chr$x99999999%128:$x99999999
$x999=$x999-$x9
$_=$x99999*011unless$x999
$_=$x9*011unless$x99999999999|$x9999999999

รายละเอียดเพิ่มเติม

open A,pop; # open the source file
for(@c=<A>){ # read all lines into @c and iterate over them
y/ 9//cd; # remove all but spaces and 9's
s/ +/ /g;s/ $//; # remove duplicate and trailing spaces
$p="((99)+|9+)";$a='+';
s/^ $p$/$1='$2'?ord<>:<>/; # convert input
s/^$p$/print'$2'?chr$1%128:$1/; # convert output
s/^ $p /\$_=$1*011unless/&&y/ /|/; # convert goto
s/ /=/;s/ /$a=-$a/ge; # convert assignment
s!9+!${x.$&}=$&/9;"\$x$&"!eg} # initialize and convert variables
eval$c[$_++]until/-/|$_>@c # run (program counter is in $_)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.