Interpretiere Kipple!


12

Einführung

Kipple ist eine Stack-basierte, esoterische Programmiersprache, die im März 2003 von Rune Berg erfunden wurde.

Kipple hat 27 Stapel, 4 Bediener und eine Kontrollstruktur.

Stapel

Die Stapel heißen a- zund enthalten 32-Bit-Ganzzahlen mit Vorzeichen. Es gibt auch einen speziellen Stapel @, um die Ausgabe von Zahlen zu vereinfachen. Wenn auf eine Nummer gedrückt wird @, werden stattdessen die ASCII-Werte der Ziffern dieser Nummer gedrückt. (Wenn Sie beispielsweise 12 bis @drücken, werden @stattdessen 49 und dann 50 bis gedrückt.)

Die Eingabe wird auf den Eingabestapel geschoben, ibevor das Programm ausgeführt wird. Der Interpreter fragt nach Werten, die ivor der Ausführung gespeichert werden sollen . Nach Abschluss der Ausführung wird alles im oAusgabestapel als ASCII-Zeichen ausgegeben. Da dies der einzige E / A-Mechanismus von Kipple ist, ist die Interaktion mit einem Kipple-Programm nicht möglich.

Betreiber

Ein Operand ist entweder eine Stapelkennung oder eine vorzeichenbehaftete 32-Bit-Ganzzahl.

Drücken Sie: >oder<

Syntax: Operand>StackIndentifieroderStackIndentifier<Operand

Der Push-Operator nimmt den Operanden nach links und schiebt ihn auf den angegebenen Stapel. Zum Beispiel 12>awird der Wert 12 auf den Stapel geschoben a. a>bwird den obersten Wert vom Stapel nehmen aund auf den Stapel schieben b. Das Platzen eines leeren Stapels a<bergibt immer 0. ist äquivalent zu b>a. a<b>cErmittelt den höchsten Wert von bund drückt auf beide cund a.

Hinzufügen: +

Syntax: StackIndentifier+Operand

Der Operator Add schiebt die Summe des obersten Elements auf dem Stapel und des Operanden auf den Stapel. Wenn es sich bei dem Operanden um einen Stapel handelt, wird der Wert daraus abgerufen. Wenn zum Beispiel der oberste Wert des Stapels a1 ist, a+2wird 3 darauf gedrückt. Wenn aleer, a+2wird 2 darauf gedrückt. Wenn die obersten Werte von stack aund b1 und 2 sind, a+bwird der Wert 2 vom Stack genommen bund 3 auf den Stack geschoben a.

Subtrahieren: -

Syntax: StackIndentifier-Operand

Der Subtraktionsoperator funktioniert genauso wie der Additionsoperator, außer dass er subtrahiert, anstatt zu addieren.

Klar: ?

Syntax: StackIndentifier?

Der Operator "Löschen" leert den Stapel, wenn das oberste Element 0 ist.

Der Dolmetscher wird alles ignorieren , die nicht neben einen Operator ist, so dass das folgende Programm funktionieren würde: a+2 this will be ignored c<i. Die richtige Möglichkeit zum Hinzufügen von Kommentaren ist jedoch die Verwendung des #Zeichens. Alles zwischen einem #und einem Zeilenendezeichen wird vor der Ausführung entfernt. Das ASCII-Zeichen Nr. 10 wird in Kipple als Zeilenende definiert.

Operanden können von zwei Operatoren gemeinsam verwendet werden, z. B. a>b c>b c?geschrieben als a>b<c?.

Das Programm 1>a<2 a+aführt in aden Werten , die [1 4](von unten nach oben) und nicht [1 3]. Ebenso für den -Betreiber.

Die Kontrollstruktur

Es gibt nur eine Kontrollstruktur in Kipple: die Schleife.

Syntax: (StackIndentifier code )

Solange der angegebene Stapel nicht leer ist, wird der Code in den entsprechenden Klammern wiederholt. Loops können andere Loops enthalten. Zum Beispiel (a a>b)werden alle Werte des Stapels aauf den Stapel verschoben b, obwohl die Reihenfolge umgekehrt wird . Eine funktional identische, aber elegantere Art, dies zu tun, ist (a>b).

Beispiele

100>@ (@>o)

Dies wird ausgegeben 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

Dies wird gedruckt "Hello World!". Wenn der oStapel ausgegeben wird, beginnt er, Zeichen von oben nach unten zu platzieren.

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

Dies ist ein Primzahlengenerator, aber ich bin nicht sicher, wie es funktioniert.

Regeln

  • Sie müssen ein Programm / eine Funktion schreiben, die Kipple interpretiert. Dieses Programm / diese Funktion kann ein Kipple-Programm über eine Quelldatei oder direkt vom Benutzer über STDIN erhalten. Wenn STDIN nicht verfügbar ist, muss es über die Tastatureingabe abgerufen werden und die Eingabe fortgesetzt werden, bis ein bestimmtes nicht druckbares Zeichen eingegeben wird. Wenn Ihr Interpreter beispielsweise in x86-Maschinencode geschrieben ist, wird das Kipple-Programm zeichenweise von der Tastatur abgerufen, und dies wird fortgesetzt, bis esc(oder eine andere Taste, die kein druckbares Zeichen ausgibt) gedrückt wird.

  • Wenn ein Fehler vorliegt, z. B. ein Syntaxfehler oder ein Stapelüberlauf, muss er dies auf irgendeine Weise bestätigen, z. B. durch Rückgabe von 10 anstelle von 0 oder Fehlermeldungen, die vom Interpreter / Compiler ausgegeben werden , ABER KEINE DRUCKFEHLERMELDUNGEN .

  • Alle anderen regulären Regeln für Code-Golf gelten für diese Herausforderung.

  • Ihr Code wird anhand einiger Beispiele im Kipple- Beispielarchiv getestet

