〜ATHインタープリターを作成する


12

人気のあるウェブコミックHomestuckは、~ATH宇宙を破壊するために呼び出されるプログラミング言語を使用しています。このゴルフの挑戦は、私たちの存在を全滅させるプログラムを書くことではありませんが、もっと面白くない(あまり面白くない)エンティティを破壊しますvariables。 

~ATH( "til death"と発音します。~ath"tilde ath"はどのように機能するかを確認してください)は、という変数を作成しTHIS、でコマンドを実行しEXECUTE、でプログラムを終了することで機能しTHIS.DIE()ます。Homestuckでの言語の使用に関するWikiページは、ここにあります。この課題の目標は、~ATH通訳を作成することです。

挑戦のために、私は~ATH実際には存在しないいくつかの詳細を作成しますが、それを(ある程度)有用にします。

  • この言語は、で宣言されている整数でのみ機能しますimport <variable name>;。変数は自動的に値0に設定されます。一度にインポートできる変数は1つだけです。
  • 変数xは、書き込みによってコピーできますbifurcate x[y,z];。これにより、変数が削除されx、同一の変数yおよびに置き換えられますz。削除された変数と同じ名前の変数を作成できないことに注意してください。基本的に、変数の名前が変更され、別の名前の変数のコピーが作成されます。これは馬鹿げた機能のように見えますが、愚かさはHomestuck に非常に深く根付いています。
  • コードを実行するプログラムを記述するための構文x~ATH(x){EXECUTE(<code>)}です。2つの変数に対して同時にコードを実行する場合、コードは次のようにネストされます~ATH(x){~ATH(y){EXECUTE(<code>)}}。のすべてのコマンド<code>両方で実行されますxy
  • それではコマンドに移りましょう。 +関連する変数を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
死ぬまで。あなたがそこで何をしたかわかる。
デジタル外傷

3
@DigitalTrauma名前を思いついたAndrew Hussie(Homestuckを書いている人)にクレジットを渡す必要があります。
アークトゥルス

1
@sysreqは~ATHのための行末としてセミコロンを使用してimportbifurcate、およびDIEコマンド。REPLとファイルの両方に問題はありません。入力と出力の両方で大文字と小文字を区別する必要があります(~ATHできるだけ実際に一致させようとしています)。
アークトゥルス

1
私は言語が実際しまうので、いくつかのことを変更しなければならなかった@sysreq 行う実際の生活の中で何かを、私は説明ペーチは大丈夫です。
アークトゥルス

2
私正直この質問は、より多くの回答を得て、さらにウィザードの魔法の杖regexyで武装したPerlのない大群がありません驚いていない驚いている

回答:


3

Pythonの2.7.6、1244 1308 1265 1253 1073 1072の 1071 1065 1064 1063バイト

申し分ありませんが、ここで記録を破るわけではありませんが、これは、時間をかけて連続的にではなく、ファイルから入力を一度に読み取る限り、最小のPythonについてです。後で別の言語(およびパーサーだけでなくインタープリター)でこれを1つにしようとします。それまでは、嫌な恐ろしい怪物を楽しんでください。

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から単一の文字列として読み込み、〜ATH式を記述されたセマンティクスを実行するPython式に置き換え、結果の文字列をexec()します。

それが何をしているのかを見るために、2番目に提供されたテストプログラムが翻訳される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()されていない変数import、または既にbifurcatedである変数を誰かが試行した場合に何が起こるべきかは述べられていません。説明に基づく私の推測は、エラーがあるはずだということでした。エラーが不要な場合は、削除できますdelステートメントをます。

編集:提供されたテストケースがテストしなかったバグを修正しました。つまり、ある方法では、すべての~ATHブロックが変数をゼロにリセットしてから増分します。それを修正するには28バイトかかりました。~ATHブロックを交換するより良い方法を誰かが見たら、それを知りたいです。

編集2:正規表現ループを展開し、それらをすべてsubnsにし、圧縮に繰り返しを処理させることにより、12バイトを保存しました。

編集3:内側のforループを文字列の乗算で置き換えることにより、さらに20バイトを節約しました。


ねえ、ついに魔法の正規表現のワンド!私はこれを打ち負かすことはできませんが、よくやった!

私の実装では、ルールで明示的にカバーされていないものを完全に無視します。つまり、エラーをスローせず、それらのケースも無視してもかまいません。

あなたは行って、いくつかのバイトを救うことができるimport sys,reのではなくimport sys;import re

1
構文の強調表示は読み、これは非常に簡単になります

1
@catすみません、ずっと前にあなたに答えるのを忘れていました。コマンドラインから実行し、入力をファイルからパイプしますpython ~ath.py < program.~ath
。– quintopia
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.