¡Interpreta a Kipple!

12

Introducción

Kipple es un lenguaje de programación esotérico basado en pila inventado por Rune Berg en marzo de 2003.

Kipple tiene 27 pilas, 4 operadores y una estructura de control.

Pilas

Las pilas se nombran a- zy contienen enteros con signo de 32 bits. También hay una pila especial @, para que la salida de números sea más conveniente. Cuando se inserta un número @, los valores ASCII de los dígitos de ese número se empujan en su lugar. (Por ejemplo, si presiona 12 a @, presionará 49 y luego 50 a @).

La entrada se inserta en la pila de entrada iantes de que se ejecute el programa. El intérprete pedirá valores para almacenar iantes de la ejecución. Una vez que finaliza la ejecución, todo lo que está en la pila de salida oaparece como carácter ASCII. Como este es el único mecanismo de E / S de Kipple, es imposible interactuar con un programa de Kipple.

Operadores

Un operando es un identificador de pila o un entero de 32 bits con signo.

Empujar: >o<

Sintaxis: Operand>StackIndentifieroStackIndentifier<Operand

El operador Push lleva el operando a la izquierda y lo empuja a la pila especificada. Por ejemplo, 12>aempujará el valor 12 a la pila a. a>baparecerá el valor más alto de la pila ay lo empujará a la pila b. Hacer estallar una pila vacía siempre devuelve 0. a<bes equivalente a b>a. a<b>csaca el valor más alto de by empuja a ambos cy a.

Añadir: +

Sintaxis: StackIndentifier+Operand

El operador Agregar empuja la suma del elemento superior en la pila y el operando en la pila. Si el operando es una pila, el valor se extrae de él. Por ejemplo, si el valor más alto de la pila aes 1, entonces a+2empujará 3 sobre él. Si aestá vacío, entonces a+2empujará 2 sobre él. Si los valores más altos de stack ay bson 1 y 2, entonces a+bsacará el valor 2 de stack by empujará 3 a stack a.

Sustraer: -

Sintaxis: StackIndentifier-Operand

El operador Restar funciona exactamente igual que el operador Agregar, excepto que resta en lugar de sumar.

Claro: ?

Sintaxis: StackIndentifier?

El operador Clear vacía la pila si su elemento superior es 0.

El intérprete ignorará cualquier cosa que no está al lado de un operador, por lo que el siguiente programa funcionaría: a+2 this will be ignored c<i. Sin embargo, la forma correcta de agregar comentarios es mediante el uso del #personaje. Cualquier cosa entre un #carácter de fin de línea y uno se elimina antes de la ejecución. El carácter ASCII # 10 se define como el final de línea en Kipple.

Los operandos pueden ser compartidos por dos operadores, por ejemplo, a>b c>b c?pueden escribirse como a>b<c?.

El programa 1>a<2 a+aresultará en acontener los valores [1 4](de abajo hacia arriba) y no [1 3]. Igualmente para el -operador.

La estructura de control

Solo hay una estructura de control en Kipple: el bucle.

Sintaxis: (StackIndentifier code )

Mientras la pila especificada no esté vacía, se repetirá el código dentro de los paréntesis coincidentes. Los bucles pueden contener otros bucles. Por ejemplo, (a a>b)moverá todos los valores de stack aa stack b, aunque el orden se revertirá . Una forma funcionalmente idéntica, pero más elegante de hacerlo es (a>b).

Ejemplos

100>@ (@>o)

Esto dará salida 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

Esto se imprimirá "Hello World!". Cuando la opila se emite, comienza a mostrar caracteres de arriba a abajo.

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

Este es un generador de números primos, pero no estoy seguro de cómo funciona.

Reglas

  • Debe escribir un programa / función que interprete Kipple. Este programa / función puede obtener un programa Kipple a través de un archivo fuente, u obtenerlo a través de STDIN directamente del usuario. Si STDIN no está disponible, debe obtenerlo de la entrada del teclado y continuar recibiendo la entrada hasta que se ingrese un carácter no imprimible específico. Por ejemplo, si su intérprete está escrito en código de máquina x86, obtendría el programa Kipple carácter por carácter desde el teclado y continuaría haciéndolo hasta que escse presione (o cualquier otra tecla que no emita un carácter imprimible).

  • Si hay un error, por ejemplo, un error de sintaxis o un desbordamiento de pila, debe reconocerlo de alguna manera, por ejemplo, devolviendo 10 en lugar de 0 o mensajes de error producidos por el intérprete / compilador, PERO NO IMPRIMIENDO MENSAJES DE ERROR .

  • Cualquier otra regla regular para el código de golf se aplica a este desafío.

  • Su código será probado con algunos de los ejemplos en el archivo de muestras de Kipple

