Traductor de Malbolge a Malbolge normalizado

12

En esta tarea, escribirá un programa / función que toma un programa Malbolge normalizado y genera el programa Malbolge resultante . (¡Esta es una herramienta secreta que utilizan todos los programadores de Malbolge!)

Entrada

Una estructura de datos que (de alguna manera) representa un programa Malbolge normalizado.

Salida

Una estructura de datos que representa el programa Malbolge resultante.

Ejemplos

jpoo*pjoooop*ojoopoo*ojoooooppjoivvvo/i<ivivi<vvvvvvvvvvvvvoji
(=BA#9"=<;:3y7x54-21q/p-,+*)"!h%B0/.~P<<:(8&66#"!~}|{zyxwvugJ%

jjjj*<jjjj*<v
('&%#^"!~}{XE

jjjjjjjjjjjjjjjjjjjjjjj*<jjjjjjjjjjjjjjjjjjjjjjjj*<v
('&%$#"!~}|{zyxwvutsrqpnKmlkjihgfedcba`_^]\[ZYXWVT1|

Como convertir

Iterar sobre el programa Malbolge normalizado, realizando los siguientes pasos para cada personaje:

  1. Reemplace los caracteres en la cadena *jpovi</con el carácter correspondiente en '(>DQbcu. (Es decir, mapa *a ', ja (, etc.)

  2. Luego reste la posición actual del contador del programa (es decir, el número de caracteres antes del actual) del código ASCII del personaje.

  3. Si el código ASCII resultante es menor que 33, increméntelo en 94 y repita hasta que sea al menos 33.

  4. Agregue el carácter resultante a la salida.

Reglas

  • Este es un concurso de ; la respuesta más corta gana.
  • No hay lagunas estándar por favor.
  • Los métodos de E / S predeterminados están permitidos.
  • La entrada solo contendrá los caracteres *jpovi</.
Ilmari Karonen
fuente
44
¿La entrada contiene solo caracteres de " *jpovi</"?
Joel
77
No entiendo qué "Entonces, menos la posición". medio. Probablemente podría resolverlo a partir del pseudocódigo, pero la explicación debería ser autónoma.
xnor
1
" Si bien el código ASCII de las representaciones temporales de Malbolge es menor que 33, incremente el carácter por 94. " ¿Qué quiere decir con esto? Cómo entendí el desafío es: 1) personajes del mapa; 2) convertir a valor unicode; 3) disminuya cada uno por contador de programa (ahora tenemos lo que llama el 'código ASCII' de representaciones temporales de Malbolge '); 4) si algún valor es menor que 33, incremente eso en 94; 5) convertir estos valores nuevamente en caracteres. Pero usando este enfoque, la salida claramente no es correcta. Entonces, ¿podría aclarar lo que quiere decir con esto para entradas de más de 33 caracteres?
Kevin Cruijssen
1
a: if ascii_code(temporary Malbolge representation) < 33: char := char + 94; goto a;
1
Felizmente daré una recompensa a cualquiera que pueda escribir una de estas cosas en Malbolge :)
JDL

Respuestas:

4

Jalea , 29 22 bytes

Oị“%þV DCµ2®  ‘_JịØṖḊ¤

Pruébalo en línea!

Un enlace monádico que toma una cadena Jelly como argumento y devuelve una cadena Jelly.

¡Gracias a @JonathanAllan por guardar 2 bytes!

Explicación

O                      | Convert to Unicode code points
 ị“%þV DCµ2®  ‘        | Index into compressed integer list [37, 31, 86, 32, 68, 67, 9, 50, 8, 32, 32] (note the 32s are never actually used because the input mod 11 will be one of 1,2,3,5,6,7,8,9)
               _J      | Subtract position of character in original string
                 ị   ¤ | Index into the following as a nilad:
                  ØṖ   | - Printable ASCII characters
                    Ḋ  | - With the first character (space) removed
Nick Kennedy
fuente
..._J‘ịØṖḊ¤ahorra un byte.
Jonathan Allan
@ JonathanAllan gracias, buena llamada!
Nick Kennedy el
2
ah, y podemos aumentar dentro de nuestra búsqueda>. < guardar otro byte:Oị“%þV DCµ2® ‘_JịØṖḊ¤
Jonathan Allan
6

Python 3 , 82 bytes

p=0
for c in input():print(end=chr((b"de{#0ABT"["*jpovi<".find(c)]-p)%94+33));p+=1

