¡Intérprete de BrainFlow!

11

BrainFlow

¿Qué es BrainFlow?

BrainFlow es una extensión de BrainF ** k (BFk) con 3 comandos adicionales para mayor funcionalidad y confusión.

Que comandos

Además de los comandos BFk normales , también tenemos:

^ Salta a la celda # dependiendo del valor en la celda. Ej: Si estamos en la celda # 0 con un valor de 4, ^ nos llevará a la celda # 4.

= Establece el valor en la celda al índice de la celda. Ej: Si estamos en la celda # 4 con un valor de 0, = establecerá nuestro valor en 4.

& Establecerá el valor en la celda actual igual al valor en la celda basado en el valor en nuestra celda actual. (¡Es difícil de decir, así que aquí hay un ejemplo!) Ej: Estamos en la celda # 33 y nuestro valor actual en esta celda es 7, y estableceremos nuestro valor actual en la celda # 33 a cualquier valor que esté en la celda # 7.

Desafíos opcionales

Lograr cualquiera de los siguientes aplicará la bonificación especificada a su conteo de bytes.

Interpreter written in BrainFlow (Puede ser interpretada por la muestra y contiene al menos un ^ = o & significativo): Puntuación / 3

Interpreter written in BrainF**k: Puntuación / 2

Doesn't contain any English letters (in either upper or lower case): Puntuación - 20

Doesn't contain any of the BrainFlow / BFk commands in the interpreter itself: Puntuación - 50

Ejemplo

Un ejemplo de intérprete de Java:

import java.util.Scanner;

public class Interpreter {

    private String exp;

    private int[] values = new int[256];
    private int index = 0;

    private Scanner in;

    public Interpreter(String exp, Scanner in){
        this.exp = exp;
        this.in = in;
    }

    public void run(){
        //Reset index and values
        for(int i = 0; i < values.length; i++){
            values[i] = 0;
        }
        this.index = 0;

        System.out.println("Starting...");
        this.process(this.exp, false);
        System.out.println("\nDone.");
    }

    private void process(String str, boolean loop){
        boolean running = loop;
        do{
            for(int i = 0; i < str.length(); i++){
                switch(str.charAt(i)){
                case '>':increaseIndex();break;
                case '<':decreaseIndex();break;
                case '+':increaseValue();break;
                case '-':decreaseValue();break;
                case '[':
                    String s = str.substring(i);
                    int j = this.getClosingIndex(s);
                    if(this.values[this.index] == 0){
                        i +=j;
                        break;
                    }
                    process(s.substring(1, j), true);
                    i += j;
                    break;
                case '.':
                    int v = this.values[this.index];
                    System.out.print((char)v);
                    break;
                case ',':this.values[this.index] =  this.in.next().charAt(0);break;
                case '^':this.index = this.values[this.index];break;// Jumps to the index specified in the current cell.
                case '=':this.values[index] = this.index;break;// Sets the value at cell #x to x
                case '&':this.values[index] = this.values[this.values[index]];break;// If cell contains X, makes value of current cell equal to value in cell X
                default:
                    //Ignore others
                    break;
                }
            }
            if(this.values[this.index] == 0){
                running = false;
            }
        }while(running);
    }

    private void increaseIndex(){
        if(++this.index >= this.values.length){
            this.index = 0;
        }
    }

    private void decreaseIndex(){
        if(--this.index < 0){
            this.index = this.values.length - 1;
        }
    }

    private void increaseValue(){
        int newVal = this.values[this.index] + 1;
        if(newVal >= this.values.length){
            newVal = 0;
        }
        this.values[this.index] =  newVal;
    }

    private void decreaseValue(){
        int newVal = this.values[this.index] - 1;
        if(newVal < 0){
            newVal = this.values.length - 1;
        }
        this.values[this.index] =  newVal;
    }

    private int getClosingIndex(String str){
        int openings = 0;
        int closings = 0;
        for(int i = 0; i < str.length(); i++){
            char c = str.charAt(i);
            if(c == '['){
                openings++;
            }else if(c == ']'){
                closings++;
            }
            if(openings == closings){
                return i;
            }
        }
        return -1;
    }
}

