ตีความ Kipple!


12

บทนำ

Kippleเป็นภาษาการเขียนโปรแกรมแบบกองซ้อนซึ่งเป็นความลับที่คิดค้นโดย Rune Berg ในเดือนมีนาคม 2003

Kipple มี 27 กอง 4 ตัวดำเนินการและโครงสร้างการควบคุม

สแต็ค

สแต็กถูกตั้งชื่อa- zและมีจำนวนเต็ม 32 บิต นอกจากนี้ยังมีสแต็กพิเศษ@เพื่อให้หมายเลขเอาต์พุตสะดวกยิ่งขึ้น เมื่อตัวเลขถูกส่งเข้าสู่@ค่า ASCII ของตัวเลขนั้นจะถูกผลักเข้าไปแทน (ตัวอย่างเช่นหากคุณกด 12 ถึง@จะได้ 49 และ 50 @แทน)

อินพุตถูกส่งไปยังอินพุตสแต็กiก่อนที่โปรแกรมจะถูกดำเนินการ ล่ามจะถามหาค่าที่จะจัดเก็บiก่อนดำเนินการ หลังจากการดำเนินการเสร็จสิ้นสิ่งใดในเอาท์พุทสแต็คoจะถูกตอกไปยังเอาท์พุทเป็นตัวอักษร ASCII เนื่องจากนี่เป็นเพียงกลไก IO ของ Kipple เท่านั้นการโต้ตอบกับโปรแกรม Kipple จึงเป็นไปไม่ได้

ผู้ประกอบการ

ตัวถูกดำเนินการเป็นทั้งตัวระบุสแต็กหรือจำนวนเต็ม 32 บิตลงนาม

กด: >หรือ<

ไวยากรณ์: Operand>StackIndentifierหรือStackIndentifier<Operand

ตัวดำเนินการพุชนำตัวถูกดำเนินการไปทางซ้ายแล้วผลักไปยังสแต็กที่ระบุ ตัวอย่างเช่น12>aจะส่งค่า 12 ลงบนสแต็aa>bจะป๊อปอัพค่าสูงสุดจากสแต็กaและกดลงบนสแต็bก การ popping สแต็กที่ว่างเปล่าส่งคืนค่า 0 a<bจะเท่ากับb>aเสมอ a<b>cปรากฏคุ้มค่าสูงสุดจากbและผลักดันทั้งสองและca

เพิ่ม: +

ไวยากรณ์: StackIndentifier+Operand

ตัวดำเนินการ Add จะเพิ่มผลรวมของรายการสูงสุดบนสแต็กและตัวถูกดำเนินการไปยังสแต็ก หากตัวถูกดำเนินการเป็นสแต็กค่าจะถูกดึงจากมัน ตัวอย่างเช่นหากค่าสูงสุดของสแต็กaคือ 1 ดังนั้นa+2จะผลัก 3 ลงไป ถ้าaว่างแล้วa+2จะกด 2 ลงไป หากค่าสูงสุดของสแต็กaและbเป็น 1 และ 2 แล้วa+bจะป๊อปค่า 2 จากสแต็กbและกด 3 ลงบนสแต็a

ลบ: -

ไวยากรณ์: StackIndentifier-Operand

ตัวดำเนินการลบทำงานเหมือนกับตัวดำเนินการเพิ่มยกเว้นว่าจะลบแทนการเพิ่ม

ชัดเจน: ?

ไวยากรณ์: StackIndentifier?

ตัวดำเนินการ Clear จะล้างสแต็กหากรายการสูงสุดเป็น 0

a+2 this will be ignored c<iล่ามจะไม่สนใจอะไรที่ไม่ติดกับการดำเนินการเพื่อให้โปรแกรมดังต่อไปนี้จะทำงาน: อย่างไรก็ตามวิธีที่เหมาะสมในการเพิ่มความคิดเห็นคือการใช้#ตัวละคร สิ่งใดระหว่าง a #และอักขระสิ้นสุดบรรทัดจะถูกลบออกก่อนดำเนินการ อักขระ ASCII # 10 ถูกกำหนดเป็น end-of-line ใน Kipple

ถูกดำเนินการอาจจะใช้ร่วมกันโดยสองผู้ประกอบการเช่นอาจจะเขียนเป็นa>b c>b c?a>b<c?