Pruébalo en línea!

Gracias a @Joel por reemplazar los caracteres feos no imprimibles en la cadena de bytes con caracteres imprimibles.

Estoy buscando una cadena de modulación para reemplazar "*jpovi<".find(c), pero no creo que haya una más corta, y una búsqueda de fuerza bruta no exhaustiva no ha encontrado nada hasta ahora.

82 bytes

f=lambda s,p=0:s and chr((b"de{#0ABT"["*jpovi<".find(s[0])]-p)%94+33)+f(s[1:],p+1)

Pruébalo en línea!

xnor
fuente
Los caracteres ASCII no imprimibles pueden compensarse con 94 para convertirse en imprimibles para una mejor legibilidad.
Joel
Puede intentar encontrar una función matemática para reemplazar la asignación b"de{#0ABT"["*jpovi<".find(c)]si tiene un programa para eso.
Joel
1
@ Joo Desafortunadamente, creo que el mapeo es un espacio de búsqueda demasiado amplio para una función aritmética, al menos con las herramientas que tengo. Yo sólo había estado buscando modulo cadenas como x%84%15%7para la mitad derecha de la asignación, pero creo que puedo reciclar algo de código que escribí para otro reto para buscar incluyendo *y /términos.
xnor
@Joel No estoy encontrando nada estilo mod-chain para el lado derecho usando %y *( //en Python 3 probablemente no valga la pena). De hecho, nada ha coincidido con los primeros 6 de 7 valores. Esperaba que esto funcionara porque una estimación aproximada de la entropía dice que probablemente haya suficientes expresiones que terminen en% 7`, pero está cerca. Y tal vez estas cadenas dan salidas que están lejos de estar distribuidas de manera uniforme, especialmente porque una vez que dos entradas colapsan al mismo valor, no pueden separarse más operaciones. Lo que estoy intentando todavía es demasiado tonto para buscar la expresión más amplia, pero si tienes alguna idea, ve por ella.
xnor
Creo que probablemente se necesita un mejor algoritmo para entradas arbitrarias como map(ord, "*jpovi<"). Si la salida no conserva el orden para la mayoría de las entradas (es decir, f(m)>=f(n)si m>=n), es probable que se necesiten algunas constantes cuidadosamente elaboradas para %y *es probable que una búsqueda de fuerza bruta produzca un resultado positivo.
Joel
6

Malbolge Unshackled (variante de rotación de 20 trits), 7,784e6 bytes

El tamaño de esta respuesta excede el tamaño máximo de programa postable (eh), por lo que el código se encuentra en mi repositorio de GitHub .

¿Cómo ejecutar esto?

Esto podría ser una parte difícil, porque el ingenuo intérprete de Haskell tardará siglos en ejecutarlo. TIO tiene un intérprete decente Malbogle Unshackled, pero lamentablemente no podré usarlo (limitaciones).

La mejor que pude encontrar es la variante de ancho de rotación fija de 20 trits, que funciona muy bien, convirtiendo 0,5 caracteres por segundo .

Para hacer que el intérprete sea un poco más rápido, eliminé todas las comprobaciones del intérprete Malbolge Unshackled de Matthias Lutter.

Mi versión modificada puede correr alrededor de un 6,3% más rápido.

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* translation = "5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!pJS72Fh"
        "OA1CB6v^=I_0/8|jsb9m<.TVac`uY*MK'X~xDl}REokN:#?G\"i@";

typedef struct Word {
    unsigned int area;
    unsigned int high;
    unsigned int low;
} Word;

void word2string(Word w, char* s, int min_length) {
    if (!s) return;
    if (min_length < 1) min_length = 1;
    if (min_length > 20) min_length = 20;
    s[0] = (w.area%3) + '0';
    s[1] = 't';
    char tmp[20];
    int i;
    for (i=0;i<10;i++) {
        tmp[19-i] = (w.low % 3) + '0';
        w.low /= 3;
    }
    for (i=0;i<10;i++) {
        tmp[9-i] = (w.high % 3) + '0';
        w.high /= 3;
    }
    i = 0;
    while (tmp[i] == s[0] && i < 20 - min_length) i++;
    int j = 2;
    while (i < 20) {
        s[j] = tmp[i];
        i++;
        j++;
    }
    s[j] = 0;
}

unsigned int crazy_low(unsigned int a, unsigned int d){
    unsigned int crz[] = {1,0,0,1,0,2,2,2,1};
    int position = 0;
    unsigned int output = 0;
    while (position < 10){
        unsigned int i = a%3;
        unsigned int j = d%3;
        unsigned int out = crz[i+3*j];
        unsigned int multiple = 1;
        int k;
        for (k=0;k<position;k++)
            multiple *= 3;
        output += multiple*out;
        a /= 3;
        d /= 3;
        position++;
    }
    return output;
}

Word zero() {
    Word result = {0, 0, 0};
    return result;
}

Word increment(Word d) {
    d.low++;
    if (d.low >= 59049) {
        d.low = 0;
        d.high++;
        if (d.high >= 59049) {
            fprintf(stderr,"error: overflow\n");
            exit(1);
        }
    }
    return d;
}

Word decrement(Word d) {
    if (d.low == 0) {
        d.low = 59048;
        d.high--;
    }else{
        d.low--;
    }
    return d;
}

Word crazy(Word a, Word d){
    Word output;
    unsigned int crz[] = {1,0,0,1,0,2,2,2,1};
    output.area = crz[a.area+3*d.area];
    output.high = crazy_low(a.high, d.high);
    output.low = crazy_low(a.low, d.low);
    return output;
}

Word rotate_r(Word d){
    unsigned int carry_h = d.high%3;
    unsigned int carry_l = d.low%3;
    d.high = 19683 * carry_l + d.high / 3;
    d.low = 19683 * carry_h + d.low / 3;
    return d;
}

// last_initialized: if set, use to fill newly generated memory with preinitial values...
Word* ptr_to(Word** mem[], Word d, unsigned int last_initialized) {
    if ((mem[d.area])[d.high]) {
        return &(((mem[d.area])[d.high])[d.low]);
    }
    (mem[d.area])[d.high] = (Word*)malloc(59049 * sizeof(Word));
    if (!(mem[d.area])[d.high]) {
        fprintf(stderr,"error: out of memory.\n");
        exit(1);
    }
    if (last_initialized) {
        Word repitition[6];
        repitition[(last_initialized-1) % 6] =
                ((mem[0])[(last_initialized-1) / 59049])
                    [(last_initialized-1) % 59049];
        repitition[(last_initialized) % 6] =
                ((mem[0])[last_initialized / 59049])
                    [last_initialized % 59049];
        unsigned int i;
        for (i=0;i<6;i++) {
            repitition[(last_initialized+1+i) % 6] =
                    crazy(repitition[(last_initialized+i) % 6],
                        repitition[(last_initialized-1+i) % 6]);
        }
        unsigned int offset = (59049*d.high) % 6;
        i = 0;
        while (1){
            ((mem[d.area])[d.high])[i] = repitition[(i+offset)%6];
            if (i == 59048) {
                break;
            }
            i++;
        }
    }
    return &(((mem[d.area])[d.high])[d.low]);
}

unsigned int get_instruction(Word** mem[], Word c,
        unsigned int last_initialized,
        int ignore_invalid) {
    Word* instr = ptr_to(mem, c, last_initialized);
    unsigned int instruction = instr->low;
    instruction = (instruction+c.low + 59049 * c.high
            + (c.area==1?52:(c.area==2?10:0)))%94;
    return instruction;
}

int main(int argc, char* argv[]) {
    Word** memory[3];
    int i,j;
    for (i=0; i<3; i++) {
        memory[i] = (Word**)malloc(59049 * sizeof(Word*));
        if (!memory) {
            fprintf(stderr,"not enough memory.\n");
            return 1;
        }
        for (j=0; j<59049; j++) {
            (memory[i])[j] = 0;
        }
    }
    Word a, c, d;
    unsigned int result;
    FILE* file;
    if (argc < 2) {
        // read program code from STDIN
        file = stdin;
    }else{
        file = fopen(argv[1],"rb");
    }
    if (file == NULL) {
        fprintf(stderr, "File not found: %s\n",argv[1]);
        return 1;
    }
    a = zero();
    c = zero();
    d = zero();
    result = 0;
    while (!feof(file)){
        unsigned int instr;
        Word* cell = ptr_to(memory, d, 0);
        (*cell) = zero();
        result = fread(&cell->low,1,1,file);
        if (result > 1)
            return 1;
        if (result == 0 || cell->low == 0x1a || cell->low == 0x04)
            break;
        instr = (cell->low + d.low + 59049*d.high)%94;
        if (cell->low == ' ' || cell->low == '\t' || cell->low == '\r'
                || cell->low == '\n');
        else if (cell->low >= 33 && cell->low < 127 &&
                (instr == 4 || instr == 5 || instr == 23 || instr == 39
                    || instr == 40 || instr == 62 || instr == 68
                    || instr == 81)) {
            d = increment(d);
        }
    }
    if (file != stdin) {
        fclose(file);
    }
    unsigned int last_initialized = 0;
    while (1){
        *ptr_to(memory, d, 0) = crazy(*ptr_to(memory, decrement(d), 0),
                *ptr_to(memory, decrement(decrement(d)), 0));
        last_initialized = d.low + 59049*d.high;
        if (d.low == 59048) {
            break;
        }
        d = increment(d);
    }
    d = zero();

    unsigned int step = 0;
    while (1) {
        unsigned int instruction = get_instruction(memory, c,
                last_initialized, 0);
        step++;
        switch (instruction){
            case 4:
                c = *ptr_to(memory,d,last_initialized);
                break;
            case 5:
                if (!a.area) {
                    printf("%c",(char)(a.low + 59049*a.high));
                }else if (a.area == 2 && a.low == 59047
                        && a.high == 59048) {
                    printf("\n");
                }
                break;
            case 23:
                a = zero();
                a.low = getchar();
                if (a.low == EOF) {
                    a.low = 59048;
                    a.high = 59048;
                    a.area = 2;
                }else if (a.low == '\n'){
                    a.low = 59047;
                    a.high = 59048;
                    a.area = 2;
                }
                break;
            case 39:
                a = (*ptr_to(memory,d,last_initialized)
                        = rotate_r(*ptr_to(memory,d,last_initialized)));
                break;
            case 40:
                d = *ptr_to(memory,d,last_initialized);
                break;
            case 62:
                a = (*ptr_to(memory,d,last_initialized)
                        = crazy(a, *ptr_to(memory,d,last_initialized)));
                break;
            case 81:
                return 0;
            case 68:
            default:
                break;
        }

        Word* mem_c = ptr_to(memory, c, last_initialized);
        mem_c->low = translation[mem_c->low - 33];

        c = increment(c);
        d = increment(d);
    }
    return 0;
}

¡Esta funcionando!

Esta funcionando

Krzysztof Szewczyk
fuente
2
Esto es una locura.
MilkyWay90
Para los transeúntes, el recuento de bytes es 7.784MB, no 7.784GB. Al principio, interpreté la coma como una agrupación de los miles en lugar de un punto decimal.
Papa44
@ Potato44 usamos coma como separador decimal en Polonia, está prohibido usar punto como tal.
Krzysztof Szewczyk
5

Python 3 , 84 83 bytes

f=lambda p,i=0:p and chr(126-(i+b"WV@:-zyg"["*jpovi<".find(p[0])])%94)+f(p[1:],i+1)

Pruébalo en línea!

Esto es principalmente un problema matemático sobre la simplificación de la computación, más algo de golf después de hacer las matemáticas. La versión no codificada del código se muestra a continuación.

Versión no recursiva no golfista

def convert(prog):
    offsets = dict(zip("*jpovi</", [87, 86, 64, 58, 45, 122, 121, 103]))  # ASCII encoded to "WV@:-zyg"
    output = ""
    for pos, c in enumerate(prog):
        output += chr(126-(offsets[c]+pos)%94)
    return output

Pruébalo en línea!

Joel
fuente
5

JavaScript (Node.js) , 69 bytes

s=>(B=Buffer)(s).map((c,i)=>33+(B(" #{T BAe0d")[c%11]+94-i%94)%94)+''

Pruébalo en línea!

¿Cómo?

[1..9]11

 char. | ASCII code | mod 11
-------+------------+--------
  '*'  |      42    |   9
  'j'  |     106    |   7
  'p'  |     112    |   2
  'o'  |     111    |   1
  'v'  |     118    |   8
  'i'  |     105    |   6
  '<'  |      60    |   5
  '/'  |      47    |   3
Arnauld
fuente
3

05AB1E , 32 31 23 22 bytes

žQ¦•4¡ˆ¶ü]₁η₃•₃вIÇèā-è

