写一个〜ATH口译员


12

流行的网络漫画《Homestuck》利用一种称为~ATH破坏宇宙的编程语言。尽管此代码挑战不是要编写一个能够消灭我们的存在的程序,但我们将破坏一些驯服(尽管不太有趣)的实体:变量。 

~ATH(读作“直到死亡”,注意~ath“ tilde ath”的工作方式)是通过创建一个名为的变量THIS,使用来执行命令EXECUTE,并使用来完成程序的THIS.DIE()。在Homestuck中使用该语言的Wiki页面可在此处找到。这项挑战的目标是创建一个~ATH口译员。

为了应对挑战,我将创建一些~ATH实际上并不存在的细节,但要使其(某种程度上)有用。

  • 该语言仅适用于以声明的整数import <variable name>;。该变量将自动设置为0值。一次只能导入一个变量。
  • x可以通过写入来复制变量bifurcate x[y,z];,这将删除该变量x并将其替换为相同的变量yz。请注意,它无法创建与已删除变量同名的变量。本质上,将重命名变量,然后创建具有不同名称的变量副本。这似乎是一个愚蠢的功能,但愚蠢是非常深刻根深蒂固的Homestuck。
  • 语法编写上执行代码的程序x~ATH(x){EXECUTE(<code>)}。如果要同时在两个变量上执行代码,则代码将嵌套,如下所示:~ATH(x){~ATH(y){EXECUTE(<code>)}}。中的所有命令都<code>将在x和上执行y
  • 现在让我们进入命令。+将相关变量加1并-减1。然后就可以了。
  • 的最后一个特点~ATH是,它杀死了所有与之兼容的东西。变量<name>=<value>以命令格式(后跟换行符)打印[<name>].DIE();。然后,程序打印单词DIE <name>和换行符的次数等于变量值的绝对值。当同时杀死变量时[<name1>,<name2>].DIE();(只要存在,就可以杀死任意多个变量),DIE()命令将按顺序对变量执行。

范例程序

程序1:

import sollux;                  //calls variable "sollux"
import eridan;                  //calls variable "eridan"
~ATH(sollux){EXECUTE(--)}       //sets the value of "sollux" to -2
~ATH(eridan){EXECUTE(+++++)}    //sets the value of "eridan" to 5
[sollux].DIE();                 //kills "sollux", prints "DIE sollux" twice
~ATH(eridan){EXECUTE(+)}        //sets the value of "eridan" to 6
[eridan].DIE();                 //kills "eridan", prints "DIE eridan" 6 times

输出:

sollux=-2
DIE sollux
DIE sollux
eridan=6
DIE eridan
DIE eridan
DIE eridan
DIE eridan
DIE eridan
DIE eridan

程式2:

import THIS;                    //calls variable "THIS"
~ATH(THIS){EXECUTE(++++)}       //sets the value of "THIS" to 4
bifurcate THIS[THIS1,THIS2];    //deletes "THIS", creates variables "THIS1" and "THIS2" both equal to 4
~ATH(THIS1){EXECUTE(++)}        //sets the value of "THIS1" to 6
[THIS1,THIS2].DIE();            //kills "THIS1" and "THIS2", prints "DIE THIS1" 6 times then "DIE THIS2" 4 times

import THAT;                                         //calls variable "THAT"
bifurcate THAT[THESE,THOSE];                         //deletes "THAT", creates variables "THESE" and "THOSE"
~ATH(THESE){~ATH(THOSE){EXECUTE(+++)}EXECUTE(++)}    //sets the value of "THESE" and "THOSE" to 3, then sets the value of "THESE" to 5
[THESE,THOSE].DIE();                                 //kills "THESE" and "THOSE", prints "DIE THESE" 5 times then "DIE THOSE" 3 times

输出:

THIS1=6
DIE THIS1
DIE THIS1
DIE THIS1
DIE THIS1
DIE THIS1
DIE THIS1
THIS2=4
DIE THIS2
DIE THIS2
DIE THIS2
DIE THIS2
THESE=5
DIE THESE
DIE THESE
DIE THESE
DIE THESE
DIE THESE
THOSE=3
DIE THOSE
DIE THOSE
DIE THOSE

这是代码高尔夫球,因此适用标准规则。以字节为单位的最短代码获胜。


2
直到死亡。我看你在那做什么。
Digital Trauma 2015年

3
@DigitalTrauma我得将功劳归功于安德鲁·侯赛(Andrew Hussie)(写霍姆斯塔克的人),因为他想出了这个名字。
Arcturus

1
@sysreq ~ATH使用分号作为行结束的importbifurcateDIE命令。REPL和文件都可以。输入和输出都要求区分大小写(我正在尝试尽可能匹配实际值~ATH)。
Arcturus

1
@sysreq我必须更改一些内容,以便该语言实际上可以在现实生活中执行某些操作,我描述的PEC很好。
Arcturus

2
老实说,我很惊讶这个问题没有得到更多的答案,更令人惊讶的是,并没有成群的Perl巫师装备着正统的魔杖
cat

Answers:


3

蟒2.7.6,1244 1308 1265 1253 1073 1072 1071 1065 1064 1063个字节

好的,我在这里没有打破任何记录,但这是最小的Python,因为它可以一次从文件中读取所有输入,而不是随时间顺序读取。稍后,我将尝试使用另一种语言(和解释器,而不仅仅是解析器)来完善它。在此之前,请尽情享受令人恶心的恐怖怪兽。

注意t在工作目录中打开一个名为的文件。要使其打开命令行参数,请添加import sys到文件顶部并更改't'sys.argv[1]

n=s='\n';m=',';X='[';Y=']';c=';';A='~ATH';D='import';b,g,k=[],[],[];r=range;l=len;f=open('t','r').read().split(n)
def d(j,u):
 p=[]
 for e in j:
  if e!=u:p.append(e)
 return''.join(p)
for h in r(l(f)):f[h]=f[h].split('//')[0].split()
while[]in f:f.remove([])
for h in r(l(f)):
 i=f[h]
 if i[0]==D and l(i)==2and i[1][l(i[1])-1]==c and d(i[1],c)not in b:g.append(0);b.append(d(i[1],c))
 elif i[0].startswith(A):
  i=i[0].split('){')
  for e in r(l(i)):
   if i[e].startswith(A):
    i[e]=i[e].split('(')
    if i[0][1]in b:g[b.index(i[0][1])]+=(i[1].count('+')-i[1].count('-'))
 elif i[0].startswith('bifurcate')and l(i)==2and i[1][l(i[1])-1]==c:
  i=i[1].split(X)
  if i[0] in b:
   z=d(d(i[1],c),Y).split(m)
   for e in r(l(z)):g.append(g[b.index(i[0])]);b.append(z[e])
   g.remove(g[b.index(i[0])]);b.remove(i[0])
 elif i[0].startswith(X)and i[0].endswith('.DIE();')and l(i)==1:
  z=d(i[0],X).split(Y)[0].split(m)
  for e in r(l(z)):
   k.append((z[e],g[b.index(z[e])]))
for e in r(l(k)):k0=k[e][0];k1=k[e][1];s+=k0+'='+str(k1)+n+('DIE '+k0+n)*abs(k1)
print s

2

Python 2中,447个 475 463 443字节

exec("eNp1UUtrAjEQvu+vCEshiYnrxl7KbqOUVmjvCoUkxUdiG7BRkpW2iP3tTVwrReppMsx8r4l936x9A8JXoN5kmu/2WeCxK0KjrSu8mWmEs0Ad96YI27lDPu/1is7wKqcQ0kBLenM+ty0nilu4zqnPtYCSQcXL2P2LmNvl1i9mjWlBUhwKbRt14uhHjlSvjzVy1tqswO/7AjsSpKtwIpGvt2zALqyNnkf3k/FIolb2ACjlpe2jR6lk8fAUQbKNulx7YIF1IDkqwmZlGwQpxNXGW9cASyCHZKqFVVOCoJQOEhjxABKLO7N5QGmET5qOs/Qfoqq6TGUfb3ZlgKvOnOxTwJKpDq6HSLzsVfK1k7g1iB7Hd9/JWh3T9wclkYwTlY4odP0nnvk0C3RUwj95/ZUq".decode('base64').decode('zip'))

