Schreiben Sie einen ~ ATH-Dolmetscher

12

Das beliebte Webcomic Homestuck verwendet eine Programmiersprache, die ~ATHdazu dient, Universen zu zerstören. Während diese Code-Golf-Herausforderung nicht darin besteht, ein Programm zu schreiben, um unsere Existenz zu vernichten, werden wir einige zahmere (wenn auch weniger interessante) Entitäten zerstören: Variablen

~ATH(ausgesprochen "bis zum Tod", beachten Sie, wie ~ath"tilde ath" ist), indem Sie eine aufgerufene Variable erstellen THIS, einen Befehl mit ausführen EXECUTEund das Programm mit beenden THIS.DIE(). Eine Wiki-Seite für die Verwendung der Sprache in Homestuck finden Sie hier . Ziel dieser Herausforderung ist es, einen ~ATHDolmetscher zu erstellen .

Um der Herausforderung willen werde ich einige Details erstellen ~ATH, die es nicht wirklich gibt, aber die es (etwas) nützlich machen.

  • Die Sprache funktioniert nur mit Ganzzahlen, die mit deklariert sind import <variable name>; . Die Variable wird automatisch auf den Wert 0 gesetzt. Es kann jeweils nur eine Variable importiert werden.
  • Eine Variable xkann durch Schreiben kopiert werden bifurcate x[y,z];, wodurch die Variable gelöscht xund durch identische Variablen yund ersetzt wird z. Beachten Sie, dass keine Variable mit demselben Namen wie die gelöschte erstellt werden kann. Im Wesentlichen wird eine Variable umbenannt und anschließend eine Kopie der Variablen mit einem anderen Namen erstellt. Dies scheint ein dummer Zug zu sein, aber die Dummheit ist sehr tief verwurzelt in Homestuck .
  • Die Syntax zum Schreiben eines Programms, in dem Code ausgeführt wird, xlautet ~ATH(x){EXECUTE(<code>)}. Wenn Sie Code auf zwei Variablen gleichzeitig ausgeführt werden soll, wird der Code verschachtelt, wie folgt aus : ~ATH(x){~ATH(y){EXECUTE(<code>)}}. Alle eingehenden Befehle <code>werden auf xund ausgeführty .
  • Gehen wir nun zu den Befehlen über. +erhöht relevante Variable (n) um 1 und- dekrementiert sie um 1. Und ... das war's.
  • Das letzte Merkmal von ~ATHist, dass es alles tötet, womit es funktioniert. Variablen werden im Format <name>=<value>(gefolgt von einer neuen Zeile) auf Befehl gedruckt [<name>].DIE();. Danach gibt das Programm das Wort DIE <name>und eine neue Zeile so oft aus, wie der absolute Wert des Werts der Variablen entspricht. Wenn Variablen gleichzeitig mit getötet werden [<name1>,<name2>].DIE();(Sie können so viele Variablen töten lassen, wie Sie möchten, solange sie existieren), wird der DIE()Befehl nacheinander für die Variablen ausgeführt.

Beispielprogramme

Programm 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

Ausgabe:

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

Programm 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

Ausgabe:

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

Dies ist Codegolf, daher gelten die Standardregeln. Kürzester Code in Bytes gewinnt.

Arcturus
quelle
2
Bis zum Tod. Ich sehe, was du dort getan hast.
Digitales Trauma
3
@DigitalTrauma Ich muss Andrew Hussie (dem Typ, der Homestuck schreibt) die Ehre erweisen, weil er den Namen erfunden hat.
Arcturus
1
@sysreq ~ATHverwendet Semikolons als Zeilenenden für das import, bifurcateund DIEBefehle. Sowohl REPL als auch Dateien sind in Ordnung. Sowohl in der Eingabe als auch in der Ausgabe muss die Groß- und Kleinschreibung beachtet werden (ich versuche, die tatsächliche Schreibweise ~ATHso weit wie möglich zu berücksichtigen).
Arcturus
1
@sysreq Ich hatte ein paar Dinge zu ändern , so dass die Sprache tatsächlich würde tut etwas im wirklichen Leben, Pecs I beschrieben ist in Ordnung.
Arcturus
2
Ich bin ehrlich überrascht, dass diese Frage nicht mehr beantwortet wurde, und noch überraschender ist, dass es keine Horde von Perl-Zauberern gibt, die mit regulären Zauberstäben bewaffnet sind
Katze vom