-8 bytes creando un puerto de la respuesta Jelly de NickKennedy , ¡así que asegúrate de votarlo!
-1 byte gracias a @Grimy.

Salidas como una lista de caracteres.

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

   4¡ˆ¶ü]₁η₃•          # Push compressed integer 82767635194143615015
              ₃в        # Converted to base-95 as list: [1,36,30,85,0,67,66,8,49,7,0]
                IÇ      # Push the input and convert each character to its unicode value
                  è     # Index each into the list we created
                   ā    # Push an integer list in the range [0, length] 
                        # (without popping the list itself)
                    -   # Subtract it from the previous list
žQ                      # Push builtin with all printable ASCII characters,
  ¦                     # and remove the leading space
                     è  # Index the values of the list into the ASCII characters
                        # (after which the result is output implicitly)

Vea esta sugerencia mía 05AB1E (sección ¿Cómo comprimir enteros grandes? Y ¿Cómo comprimir listas enteras? ) Para comprender por qué •4¡ˆ¶ü]₁η₃•es 82767635194143615015y •4¡ˆ¶ü]₁η₃•₃вes [1,36,30,85,0,67,66,8,49,7,0].

Kevin Cruijssen
fuente
•1ÃQWý₂Ýδ9•86в->•4¡ˆ¶ü]₁η₃•₃в
Grimmy
@Grimy Gracias :)
Kevin Cruijssen
2