事实证明,压缩和编码程序base64仍比正常版本节省字节。为了进行比较,这是正常的:

import sys,re
d={}
s=sys.stdin.read()
s,n=re.subn(r"//.*?$",'',s,0,8)
s,n=re.subn(r"import (.*?);",r"d['\1']=0;",s,0,8)
s,n=re.subn(r"bifurcate (.*?)\[(.*?),(.*?)\];",r"d['\2']=d['\3']=d['\1'];del d['\1'];",s,0,8)
s,n=re.subn(r"([+-])",r"\g<1>1",s,0,8)
s,n=re.subn(r"EXECUTE\((.*?)\)",r"0\1",s,0,8)
s,n=re.subn(r"\[(.*?)\]\.DIE\(\);",r"for i in '\1'.split(','):print i+'='+`d[i]`+('\\n'+'DIE '+i)*abs(d[i])",s,0,8)
n=1
s=s[::-1]
while n:s,n=re.subn(r"\}([+-01]*);?([^}]*?)\{\)(.*?)\(HTA~",r";\g<2>0+\1=+]'\3'[d;\1",s,0,8)
exec(s[::-1])

基本上是所需的“魔术的魔杖”解决方案。从stdin作为单个字符串读取整个程序,用执行所描述语义的Python表达式替换〜ATH表达式,然后exec()s得到结果字符串。

要查看其功能,请查看python程序,将第二个提供的测试程序转换为:

d['THIS']=0;                    
0+1+1+1+1;d['THIS']+=0+1+1+1+1+0;       
d['THIS1']=d['THIS2']=d['THIS'];del d['THIS'];    
0+1+1;d['THIS1']+=0+1+1+0;        
for i in 'THIS1,THIS2'.split(','):print i+'='+`d[i]`+('\n'+'DIE '+i)*abs(d[i])            

d['THAT']=0;                                         
d['THESE']=d['THOSE']=d['THAT'];del d['THAT'];                         
0+1+1;d['THESE']+=0+1+1+00+1+1+1;d['THOSE']+=0+1+1+1+0;    
for i in 'THESE,THOSE'.split(','):print i+'='+`d[i]`+('\n'+'DIE '+i)*abs(d[i])                                 

00 == 0:P 是一件好事

显然,通过利用规则中的歧义可以节省一些字节。例如,并没有说如果有人尝试DIE()一个尚未被imported或已经被bifurcated 的变量,该怎么办。根据描述,我的猜测是应该有一个错误。如果不需要任何错误,则可以删除该del语句。

编辑:修复了提供的测试用例未测试的错误。即,按原样,每个~ATH块在将其递增之前将变量重置为零。解决这个问题花了我28个字节。如果有人发现替换~ATH积木的更好方法,我很想知道。

编辑2:通过展开正则表达式循环,使它们成为所有子元素,并让压缩处理重复,节省了12个字节。

编辑3:通过将内部for循环替换为字符串乘法,又节省了20个字节。


嘿,终于是神奇的魔杖!我将无法胜任,但做得很好!
2015年

我的实现完全忽略了规则未明确涵盖的内容,这意味着您可以不抛出错误,也只需忽略这些情况。

你可以这样做节省一些字节import sys,re,而不是import sys;import re

1
语法高亮使它更容易阅读
cat

1
@cat对不起,我很久以前忘了回答你。您可以从命令行运行它,并将输入通过文件python ~ath.py < program.~ath
传递
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.