Ni siquiera cerca del campo de golf, pero debería proporcionar un buen punto de partida.

El puntaje final más bajo gana, donde el puntaje es el número de bytes en su programa después de que se hayan tenido en cuenta las reducciones de desafío aplicables.

Pruebas

El siguiente programa BrainFlow debería imprimir la salida especificada después de leer un '+' char de stdin:

<<,++++[>++++[>++++<-]<-] Set cell #0 to a value dependent on input
>>>+[[-]&>=]+& Set every other cell to that value
[ Start loop
+^ Add one to current value and jump to that cell index
. Print the value at that cell
& Copy value from specified cell
] End loop

Salida:

ðñðòñðòðôóòñóñôóðòõóñõðôôóòñööõôöðóöðõðùõñô÷ùõóñöóùñô÷øôøõôòöõóðòöóñ÷ðõôûôòú÷úø÷öùøöùñøðùúðûðþöûñùýøðòñ
Spocot
fuente
Tenga en cuenta que & le permite esencialmente crear variables en las celdas inferiores y luego hacer referencia a ellas más adelante. Por ejemplo, si almaceno mi edad en la segunda celda y el mes en que nací en la tercera celda, y actualmente estoy en la celda 64, puedo hacerlo ++&para recuperar mi edad o +++&el mes en que nací. (Suponiendo por supuesto, la celda 64 está en el valor predeterminado de 0)
spocot
2
Creo que quieres decir 'superconjunto', no subconjunto.
28ıʇǝɥʇuʎs
@ ɐɔıʇǝɥʇuʎs Cambiado de subseta extension. Gracias por la respuesta.
spocot
la puntuación para escribir en el flujo cerebral es una mala idea: Brainfuck es un subconjunto del flujo cerebral, por lo tanto, cualquier programa Brainfuck es un programa de flujo cerebral. es como decir que un programa de c ++ tendrá mejor puntaje que un programa de C. OK, mi programa C es un programa C ++, así que ...
pseudonym117
1
¿Por qué escribir una implementación en Brainfuck tiene un beneficio menor que escribir una en Brainflow? Parece que el primero sería más desafiante, ya que es un idioma más pequeño.
Peter Olson

Respuestas:

7

Perl - 233 230 210 182 180 176 174 171 bytes

$/=$,;%d=qw(> $p++ < $p-- + $v[$p]++ - $v[$p]-- , $v[$p]=ord+getc . print+chr+$v[$p] [ while+$v[$p]{ ] } ^ $p=$v[$p] = $v[$p]=$p & $v[$p]=$v[$v[$p]]);eval$d{$_}for<>=~/./g

Simplemente tomé un intérprete mío BrainFuck existente, lo jugué al golf y agregué las funciones BrainFlow.

Actualización: Completamente reestructurado el programa para perder 28 bytes.

malkaroee
fuente
Tenga en cuenta que si fuera alimentado con una cadena de 300 "+" s, terminaría con valores no válidos. Debe realizar una comprobación de cordura% 256 después / mientras establece muchos de esos valores.
user0721090601
Creo que esto no funciona con bucles ( []). No puede evaluar carácter por carácter para eso.
nutki
¿Cómo se traducen las ventajas en paréntesis?
nutki
6

Vamos a empezar esta fiesta.

C - 408384393390380357352 bytes (aún descontando)

Compile con gccun sistema compatible con POSIX. El primer argumento es el nombre de un archivo que contiene el código de Brainflow a interpretar. Se agregaron nuevas líneas para mejorar la legibilidad.

i,p,b[9999],*k=b;unsigned char g[9999],a[30000],*d=a;main(c,v)char**v;
{read(open(v[1],0),g,9999);while(c=g[i++]){c-62||d++;c-60||d--;c-43||
(*d)++;c-45||(*d)--;c-46||putchar(*d);c==44?*d=getchar():0;c==94?d=a+*d:0;
c==61?*d=d-a:0;c==38?*d=a[*d]:0;c==93?i=*(--k):0;if(c==91)if(*d)*k++=i-1;else 
while(c=g[i++]){c==91?p++:0;if(c==93)if(p)p--;else break;}}}

Y la versión no golfista si te interesa. Avísame si ves algún error.

