Interpretar volátil

11

Interpretar volátil

Volátil es un esolang basado en pila hecho por A_ / a '_' / A que solo tiene 8 instrucciones y se está completando. Sin embargo, también es no determinista ... lo que significa que los programas no siempre dan el mismo resultado. Tu tarea es interpretar este lenguaje.

Especificaciones de idioma

Tomado de la página de esolangs:

~: Push a random integer in any range of integers. Minimum range of 0 through 32768

+: Pop 2 values and push the sum of the 2 values

-: Like +, but subtracts

*: Multiply

/: Divide. 0-division will result in an error.

:: Duplicate the top of the stack

.: Output the top of the stack without popping it


(...): Execute ... inside a while loop when the top of the stack is not 0

Todo lo demás no se tiene en cuenta.

Entrada

Tenga en cuenta que estos programas pueden fallar aleatoriamente

~:/::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.~:/:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.~:/::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.~:/::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.~:/:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.~:/::::::::::::::::::::::::::::::::::::::::::::++++++++++++++++++++++++++++++++++++++++++++.~:/::::::::::::::::::::::::::::::::++++++++++++++++++++++++++++++++.~:/:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.~:/:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.~:/::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.~:/::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.~:/::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.~:/:::::::::::::::::::::::::::::::::+++++++++++++++++++++++++++++++++.~:/::::::::::++++++++++.

~:-.~:/+.(~:/+.)

~:-:/

Salida

73 102 109 109 112 45 33 120 112 115 109 101 34 11

0 1 2 3 4 5 6 7 8 9 ...

<Any Error Message>

Se pueden encontrar más ejemplos, así como una implementación de referencia (use el segundo, que se encuentra en (Otro) intérprete de python 3 ) en https://esolangs.org/wiki/Volatile

Puntuación

Este es el código de golf, por lo que la respuesta más corta en bytes gana

Tablas de clasificación

Aquí hay un fragmento de pila para generar una tabla de clasificación regular y una descripción general de los ganadores por idioma.

Para asegurarse de que su respuesta se muestre, comience con un título, usando la siguiente plantilla de Markdown:

# Language Name, N bytes

¿Dónde Nestá el tamaño de su envío? Si mejora su puntaje, puede mantener los puntajes antiguos en el título, tachándolos. Por ejemplo:

# Ruby, <s>104</s> <s>101</s> 96 bytes

Si desea incluir varios números en su encabezado (por ejemplo, porque su puntaje es la suma de dos archivos o desea enumerar las penalizaciones de la bandera del intérprete por separado), asegúrese de que el puntaje real sea el último número en el encabezado:

# Perl, 43 + 2 (-p flag) = 45 bytes

También puede hacer que el nombre del idioma sea un enlace que luego aparecerá en el fragmento de la tabla de clasificación:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes

Lyxal
fuente
2
¿Se supone que la división se redondea hacia 0?
Grimmy
¿ ~Empuja un número entero o cualquier número?
mbomb007
1
Además, dependiendo de la implementación, esto podría no ser realmente no determinista. Claro, la página de esolang dice que sí, pero eso es solo por la forma en que aparece para empujar 1, que podría dividirse por cero. ~debe ser capaz de presionar cero, de lo contrario es determinista. Además, el RNG siempre debe poder devolver cero después de cualquier número de ceros en una fila.
mbomb007
2
¿No debería ~:-.~:/+.(~:/+.)comenzar esa segunda entrada en 0 1 2 ...lugar de 1 2 3 ...? El ~:-.resultado sería 0, que sale. Esos intérpretes en la página de Esolang parecen confirmar esto ( aquí el segundo ).
Kevin Cruijssen
2
Sugerencia para agregar un caso de prueba:~:-.(~:/+.)
Night2

Respuestas:

6

05AB1E , 35 bytes

"~:/.()"”žGÝΩ DŠéõq}÷ = [D_# }”#‡.V

Pruébalo en línea!

Transpila el código volátil a 05AB1E, luego lo evalúa. *, +y -se puede dejar como está. :, .y )tienen un equivalente directo de un byte. Los otros comandos toman unos pocos bytes cada uno. Desafortunadamente, 05AB1E no se bloquea en la división por 0, por lo que en su lugar se implementa mediante un "salir condicional si la parte superior de la pila == 0".