โปรแกรมที่1>a<2 a+aจะส่งผลให้aมีค่า[1 4](จากล่างขึ้นบน) [1 3]และไม่ได้ ในทำนองเดียวกันสำหรับ-ผู้ประกอบการ

โครงสร้างการควบคุม

Kipple มีโครงสร้างการควบคุมเดียวเท่านั้น: การวนซ้ำ

ไวยากรณ์: (StackIndentifier code )

ตราบใดที่สแต็กที่ระบุไม่ว่างเปล่าโค้ดภายในวงเล็บที่ตรงกันจะถูกทำซ้ำ ลูปอาจมีลูปอื่น ยกตัวอย่างเช่น(a a>b)จะย้ายค่าทั้งหมดของสแต็คaบนสแต็คbแม้ว่าจะสั่งซื้อจะถูกกลับรายการ วิธีหน้าที่เหมือน (a>b)แต่สง่างามมากขึ้นที่จะทำคือ

ตัวอย่าง

100>@ (@>o)

สิ่งนี้จะออก 100

33>o 100>o 108>o 114>o 111>o 87>o 32>o 111>o 108>o 108>o 101>o 72>o

"Hello World!"นี้จะพิมพ์ เมื่อoสแต็กกำลังถูกเอาต์พุตมันจะเริ่มป๊อปอักขระจากด้านบนของสแต็กไปด้านล่าง

#prime.k by Jannis Harder
u<200
#change 200


k<2>m
u-2
(u-1 u>t u>z u<t
  (k>e e+0 e>r)
  (e>k)
  m+1
  m>t
  m>z
  m<t
  t<0>z? t?
  1>g
  (r>b
    m+0 m>a
    b+0 b>w
    (a-1 
      b+0 b>j
      j?
      1>s
      (j<0>s j?)
      s?
      (s<0 w+0 w>b s?)
      a>t
      a>z
      t>a
      b-1
      b>t
      b>z
      t>b
      z<0>t? z?
    a?)
    b?
    1>p
    (b<0 b? 0>p)
    p?
    (p 0>r? 0>p? 0>g)
  )
  g?
  (g m+0 m>k 0>g?)
u?)
(k>@
  10>o
  (@>o)
)

นี่คือตัวสร้างจำนวนเฉพาะ แต่ฉันไม่แน่ใจว่ามันทำงานอย่างไร

กฎระเบียบ

  • คุณต้องเขียนโปรแกรม / ฟังก์ชั่นที่ตีความ Kipple โปรแกรม / ฟังก์ชั่นนี้อาจได้รับโปรแกรม Kipple ผ่านไฟล์ต้นฉบับหรือรับมันผ่าน STDIN โดยตรงจากผู้ใช้ หาก STDIN ไม่พร้อมใช้งานจะต้องได้รับจากอินพุตคีย์บอร์ดและดำเนินการรับอินพุตต่อไปจนกว่าจะป้อนอักขระที่ไม่สามารถพิมพ์ได้ ตัวอย่างเช่นหากล่ามของคุณเขียนด้วยรหัสเครื่อง x86 มันจะได้รับตัวอักษรโปรแกรม Kipple ตามตัวอักษรจากแป้นพิมพ์และทำต่อไปจนกว่าจะกดesc(หรือปุ่มอื่นใดที่ไม่ได้พิมพ์อักขระที่พิมพ์ได้)

  • หากมีข้อผิดพลาดเช่นไวยากรณ์ผิดพลาดหรือแตกล้นก็จะต้องยอมรับมันในบางวิธีเช่นโดยการกลับมา 10 แทน 0 หรือข้อความที่ผลิตโดยล่าม / เรียบเรียงข้อผิดพลาดแต่ไม่พิมพ์ข้อความผิดพลาด

  • กฎทั่วไปอื่น ๆ สำหรับการตีกอล์ฟจะมีผลกับความท้าทายนี้

  • รหัสของคุณจะถูกทดสอบพร้อมกับตัวอย่างบางส่วนในคลังเก็บตัวอย่างของ Kipple

นี่คือรหัสกอล์ฟโค้ดที่สั้นที่สุดเป็นไบต์จะเป็นผู้ชนะ โชคดี!


โปรดทราบว่ามีโอเปอเรเตอร์เสริมใน Kipple "แต่มันไม่ได้เป็นส่วนหนึ่งของข้อมูลจำเพาะและเป็นเพียงคุณสมบัติพิเศษในล่ามอย่างเป็นทางการ ฉันไม่ได้พูดถึงที่นี่ดังนั้นจึงไม่จำเป็นต้องได้รับการสนับสนุนในการส่งของคุณ

