解释基普尔!


12

介绍

Kipple是Rune Berg于2003年3月发明的基于堆栈的深奥编程语言。

Kipple有27个堆栈,4个运算符和一个控制结构。

堆栈

堆栈被命名为a- z并包含32位带符号整数。还有一个特殊的堆栈,@使输出数字更加方便。当将数字压入时@,实际上将压入该数字的ASCII值。(例如,如果您将12推到@,它将推49,然后推50。@

i在执行程序之前,将输入压入输入堆栈。解释器将i在执行之前要求存储值。执行完成后,输出堆栈上的所有内容o都会弹出以ASCII字符形式输出。由于这是Kipple唯一的IO机制,因此无法与Kipple程序进行交互。

经营者

操作数可以是堆栈标识符或带符号的32位整数。

推送:><

语法:Operand>StackIndentifierStackIndentifier<Operand

Push运算符将操作数向左移并将其推入指定的堆栈。例如,12>a将值12推入stack aa>b将从堆栈中弹出最高值a并将其推入堆栈b。弹出空堆栈总是返回0 a<b相当于b>aa<b>c从弹出最高值,b并同时推入ca

加: +

句法: StackIndentifier+Operand

Add运算符将堆栈上最顶层项目和操作数之和压入堆栈。如果操作数是堆栈,则从中弹出值。例如,如果堆栈的最高值为a1,a+2则将3压入堆栈。如果a为空,a+2则将2推入。如果堆叠的最值ab是1和2,然后a+b将从栈中弹出的值2 b和3推入堆栈a

减去: -

句法: StackIndentifier-Operand

减法运算符的工作方式与加法运算符完全相同,只是它减去而不是加法。

明确: ?

句法: StackIndentifier?

如果最上面的项目为0,则Clear运算符将清空堆栈。

解释器将忽略操作符旁边不存在的所有内容,因此以下程序将起作用:a+2 this will be ignored c<i。但是,添加注释的正确方法是使用#字符。#执行前,a 和行尾字符之间的所有内容都将被删除。ASCII字符#10在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)将顺序的所有值都移到stack ab,尽管顺序相反。在功能上相同但更优雅的方法是(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

好吧,这就是我在esotric Wiki上发现的。是的,因为你的解释可能是与他们的机制都是基于此功能的其他kipple程序兼容

您能否更详细地说明发生错误时的行为?这样我们可以返回错误的答案或发出错误,但是我们无法打印错误?
Alex A.

@Alex A.是的,因为可以将其视为程序的输出,并且可以制作一个kipple程序,该程序可以具有与错误消息相同的输出。没有打印错误消息的功能/语句也是“便宜”(使用较少的字符)。

3
在源程序中可以出现什么空格?i如果我从stdin中获取源程序,如何请求输入?
orlp

Answers:


6

C,709702字节

字节分数是用换行符(可以删除)删除的,但是为了便于阅读,我在这里用换行符发布:

#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”堆栈的问题。

顺便说一句,它如何读取kipple程序?通过命令参数?我应该如何使用它?

@GLASSIC期望程序在stdin上。
orlp 2016年

到什么时候 ?如何开始执行?

@GLASSIC只需在stdin上传递程序即可。例如./a.out < prime.k
orlp 2016年

3

Ruby,718个字节(当前处于非竞争状态)

我很累

文件作为命令行参数加载,输入通过STDIN发送。或者,如果不需要在i寄存器中输入,则将文件通过管道传输到STDIN 。

由于对规范有些困惑,因此当前版本无法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。您尝试了斐波那契程序吗?
edc65 '16

@ edc65 Fibbonacci序列程序也会打印错误的东西:0 1 1 2 4 8 16...我想知道这是否是规范错误
Value Ink

不,斐波那契程序是胡扯,例如该行a+0是胡说八道
edc65 '16

我猜素数的问题是它不能处理嵌套的控制结构,但是我对ruby不太了解,我怀疑我的猜测是正确的。

该程序应正确处理嵌套的套票,因为/(\((\g<1>|\s)+\)|[^()\s]+)/m它用于递归的正则表达式匹配,它用于拆分令牌和令牌组。(在regex101上测试)。在其余的解析过程中可能是一个错误,但我不知道在哪里。
价值墨水
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.