Mugriento
fuente
1
¿Funciona esto correctamente para el bucle? Si ingreso el segundo caso de prueba, parece salir 0y 1correctamente antes del ciclo, pero luego comienza a emitir el programa Volátil (la entrada implícita) en sí. Me gusta esa D Doingõqcadena de diccionario para la declaración if, por cierto! :)
Kevin Cruijssen
1
@KevinCruijssen, el ejemplo parece suponer que el bucle es a while peek, pero en el intérprete de referencia es a while pop. El ejemplo se puede solucionar agregando algunos :( TIO ). Alternativamente, mi código se puede cambiar a a while peekmediante la adición de a D.
Grimmy
1
Sin embargo 0 1 2 3 ..., ambos intérpretes de referencia de Esolang todavía salen . No he mirado su código fuente, pero solo he probado los dos.
Kevin Cruijssen
1
@KevinCruijssen Oh, la función se llama pop pero en realidad es un vistazo. Máximamente confuso. Agregué el Den mi código.
Grimmy
Lol ... Los nombres confusos incorporados me recuerdan a los replacevs de Java replaceAll(que reemplazan todas las ocurrencias, pero las replaceAllexpresiones regulares de uso y la otra no). xD
Kevin Cruijssen
4

Julia 1.0 , 334 bytes

a\b=push!(a,b)
a=pop!(a)
v(q,s=[],l=0)=(i=1;
for c in q
!r=c==r
i+=1
!')' ? (l<1 && break;l-=1) :
!'(' ? (while s[end]!=0 v(q[i:end],s) end;l+=1) :
l>0 ? continue :
!'~' ? s\rand(Int) : 
!'+' ? s\(s+√s) :
!'-' ? s\(s-√s) :
!'*' ? s\(s*√s) :
!'/' ? s\(s÷√s) :
!':' ? s\s[end] :
!'.' ? print(s[end]," ") : 0
end)

Mi primer "intérprete" de cualquier tipo, fue más fácil de lo que esperaba. Practiqué un poco de golf básico, pero probablemente haya espacio para más. Lo hice imprimir un espacio después de la salida para. a mach a salida de ejemplo. La versión sin golf está en el encabezado en el enlace TIO. Ejemplo de uso v("~:-:/").

+41 bytes para corregir el error que Night2 señaló al agregar un contador de bucle. Ahora veo por qué transpilar es una buena opción. Un buen caso de prueba es ~:-.(~:/+.)(~:/+.())~:-.con la salida esperada0 0

Pruébalo en línea!

gggg
fuente
3

Encantamientos rúnicos , 266 264 bytes

DS͗{r;'ui[0[0y̤<<<<<?+f2,;$"!0/"?*7≠0:S͗\
RS͗}:'~=?!\:':=?!\:'+=?!\:'-=?!\:'/=?!/:'.=?!\:'*=?!\:';=?!;:')≠3*?04B͍:'(=?!S͗
U/lA`R耀`S͗/?7  :S͗/?+f1+S͗/?3  -S͗/?3     $ '$:S͗/?7  *S͗/
U\m(d*?"SO!"$;
{:'(=?!\:')=?!\R
~/?)0l{͗/?8 {͗l}͗/U
 \}͗21B͍

Pruébalo en línea!

Debido a las limitaciones integradas en Runic, solo puede admitir longitudes de programa (y tamaño de pila) de ~ 50 1 . Los programas que son demasiado grandes simplemente fallarán. Si la pila crece demasiado, se producirá un error con SO!(no era necesario, pero era mejor que la terminación silenciosa; costo 24 bytes). Si el programa intenta dividir por 0, se imprimirá /0!.

Los errores se agregan al final de la salida estándar ya que Runic no tiene forma de escribir en STDERR.

Esta versión admitirá programas arbitrariamente largos, pero aún se limita a una pila de ~ 90 (y, por lo tanto, errores en el segundo resultado del primer programa de prueba) y no se ha jugado muy bien (el aumento en la longitud del comando entre S͗}:y S͗}͍:0%:requirió algo de espacio adicional para que las secciones se alineen, pero ese espacio adicional también permitió más <para un tamaño de pila máximo más grande).

Alternativamente, este programa evitará ~generar un cero y el programa terminará después de 1 millón de pasos de ejecución (una protección contra bucles infinitos integrados en el intérprete rúnico). También incluye algunos bytes para omitir el exceso de espacio NOP y ejecutar un poco más.

  1. Se acumulan los fizzling de gran tamaño en (IP mana + 10) y el control que puse para la pila de Volatile es sizeof(stack) < manay hay 5 IP que se combinan y combinan su maná (50 iniciales). Aumentar ese valor al límite verdadero (el +10) costaría otros 2 bytes y dejé la lógica golfy en lugar de precisa.