หากคุณมีข้อสงสัยเกี่ยวกับส่วนหนึ่งของข้อกำหนดใด ๆ ที่คุณสามารถตรวจสอบกับล่ามอย่างเป็นทางการเขียนใน Java นี่จะดาวน์โหลดไฟล์ zip ที่มีโปรแกรมที่คอมไพล์และซอร์สโค้ด มันได้รับอนุญาตภายใต้ GPL


1
เราต้องใช้จำนวนเต็มแบบ 32 บิตหรือเราสามารถใช้ชนิดจำนวนเต็มแบบธรรมชาติของโฮสต์ได้หรือไม่ (กรณีที่สำคัญที่สุดอาจเป็นจำนวนเต็ม 32 บิตแบบไม่มีลายเซ็น, เลขจำนวนเต็ม 8 บิตที่ลงชื่อหรือไม่ได้ลงนามและจำนวนเต็มความแม่นยำโดยพลการ)
Martin Ender

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

คุณสามารถเฉพาะเจาะจงมากขึ้นเกี่ยวกับพฤติกรรมในกรณีที่มีข้อผิดพลาดหรือไม่? ดังนั้นเราสามารถส่งคืนคำตอบที่ไม่ถูกต้องหรือปล่อยข้อผิดพลาด แต่เราไม่สามารถพิมพ์ข้อผิดพลาดได้?
Alex A.

@Alex A. ใช่เพราะมันถือได้ว่าเป็นเอาต์พุตของโปรแกรมและคุณสามารถสร้างโปรแกรม kipple ซึ่งสามารถมีเอาต์พุตเหมือนกับข้อความแสดงข้อผิดพลาดได้ นอกจากนี้ยังเป็น "ถูกกว่า" (ใช้อักขระน้อยกว่า) เพื่อไม่ให้มีฟังก์ชั่น / ข้อความสั่งที่พิมพ์ข้อความแสดงข้อผิดพลาด

3
ช่องว่างใดที่สามารถเกิดขึ้นได้ในซอร์สโปรแกรม ฉันจะขออินพุตได้iอย่างไรถ้าฉันใช้ซอร์สโปรแกรมจาก stdin
orlp

คำตอบ:


6

C, 709 702 ไบต์

คะแนนไบต์นั้นขึ้นอยู่กับการขึ้นบรรทัดใหม่ (ที่สามารถลบออกได้) แต่เพื่อความสะดวกในการอ่านฉันโพสต์ไว้ที่นี่ด้วยการขึ้นบรรทัดใหม่:

#define R return
#define C ;break;case
c[999]={};*P=c;*S[28];M[99999]={};t;*T;
u(s,v){S[s]+=28;*S[s]=v;
if(s>26){for(t=v/10;t;t/=10)S[s]+=28;T=S[s];do{*T=48+v%10;T-=28;}while(v/=10);}}
o(s){t=S[s]-M>27;S[s]-=28*t;R S[s][28]*t;}
I(s){R s<65?27:s-97;}
O(int*p){if(!isdigit(*p))R o(I(*p));
for(;isdigit(p[-1]);--p);for(t=0;isdigit(*p);t*=10,t+=*p++-48);R t;}

main(i,a){for(i=0;i<28;++i)S[i]=M+i;
for(;~(*++P=getchar()););P=c+1;
for(;;){i=I(P[-1]);switch(*P++){
case 35:for(;*P++!=10;)
C'<':u(i,O(P))
C'>':u(I(*P),O(P-2))
C'+':u(i,*S[i]+O(P))
C'-':u(i,*S[i]-O(P))
C'?':if(!*S[i])S[i]=M+i
C'(':for(i=1,T=P;i;++T)i+=(*T==40)-(*T==41);if(S[I(*P)]-M<28)P=T;else u(26,P-c)
C')':P=c+o(26)-1
C-1:for(;i=o(14);)putchar(i); R 0;}}}

รวบรวมด้วยgcc -w golf.c(ปิดเสียง-wเตือนเพื่อความมีสติ)

รองรับทุกอย่างยกเว้นiอินพุตเนื่องจากผู้ถามยังไม่ได้ตอบคำถามของฉันหากคุณใช้รหัสจาก stdin มันไม่ได้รายงานข้อผิดพลาดทางไวยากรณ์