int i, depth, buffer[9999], *stack = buffer;
unsigned char c, program[9999], array[30000], *data = array;

main(int argc, char **argv)
{
    read(open(argv[1], 0), program, 9999);

    while(c = program[i++]){
        if (c=='>') data++;
        if (c=='<') data--;
        if (c=='+') (*data)++;
        if (c=='-') (*data)--;
        if (c=='.') putchar(*data);
        if (c==',') *data=getchar();
        if (c=='^') data=array+*data;
        if (c=='=') *data=data-array;
        if (c=='&') *data=array[*data];
        if (c==']') i=*(--stack);
        if (c=='[')
            if (*data) *stack++=i-1;
            else while (c=program[i++]) {
                    if (c=='[') depth++;
                    if (c==']') if (depth) depth--; else break;
            }
    }
}

Actualizaciones:

  • Gracias por los comentarios iniciales que me permitieron eliminar 24 bytes adicionales.

  • Error de señal solucionado. Se agregaron otros 9 bytes.

  • Guardado otros 3 bytes por sugerencias de es1024.

  • Se guardaron otros 10 bytes por más sugerencias de es1024.

  • Recién recordé que las variables globales se inicializan a 0. Cambiaron de fread y fopen para leer y abrir. Guardado 23 bytes.

  • No es necesario establecer un terminador nulo en el programa porque el búfer ya está inicializado a cero. Guardado 5 bytes.
O por
fuente
2
Creo que el if () y el; podría reemplazarse con?: y guardar algunos caracteres.
Jerry Jeremiah
2
Los literales de caracteres se pueden reemplazar con sus equivalentes ASCII para guardar caracteres.
seudónimo117
1
@Orby Parece que no procesa los caracteres de entrada correctamente. Debe convertirlos a la representación ascii y almacenarlos. Aparte de eso funciona.
spocot
1
Se puede reemplazar main(int c,char**v){con main(c,v)char**v;{y guardar dos bytes, así como movimiento int i=0,p=0,b[9999],*k=b;de fuera de la función, y soltar el int de salvar cuatro bytes. if (c==91)También tiene un espacio innecesario.
es1024
1
También puede reemplazar la mayoría, si no todos, c==[number]?[action]:0;con c-[number]||[action]. ( c-[number]es equivalente c != [number]y if(p)p--;conp&&p--;
es1024
6

AppleScript 972 670

Sobre todo golf, aunque no hay forma de que gane. No sé por qué no pensé en construir un script como lo hizo Perl (aunque todavía no ganará jaja). Probablemente, esto podría mejorarse más reajustando cómo los valores del índice son un poco mejores, AppleScript es frustrantemente (para este tipo de cosas) un lenguaje de índice 1.

Simplemente pase el código de BrainFlow a e (). Tenga en cuenta que los comandos ASCII de AppleScript utilizan la codificación MacOSRoman, por lo que si bien la salida aparecerá diferente, es correcto observar su representación binaria. Deberá tener eso en cuenta al pasar los caracteres ASCII superiores a través de los comandos ",".

on e(x)
set d to {"", "set b'sitem(i+1)to(b'sitem(i+1)+1)mod 256", "set b'sitem(i+1)to(b'sitem(i+1)+255)mod 256", "set i to(i+1)mod 256", "set i to(i+255)mod 256", "repeat while b'sitem(i+1)≠0", "end", "set o to o&(ASCII character b'sitem(i+1))", "display dialog \"\"default answer\"\"
set b'sitem(i+1)to ASCII number result'stext returned'stext1", "set i to b'sitem(i+1)", "set b'sitem(i+1)to i", "set b'sitem(i+1)to b'sitem(b'sitem(i+1)+1)"}
set s to "set i to 0
set b to{}
repeat 256
set b'send to 0
end
set o to  \"\"
"  
repeat with c in x'stext
set s to s&d'sitem((offset of c in "+-><[].,^=&")+1)&"
"
end
set s to s&"return o"
return run script s
end

(porque ¿qué le importa más a su cerebro que escribir un intérprete de flujo mental / flujo en otro idioma que le jode demasiado la cabeza?

usuario0721090601
fuente