Explicación

Flujo volátil

  1. El programa comienza en el área azul del centro superior a lo largo de <<<<<y las cinco IP se fusionan en ely
  2. IP se mueve hacia la izquierda, configura las pilas y lee la entrada y se mueve a la sección cian
  3. IP se mueve hacia la derecha por esta línea y comprueba el carácter superior de la pila para saber qué comando es. Esta línea continúa a la derecha más allá de lo visible. cuando se encuentra la instrucción correcta, ejecuta el código en la línea de abajo a la izquierda (saltando sobre otras secciones para volver al cian a través del azul).
  4. La sección magenta se ejecuta durante ~o: comandos de error en el desbordamiento de la pila, la sección amarilla se omite si la pila no está demasiado llena y regresa a través del envolvente al azul oscuro.
  5. Lejos a la derecha cuando )se encuentra el programa, se ramifica a la sección roja y se mueve a la derecha.
  6. Esta sección gira la pila de comandos hacia la derecha hasta que (se encuentra un (continúe en verde).
  7. Por cada adicional que )se encuentre (proceda en naranja), la pila de profundidad de pila se golpea y cuando (se encuentra a, la pila de profundidad de pila se abre una vez (proceder al reingreso verde oscuro y naranja)
  8. Si la pila de profundidad está vacía, continúe siguiendo el color verde hacia By regrese al cian al bucle de análisis principal; de lo contrario, envuelva a través de naranja-> amarillo-> rojo (reingresando al bucle de reinicio del bucle).
  9. El morado en la esquina superior derecha maneja la división, si el valor para dividir por 0 es, la sección marrón maneja el error y la terminación. Vuelve a ingresar al ciclo de análisis principal saltando la sección cian.
Draco18s ya no confía en SE
fuente
2

PHP , 196 bytes

eval(strtr($argn,[':'=>($v='$a[]=').$e='end($a);','~'=>$v.'rand();','+'=>($q=$v.$p='array_pop($a)')."+$p;",'-'=>"$q-$p;",'*'=>"$q*$p;",'/'=>"$q/$p;",'.'=>"echo' ',$e",'('=>"for(;$e){",')'=>'}']));

Entrada 1: ¡ Pruébelo en línea!

Entrada 2 (0, 1, 2, ...): ¡ Pruébelo en línea!

Entrada 3 (división por error cero): ¡ Pruébelo en línea!

¡Simplemente traduce el código a PHP y lo evalúa!

Noche2
fuente
2

JavaScript (V8) ,  178172171  bytes

Transpiles a JS. Puede arrojar cualquiera Z is not definedo x is not definedsi el código intenta hacer algo malo.

s=>eval(s.replace(/./g,c=>`S.push(${c>'}'?'x=Math.random()*1e5|0':c>'9'?'x':c=='.'?');print(x':c<')'?');while(x){(0':c<'*'?')}(0':`1/(x${c}=S.pop(S.pop()))?x:Z`});`,S=[]))

¡Prueba el primer programa en línea!

¡Prueba el segundo programa en línea!

¡Prueba el 3er programa en línea!

¿Cómo?

Cada instrucción se transpira a S.push(, seguida de un patrón específico, seguido de );.

Tenemos que probar la división por cero explícitamente porque a JS no le importa en lo más mínimo una operación tan inofensiva. :-pags

carbonizarse. El | Código JS
------- + --------------------------------------
   ~ | S.push ( x = Math.random () * 1e5 | 0 );
   + | S.push ( 1 / (x + = S.pop (S.pop ()))? X: Z );
   - | S.push ( 1 / (x- = S.pop (S.pop ()))? X: Z );
   * | S.push ( 1 / (x * = S.pop (S.pop ()))? X: Z );
   / | S.push ( 1 / (x / = S.pop (S.pop ()))? X: Z );
   : | S.push ( x );
   . El | S.push ( ); imprimir (x );
   (| S.push ( ); mientras que (x) {(0 );
   ) | S.push ( )} (0 );
Arnauld
fuente
2

Java 8, 420 418 402 373 359 357 341 bytes

import java.util.*;s->f(s,new Stack());void f(String s,Stack<Integer>S){for(int i=0,c,t,u;i++<s.length();){if((c=s.charAt(i-1))<42&&S.peek()!=0)f(s.substring(40/c*i),S);if(c==46)System.out.println(S.peek());if(c>57)S.add(c>99?new Random().nextInt():S.peek());if(c<44|c==45|c==47){t=S.pop();u=S.pop();S.add(c<43?u*t:c<45?u+t:c<46?u-t:u/t);}}}

-2 bytes gracias a @Grimy .
-16 bytes gracias a @ceilingcat .

Pruébalo en línea.

Explicación:

import java.util.*;       // Required import for 2x Stack and Random

s->                       // Method with String parameter and no return-type
  f(s,new Stack())        //  Call the recursive function, with a new Stack

// Separated recursive method with String and Stack parameters
void f(String s,Stack<Integer>S){
  int i=0,                //  Index integer
      c,                  //  Temp integer used for the current character
      t,u;                //  Temp integers used for the peeked/popped top of the stack
  for(;i++<s.length();){  //  Loop `i` in the range [0, String-length):
    if((c=s.charAt(i-1))  //   Set `c` to the current character
        <42               //   If the character is either '(' or ')',
        &&S.peek()!=0)    //   and the top of the stack is not 0:
         f(s.substring(   //    Take the substring, either removing everything before and
            40/c*i),      //    including the "(", or keeping the string as is for ")"
           S);            //    And do a recursive call with this String
    if(c==46)             //    If the character is '.'
      System.out.println( //     Print with trailing newline:
       S.peek());         //      The peeked top of the stack
    if(c>57)              //    If the character is ':' or '~':
      S.add(c>99?         //     If the character is '~':
        new Random().nextInt()
                          //      Add a random [0,2147483647) integer to the stack
       :                  //     Else (the character is ':')
        S.peek());        //      Add the peeked top to the stack
    if(c<44|c==45|c==47)  //    If the character is '*', '+', '-', or '/':
      t=S.pop();u=S.pop();//    Pop and set the top two values to `t` and `u`
      S.add(c<43?         //     If the character is '*':
        u*t               //      Add the product of the two values to the stack
       :c<44?             //     Else-if the character is '+':
        u+t               //      Add the sum of the two values to the stack
       :c<46?             //     Else-if the character is '-':
        u-t               //      Subtract the top two values, and add it to the stack
       :                  //     Else (the character is '/'):
        u/t;}}}           //      Divide the top two values, and add it to the stack
Kevin Cruijssen
fuente
1
new Random().nextInt()es 2 más corto que (int)(Math.random()*1e5).
Grimmy
@ Grimy Ah, olvidé que tenía esa java.util.*importación para el Stack. ¡Gracias! :)
Kevin Cruijssen
@ceilingcat Gracias por -16!
Kevin Cruijssen
Esto probablemente va en contra de una o más reglas del decoro, pero si lo reemplaza new Random().nextInt()con 5todos los casos de prueba, todavía pasará.
ceilingcat
@ceilingcat Sí, pero 5no es exactamente al azar ;) Relevante xkcd
Kevin Cruijssen
2