ฉันได้ตอบคำถามของคุณเกี่ยวกับสแต็ค "i" ในความคิดเห็นของโพสต์หลัก

btw อ่านโปรแกรม kipple ได้อย่างไร? ผ่านคำสั่งอาร์กิวเมนต์? ฉันควรใช้มันอย่างไร?

@GLASSIC มันคาดว่าโปรแกรมบน stdin
orlp

จนกระทั่งเมื่อไหร่ จะเริ่มต้นการขับถ่ายอย่างไรได้อย่างไร

@GLASSIC เพียงผ่านโปรแกรมบน stdin ./a.out < prime.kเช่น
orlp

3

Ruby, 718 ไบต์ (ปัจจุบันไม่ใช่การแข่งขัน)

ฉันเหนื่อยมาก

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

เนื่องจากความสับสนบางประการเกี่ยวกับข้อมูลจำเพาะรุ่นปัจจุบันจึงไม่สามารถจัดการa<b>cได้อย่างถูกต้องดังนั้นจึงไม่สามารถแก้ไขได้จนกว่าจะได้รับการแก้ไข

a<b>cได้รับการแก้ไขแล้ว อย่างไรก็ตามมันยังคงส่งคืนผลลัพธ์ที่ไม่ถูกต้องเมื่อเรียกใช้ฟังก์ชัน primes ดังนั้นจึงยังคงเป็นคำตอบที่ไม่เข้ากัน

(f=$<.read.gsub(/#.*?\n|\s[^+-<>#()?]*\s/m,' ').tr ?@,?`
t=Array.new(27){[]}
t[9]=STDIN.read.bytes
k=s=2**32-1
r=->c{c=c[0];c[0]==?(?(s[c[1..-2]]while[]!=t[c[1].ord-96]):(c=c.sub(/^(.)<(\D)>(.)/){$1+"<#{t[$2.ord-96].pop||0}>"+$3}.sub(/(\d+|.)(\W)(\d+|.)?/){_,x,y,z=*$~
a=x.ord-96
b=(z||?|).ord-96
q=->i,j=z{j[/\d/]?j.to_i: (t[i]||[]).pop||0}
l=t[a]
y<?-?(x==z ?l[-1]*=2:l<<(l.pop||0)+q[b]
l[-1]-=k while l[-1]>k/2):y<?.?(x==z ?l[-1]=0:l<<(l.pop||0)-q[b]
l[-1]+=k while l[-1]<-k/2-1):y<?>?t[a]+=a<1?q[b].to_s.bytes: [q[b]]:y<???
(t[b]+=b<1?q[a,x].to_s.bytes: [q[a,x]]): l[-1]==0?t[a]=[]:0
z||x}while c !~/^(\d+|.)$/)}
s=->c{(z=c.scan(/(\((\g<1>|\s)+\)|[^()\s]+)/m)).map &r}
s[f]
$><<t[15].reverse.map(&:chr)*'')rescue 0

+1 อยู่ดี คุณลองใช้โปรแกรม fibonacci หรือไม่?
edc65

โปรแกรมลำดับ @ edc65 Fibbonacci พิมพ์ผิดเช่นกัน: 0 1 1 2 4 8 16...ฉันสงสัยว่ามันเป็นข้อผิดพลาดสเป็ค
Value Ink

ไม่โปรแกรมฟีโบนักชีa+0เป็นเรื่องไร้สาระตัวอย่างเช่นบรรทัดไม่มีสาระ
edc65

ฉันเดาว่าปัญหาเกี่ยวกับตัวเลขสำคัญคือมันไม่ได้จัดการโครงสร้างการควบคุมที่ซ้อนกัน แต่ฉันไม่รู้มากเกี่ยวกับทับทิมฉันสงสัยว่าการเดาของฉันถูกต้อง

โปรแกรมนี้ควรจัดการชุดของ parens ที่ซ้อนกันอย่างถูกต้องเนื่องจากการจับคู่ regex แบบซ้ำ/(\((\g<1>|\s)+\)|[^()\s]+)/mที่ใช้เพื่อแยกโทเค็นและกลุ่มของโทเค็น ( ทดสอบบน regex101 ) อาจเป็นข้อผิดพลาดในการวิเคราะห์คำที่เหลือ แต่ฉันไม่รู้ว่าอยู่ที่ไหน
Value Ink
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.