Antworten:

3

Python 2.7.6, 1244 1308 1265 1253 1073 1072 1071 1065 1064 1063 Bytes

In Ordnung, ich brich hier keine Rekorde, aber dies ist ungefähr die kleinste Python-Methode, bei der alle Eingaben auf einmal aus einer Datei und nicht nacheinander im Laufe der Zeit gelesen werden. Ich werde später versuchen, dies in einer anderen Sprache (und einem Dolmetscher, nicht nur einem Parser) zu erläutern. Genießen Sie bis dahin die widerlich schreckliche Monstrosität.

Hinweis : Öffnet eine tim Arbeitsverzeichnis aufgerufene Datei . Um ein Befehlszeilenargument zu öffnen, fügen Sie import syses am Anfang der Datei hinzu und ändern Sie es 't'insys.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
Katze
quelle
2

Python 2, 447 475 463 443 Bytes

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

Es stellt sich heraus, dass das Zippen und Codieren des Programms base64 immer noch Bytes gegenüber der normalen Version spart. Zum Vergleich hier der normale:

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])

Grundsätzlich war die "regexy Zauberstäbe" -Lösung erwünscht. Liest das gesamte Programm von stdin als einzelne Zeichenfolge ein, ersetzt ~ ATH-Ausdrücke durch Python-Ausdrücke, die die beschriebene Semantik ausführen, und führt () die resultierende Zeichenfolge aus.

Schauen Sie sich das Python-Programm an, in das das zweite Testprogramm übersetzt wird:

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])                                 

Es ist gut, dass 00 == 0: P

Offensichtlich könnten einige Bytes gespart werden, indem Mehrdeutigkeiten in den Regeln ausgenutzt werden. Zum Beispiel wird nicht gesagt, was passieren soll, wenn jemand versucht, DIE()eine Variable zu bearbeiten, die nicht importoder bereits bifurcatebearbeitet wurde. Meine Vermutung basierend auf der Beschreibung war, dass es einen Fehler geben sollte. Wenn kein Fehler erforderlich ist, könnte ich die delAnweisung entfernen .

BEARBEITEN: Es wurde ein Fehler behoben, auf den die bereitgestellten Testfälle nicht getestet wurden. So wie es war, setzte jeder ~ATHBlock die Variable auf Null zurück, bevor er sie inkrementierte. Es hat mich 28 Bytes gekostet, das zu reparieren. Wenn jemand eine bessere Möglichkeit zum Ersetzen von ~ATHBlöcken sieht , würde ich es gerne wissen.

BEARBEITEN 2: 12 Bytes wurden eingespart, indem die Regex-Schleife aufgerollt wurde, alle Subns erstellt wurden und die Komprimierung sich um die Wiederholung kümmerte.

EDIT 3: Durch Ersetzen der inneren forSchleife durch eine String-Multiplikation wurden 20 weitere Bytes eingespart.

Quintopie
quelle
Hey, endlich die regexy Zauberstäbe! Ich werde das nicht schlagen können, aber gut gemacht!
Katze
Meine Implementierung ignoriert alle Dinge, die nicht explizit von den Regeln abgedeckt werden. Das bedeutet, dass es in Ordnung ist, keinen Fehler zu werfen und diese Fälle einfach zu ignorieren.
Katze
Sie könnten ein paar Bytes , indem Sie speichern import sys,renichtimport sys;import re
Katze
1
Syntax-Hervorhebung erleichtert das Lesen
cat
1
@cat sorry, ich habe vergessen, dir vor so langer Zeit zu antworten. Sie führen es von der Kommandozeile aus und python ~ath.py < program.~ath
leiten