C (gcc) para Linux x86_64, 675 643 621 613 597 432 404 399 bytes

printf();*z;*mmap();(*p)();*j(char*a){char*t=a,*n,c;for(p=0;read(0,&c,!p);t=!~c?n=j(t+9),z=mempcpy(t,L"\xf00f883Ƅ",5),*z=n-t-9,n:!c?p=*t++=233,z=t,*z=a-13-t,z+1:stpcpy(t,c-85?c-2?c-4?c-1?c-6?c-17?"PAPTYh%ld T_P^1\xc0QH\x83\xcc\bQA\xff\xd0\\AXX":"P":L"\xfef7995e":"[\xf7\xeb":"[)\xd8":"[\1\xd8":L"\xf0c70f50"))c-=41;return t;}main(){p=mmap(0,1<<20,6,34,0,0);p(strcpy(j(p),"j<X\xf\5"),0,0,0,printf);}

Pruébalo en línea!

Este es un JIT que traduce directamente las instrucciones volátiles al lenguaje de máquina x86_64 y ejecuta el código. Si su máquina no tiene la rdrandinstrucción, se puede reemplazar L"\xf0c70f50"con "Pj*X"un " PRNG menos uniforme ". Al puerto de algo que no sea Linux, reemplace las llamadas al sistema en los printf()y exit()las gotas y ajustar los parámetros a mmap().

EDITAR: esta versión llama en printf()lugar de implementar un subconjunto desde cero.

EDIT2: Los enteros compatibles ahora son de 32 bits en lugar de 64.

Un poco menos golfizado ...