Dies ist ein . Der kürzeste Code in Bytes gewinnt. Viel Glück!


Beachten Sie, dass es in Kipple einen optionalen Operator gibt, der "jedoch nicht Teil der Spezifikation und nur eine zusätzliche Funktion im offiziellen Interpreter ist. Ich habe es hier nicht erwähnt, so dass es in Ihrer Einreichung nicht unterstützt werden muss.

Wenn Sie irgendwelche Zweifel an einem Teil der Spezifikation haben, können Sie diese mit einem in Java geschriebenen offiziellen Interpreter untersuchen . Dadurch wird eine Zip-Datei mit kompiliertem Programm und Quellcode heruntergeladen. Es ist unter der GPL lizenziert.


1
Haben wir haben 32-Bit - Integer mit Vorzeichen verwenden oder können wir mit der Host - Implementierung natürlichen Integer - Typ gehen? (Die wichtigsten Fälle sind wahrscheinlich vorzeichenlose 32-Bit-Ganzzahlen, vorzeichenbehaftete oder vorzeichenlose 8-Bit-Ganzzahlen und Ganzzahlen mit willkürlicher Genauigkeit.)
Martin Ender

Nun, es war das, was ich im esotric wiki gefunden habe. ja, da Ihr Interpreter möglicherweise nicht mit anderen Kipple-Programmen kompatibel ist, deren Mechanismus auf dieser Funktion basiert

Können Sie das Verhalten im Fehlerfall genauer beschreiben? So können wir eine falsche Antwort zurückgeben oder einen Fehler ausgeben, aber wir können den Fehler nicht drucken?
Alex A.

@Alex A. Ja, da dies als Programmausgabe betrachtet werden kann und Sie ein Kipple-Programm erstellen können, das dieselbe Ausgabe wie eine Fehlermeldung haben kann. Es ist auch "billiger" (benötigt weniger Zeichen), keine Funktion / Anweisung zu haben, die eine Fehlermeldung ausgibt.

3
Welche Leerzeichen können in einem Quellprogramm auftreten? Wie kann ich nach einer Eingabe fragen, iwenn ich das Quellprogramm von stdin übernehme?
Orlp

Antworten:


6

C 709 702 Bytes

Die Bytewertung wird mit Zeilenumbrüchen (die entfernt werden können) entfernt, aber zum leichteren Lesen poste ich sie hier mit Zeilenumbrüchen:

#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;}}}

Kompilieren Sie mit gcc -w golf.c( -wStille Warnungen für Ihre geistige Gesundheit).

Unterstützt alles außer der iEingabe, da der Fragesteller noch nicht auf meine Anfrage geantwortet hat, wie es geht, wenn Sie den Code von stdin nehmen. Es werden keine Syntaxfehler gemeldet.


Ich habe deine Frage zu "i" in den Kommentaren des Hauptpostens beantwortet.

übrigens, wie liest es Kipple-Programme? über Befehlsargumente? Wie soll ich es benutzen?

@GLASSIC Es erwartet das Programm auf stdin.
Orlp

Bis wann? Wie fange ich an?

@GLASSIC Gib einfach das Programm an stdin weiter. ZB ./a.out < prime.k.
Orlp

3

Ruby, 718 Bytes (derzeit nicht konkurrierend)

Ich bin sehr müde

Die Datei wird als Befehlszeilenargument geladen und die Eingabe wird über STDIN gesendet. Alternativ können Sie die Datei an STDIN weiterleiten, wenn Sie keine Eingabe in Ihr iRegister benötigen .

Aufgrund einiger Unklarheiten in Bezug auf die Spezifikation wird die aktuelle Version nicht a<b>cordnungsgemäß verarbeitet und ist daher erst dann konkurrierend, wenn sie behoben ist.

a<b>cist jetzt behoben. Es gibt jedoch immer noch das falsche Ergebnis zurück, wenn die Primzahlenfunktion ausgeführt wird, sodass es immer noch eine nicht konkurrierende Antwort ist.

(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 sowieso. Haben Sie das Fibonacci-Programm ausprobiert?
EDC65

@ edc65 Fibbonacci-Sequenzprogramm druckt auch das Falsche: 0 1 1 2 4 8 16...Ich frage mich, ob es ein Spezifikationsfehler ist
Value Ink

Nein, das Fibonacci-Programm ist Mist, zum Beispiel ist die Zeile a+0Unsinn
edc65

Ich denke, das Problem bei Primzahlen ist, dass es keine verschachtelten Kontrollstrukturen handhabt, aber ich weiß nicht viel über Ruby, ich bezweifle, dass meine Vermutung richtig ist.

Dieses Programm sollte verschachtelte Sätze von Parens aufgrund der rekursiven Regex-Übereinstimmung /(\((\g<1>|\s)+\)|[^()\s]+)/m, die zum Teilen von Tokens und Token-Gruppen verwendet wird, ordnungsgemäß behandeln . ( Teste es auf regex101 ). Es ist wahrscheinlich ein Fehler im Rest meiner Analyse, aber ich weiß nicht wo.
Value Ink
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.