Este es un . El código más corto en bytes ganará. ¡Buena suerte!


Tenga en cuenta que hay un operador opcional en Kipple, "pero no es parte de la especificación y solo una característica adicional en el intérprete oficial. No lo he mencionado aquí, por lo que no es necesario que sea compatible con su envío.

Si tiene alguna duda sobre cualquier parte de la especificación, puede examinarla con un intérprete oficial escrito en Java . Esto descargará un archivo zip que contiene el programa compilado y el código fuente. Tiene licencia bajo la GPL.


fuente
1
Hacer que tenemos que utilizar enteros con signo de 32 bits o podemos ir con el tipo entero natural de la aplicación anfitrión? (Los casos más importantes son probablemente enteros de 32 bits sin signo, enteros de 8 bits con signo o sin signo y enteros de precisión arbitraria.)
Martin Ender
bueno, fue lo que encontré en wiki esotric. sí, porque su intérprete puede ser incompatible con otros programas de kipple en los que su mecanismo se basa en esta característica
¿Puede ser más específico sobre el comportamiento en caso de errores? Entonces, ¿podemos devolver una respuesta incorrecta o emitir un error, pero no podemos imprimir el error?
Alex A.
@Alex A. Sí, porque puede considerarse como la salida del programa y puede crear un programa Kipple que puede tener la misma salida que el mensaje de error. También es "más barato" (usa menos caracteres) no tener una función / declaración que imprima un mensaje de error.
3
¿Qué espacio en blanco puede ocurrir en un programa fuente? ¿Cómo puedo pedir información isi tomo el programa fuente de stdin?
orlp

Respuestas:

6

C, 709 702 bytes

La puntuación de bytes se elimina con nuevas líneas (que se pueden eliminar), pero para facilitar la lectura, la publico aquí con nuevas líneas:

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

Compila con gcc -w golf.c( -wsilencia las advertencias para tu cordura).

Admite todo excepto la ientrada, ya que el autor de la pregunta aún no ha respondido a mi consulta sobre cómo hacerlo si toma el código de stdin. No informa errores de sintaxis.

orlp
fuente
He respondido a tu pregunta sobre la pila "i" en los comentarios de la publicación principal.
Por cierto, ¿cómo lee los programas de Kipple? a través de argumentos de comando? ¿Cómo debo usarlo?
@GLASSIC Espera el programa en stdin.
orlp
Hasta cuando ? ¿Cómo comenzar la excitación?
@GLASSIC Simplemente pasa el programa en stdin. Por ej ./a.out < prime.k.
orlp
3

Ruby, 718 bytes (actualmente sin competencia)

estoy muy cansado

El archivo se carga como un argumento de línea de comando y la entrada se envía a través de STDIN. Alternativamente, canalice el archivo en STDIN si no necesita entrada en su iregistro.

Debido a cierta confusión con respecto a la especificación, la versión actual no se maneja a<b>ccorrectamente y, por lo tanto, no es competitiva hasta que se solucione.

a<b>cestá arreglado ahora. Sin embargo, aún devuelve el resultado incorrecto al ejecutar la función primos, por lo que sigue siendo una respuesta no competitiva.

(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
Tinta de valor
fuente
+1 de todos modos. ¿Probaste el programa fibonacci?
edc65
@ edc65 El programa de secuencia de Fibbonacci también imprime algo incorrecto: 0 1 1 2 4 8 16...me pregunto si es un error de especificación
Value Ink
No, el programa Fibonacci es una mierda, por ejemplo, la línea no a+0tiene sentido
edc65
Supongo que el problema con los números primos es que no maneja estructuras de control anidadas, pero no sé mucho sobre Ruby, dudo que mi suposición sea correcta.
Este programa debe manejar conjuntos anidados de parens correctamente debido a la coincidencia de expresiones regulares recursivas /(\((\g<1>|\s)+\)|[^()\s]+)/mque utiliza para dividir en tokens y grupos de tokens. ( Pruébelo en regex101 ). Probablemente sea un error en el resto de mi análisis, pero no sé dónde.
Value Ink