printf();*z;*mmap();(*p)();
// recursive function translates Volatile commands to x86_64 instructions
*j(char*a){
  char*t=a,*n,c;
  for(p=0;read(0,&c,!p);)
    c-=41,
    t=c=='('+41?
      // cmp eax,0
      // je n-t-9
      n=j(t+9),
      z=mempcpy(t,"\x83\xf8\x00\x0f\x84",5),
      *z=n-t-9,
      n
    :
      c==')'+41?
        // jmp a-13-t
        p=*t++=233,
        z=t,
        *z=a-13-t,
        z+1
      :
        stpcpy(t,c-'~'+41?
                   c-'+'+41?
                     c-'-'+41?
                       c-'*'+41?
                         c-'/'+41?
                           c-':'+41?
                             // ; This calls printf("%ld ",%rax)
                             // push rax
                             // push r8
                             // push rsp
                             // pop  rcx
                             // push 0x20646c25
                             // push rsp
                             // pop  rdi
                             // push rax
                             // pop  rsi
                             // xor  eax, eax
                             // push rcx
                             // or   rsp, 8
                             // push rcx
                             // call r8
                             // pop  rsp
                             // pop  r8
                             // pop  rax
                             "\x50\x41\x50\x54\x59\x68\x25\x6c\x64\x20\x54\x5f\x50\x5e\x31\xc0\x51\x48\x83\xcc\x08\x51\x41\xff\xd0\x5c\x41\x58\x58"
                           :
                             // push rax
                             "\x50"
                         :
                           // pop rsi
                           // cdq  
                           // idiv esi
                           "\x5e\x99\xf7\xfe"
                       :
                         // pop rbx
                         // imul ebx
                         "\x5b\xf7\xeb"
                     :
                       // pop rbx
                       // sub eax, ebx
                       "\x5b\x29\xd8"
                   :
                     // pop rbx
                     // add eax, ebx
                     "\x5b\x01\xd8"
                 :
                   // push rax
                   // rdrand eax
                   "\x50\x0f\xc7\xf0");
  return t;
}
main(){
  p=mmap(0,1<<20,6,34,0,0);
  p(strcpy(j(p),"\x6a\x3c\x58\x0f\x05"),0,0,0,printf);
}
techo
fuente
1

Kotlin , 412 bytes

Desafortunadamente, perdí con Java, pero no quería hacerlo import java.util.Stack(y no estoy seguro de que cerraría la brecha de todos modos).

{p->var i=0
var s=List(0){0}
var c=List(0){0}
while(i<p.length){when(val o=p[i]){'~'->s+=(0..32768).random()
in "+-*/"->{val(a,b)=s.takeLast(2)
s=s.dropLast(2)+when(o){'+'->a+b
'-'->a-b
'*'->a*b
'/'->a/b
else->0}}
':'->s+=s.last()
'.'->println(s.last())
'('->{if(s.last()!=0)c+=i else{var z=0
do{if(p[i]=='(')z++else if(p[i]==')')z--
i++}while(z>0)
i--}}
')'->if(s.last()!=0)i=c.last()else c=c.dropLast(1)}
i++}}

Sin golf

{ p ->                  // open lambda: p is the code string
    var i = 0           // program counter
    var s = List(0){0}  // data stack
    var c = List(0){0}  // jump stack

    // main loop
    while(i<p.length) {
        // match on the current character
        when(val o = p[i]) {
            // add random number to end of stack
            '~' -> s += (0..32768).random()
            // if a math op...
            in "+-*/" -> {
                // pick top stack items
                val (a, b) = s.takeLast(2)
                // pop two items and then push based on op
                s = s.dropLast(2) + when(o) {
                    '+' -> a+b
                    '-' -> a-b
                    '*' -> a*b
                    '/' -> a/b
                    else -> 0  // else is required here
                }
            }
            // duplicate top stack item
            ':' -> s += s.last()
            // print top stack item
            '.' -> println(s.last())
            // open loop
            '(' -> {
                if(s.last()!=0)
                    // push to jump stack if top of data stack is nonzero
                    c+=i
                else {
                    // skip ahead
                    var z=0
                    do {
                        // seek to matching brace
                        if(p[i]=='(') z++ else if(p[i]==')') z--
                        i++
                    } while(z>0)
                    // ensure program counter doesn't go too far
                    i--
                }
            }
            // close loop
            ')' -> if(s.last()!=0) i=c.last() else c=c.dropLast(1)
        }
        // next character
        i++
    }
}

Pruébalo en línea!

caracol_
fuente