Perl 5 ( -p), 53 , 51 bytes

guardar 2 bytes, usar en de{#0ABTlugar de '(>DQbcupara que 61ya no sea necesario

y;*jpovi</;de{#0ABT;;s/./chr 33+(-"@-"+ord$&)%94/ge

TIO

la primera respuesta fue

y;*jpovi</;'(>DQbcu;;s/./chr 33+(61-"@-"+ord$&)%94/ge

TIO

Nahuel Fouilleul
fuente
2

Japt , 24 23 bytes

Solución de jalea del puerto de Nick

;£EÅgYn" #T BA0 "cXc

Intentalo

;£EÅgYn"..."cXc     :Implicit input of string
 £                  :Map each character X at 0-based index Y
; E                 :ASCII
   Å                :Slice of the first character (space)
    g               :Get character at index
     Y              :  Increment Y
      n             :  Subtract from
       "..."        :    Literal string (Codepoints: 32,35,29,84,32,66,65,7,48,6,32)
            c       :    Codepoint at index
             Xc     :      Codepoint of X
Lanudo
fuente
1

Retina 0.8.2 , 50 bytes

T`*j\p\ovi</`'(>DQbcu
.
$.`$* $&¶
+T`!p`~_p` .¶
¶

Pruébalo en línea! El enlace incluye casos de prueba. Explicación:

T`*j\p\ovi</`'(>DQbcu

Realice la transliteración como se describe en la pregunta. p(descrito a continuación) y otienen un significado especial para Transliterate, por lo que deben ser citados.

.
$.`$* $&¶

Enumere cada carácter en su propia línea, precedido por un número de espacios de acuerdo con su índice, es decir, cuál sería el contador del programa.

+T`!p`~_p` .¶

Disminuya cíclicamente repetidamente el último carácter en cada línea, eliminando el espacio anterior cada vez, hasta que se hayan eliminado todos los espacios. Los pstands para ASCII imprimible es decir -~, sin embargo, quieren que el !asignar a ~fin de que es transcrito primero, y luego la _hace que el espacio en el partido se va a eliminar, mientras que los caracteres restantes consiguen transliterados un código de carácter a la vez.

Únete a todos los personajes de nuevo juntos.

Neil
fuente
1

Carbón , 23 bytes

⭆S§Φγμ⁻℅§ #{T BAe0d ℅ικ

Pruébalo en línea! El enlace es a la versión detallada del código. Puerto de la respuesta de JavaScript de @ Arnauld. Explicación:

 S                      Input string
⭆                       Map over characters and join
                     ι  Current character
                    ℅   ASCII code
        §               Cyclically indexed into
          #{T BAe0d     Literal string ` #{T BAe0d `
       ℅                ASCII code
      ⁻                 Subtract
                      κ Current index
  §                     Cyclically indexed into
    γ                   Printable ASCII
   Φ                    Filtered on
     μ                  Inner index (i.e. skip initial space)
                        Implicitly print
Neil
fuente
1

Haskell , 135 bytes

t=h"*jpovi</"(fromEnum<$>"'(>DQbcu")
h(x:m)(y:n)i|i==x=y|1<2=h m n i
a n|n<33=a(n+94)|1<2=n
f=(toEnum.a<$>).(zipWith(+)[0,-1..]).(t<$>)

Pruébalo en línea!

david
fuente