Traduttore normalizzato da Malbolge a Malbolge


12

In questa attività, verrà scritto un programma / funzione che accetta un programma Malbolge normalizzato e genera il programma Malbolge risultante . (Questo è uno strumento segreto che tutti i programmatori Malbolge stanno usando!)

Ingresso

Una struttura di dati che (in qualche modo) rappresenta un programma Malbolge normalizzato.

Produzione

Una struttura di dati che rappresenta il programma Malbolge risultante.

Esempi

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|

Come convertire

Scorrere il programma Malbolge normalizzato, eseguendo i seguenti passaggi per ciascun personaggio:

  1. Sostituisci i caratteri nella stringa *jpovi</con il carattere corrispondente in '(>DQbcu. (Cioè, mappa *a ', ja (e così via.)

  2. Quindi sottrarre la posizione corrente del contatore del programma (ovvero il numero di caratteri prima di quello corrente) dal codice ASCII del personaggio.

  3. Se il codice ASCII risultante è inferiore a 33, aumentalo di 94 e ripeti fino a quando non è almeno 33.

  4. Aggiungi il carattere risultante all'output.

Regole

  • Questa è una gara di ; vince la risposta più breve.
  • Nessuna scappatoia standard per favore.
  • Sono consentiti i metodi I / O predefiniti.
  • L'input conterrà solo i caratteri *jpovi</.

4
L'input contiene solo caratteri di " *jpovi</"?
Gioele,

7
Non capisco cosa "Quindi, meno la posizione". si intende. Probabilmente potrei capirlo dallo pseudocodice, ma la spiegazione dovrebbe essere autonoma.
xnor

1
" Mentre il codice ASCII delle rappresentazioni temporanee di Malbolge è inferiore a 33, incrementa il carattere del 94. " Cosa intendi con questo? Come ho capito la sfida è: 1) personaggi della mappa; 2) converti in valore unicode; 3) diminuisci ciascuno per contatore del programma (ora abbiamo quello che tu chiami "codice ASCII" delle rappresentazioni di Malbolge temporanee); 4) se qualsiasi valore è inferiore a 33, incrementarlo di 94; 5) convertire questi valori in caratteri. Ma usando questo approccio l'output chiaramente non è corretto .. Quindi potresti chiarire cosa intendi con questo per input più lunghi di 33 caratteri?
Kevin Cruijssen,

1
a: if ascii_code(temporary Malbolge representation) < 33: char := char + 94; goto a;

1
Darò felicemente una taglia a chiunque possa scrivere una di queste cose in Malbolge :)
JDL

Risposte:


4

Gelatina , 29 22 byte

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

Provalo online!

Un collegamento monadico che prende una stringa Jelly come argomento e restituisce una stringa Jelly.

Grazie a @JonathanAllan per aver salvato 2 byte!

Spiegazione

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

..._J‘ịØṖḊ¤salva un byte.
Jonathan Allan,

@JonathanAllan grazie, bella chiamata!
Nick Kennedy,

2
oh, e possiamo incrementare all'interno della nostra ricerca>. < salvando un altro byte:Oị“%þV DCµ2® ‘_JịØṖḊ¤
Jonathan Allan,

6

Python 3 , 82 byte

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

Provalo online!

Grazie a @Joel per aver sostituito i brutti personaggi non stampabili nella stringa con quelli stampabili.

Sto cercando una mod-chain da sostituire "*jpovi<".find(c), ma non credo che ce ne sia una più breve, e una ricerca non esaustiva sulla forza bruta non ha trovato nulla finora.

82 byte

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

Provalo online!


I caratteri ASCII non stampabili possono essere sfalsati di 94 per essere trasformati in stampabili per una migliore leggibilità.
Gioele,

Potresti provare a trovare una funzione matematica per sostituire la mappatura b"de{#0ABT"["*jpovi<".find(c)]se hai un programma per quello.
Gioele,

1
@Joel Sfortunatamente, penso che la mappatura sia uno spazio di ricerca troppo ampio per una funzione aritmetica, almeno con gli strumenti che ho. Avevo appena cercato catene di moduli come x%84%15%7per la metà giusta della mappatura, ma penso di poter riciclare del codice che ho scritto per un'altra sfida da cercare, inclusi termini *e /termini.
xnor

@Joel Non trovo nulla di mod-chain-style per il lato destro usando %e *( //in Python 3 probabilmente non ne vale la pena.) In realtà, nulla ha eguagliato i primi 6 di 7 valori. Speravo che funzionasse perché una stima approssimativa dell'entropia dice che probabilmente ci sono abbastanza espressioni che terminano in% 7`, ma è vicino. E forse queste catene forniscono output tutt'altro che distribuiti uniformemente, soprattutto perché una volta che due input collassano allo stesso valore, nessuna ulteriore operazione può separarli. Le cose che sto provando sono ancora troppo stupide per cercare l'espressione più grande, ma se hai qualche idea, provaci.
xnor

Penso che sia probabilmente necessario un algoritmo migliore per input arbitrari come map(ord, "*jpovi<"). Se l'output non mantiene l'ordine per la maggior parte degli input (cioè f(m)>=f(n)se m>=n), alcune costanti accuratamente realizzate per %e *sono probabilmente necessarie e è improbabile che una ricerca di forza bruta produca un risultato positivo.
Gioele,

6

Malbolge Unshackled (variante a rotazione da 20 trit), 7.784e6 byte

Le dimensioni di questa risposta superano le dimensioni massime del programma (eh), quindi il codice si trova nel mio repository GitHub .

Come eseguirlo?

Questa potrebbe essere una parte difficile, perché l'ingenuo interprete di Haskell impiegherà anni e secoli per eseguire questo. TIO ha un discreto interprete Malbogle Unshackled, ma purtroppo non sarò in grado di usarlo (limitazioni).

La migliore che ho trovato è la variante con larghezza di rotazione fissa di 20 trit, che funziona molto bene, convertendo 0,5 caratteri al secondo .

Per rendere l'interprete un po 'più veloce, ho rimosso tutti i controlli dall'interprete Malbolge Unshackled di Matthias Lutter.

La mia versione modificata può essere più veloce del 6,3% circa.

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

Sta funzionando!

Sta funzionando


2
Questo è semplicemente folle.
MilkyWay90

Per i passanti, il conteggio dei byte è 7,784 MB, non 7,784 GB. Ho interpretato la virgola come inizialmente raggruppando le migliaia anziché un punto decimale.
Potato44

@ Potato44 usiamo la virgola come separatore decimale in Polonia, l'uso del punto in quanto tale è proibito.
Krzysztof Szewczyk,

5

Python 3 , 84 83 byte

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

Provalo online!

Questo è principalmente un problema di matematica sulla semplificazione del calcolo, oltre a un po 'di golf dopo aver fatto la matematica. La versione non modificata del codice è mostrata di seguito.

Versione non rigata, non ricorsiva

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

Provalo online!


5

JavaScript (Node.js) , 69 byte

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

Provalo online!

Come?

[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


3

05AB1E , 32 31 23 22 byte

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

-8 byte creando una porta della risposta Jelly di NickKennedy , quindi assicurati di votarlo !!
-1 byte grazie a @Grimy.

Emette come un elenco di caratteri.

Provalo online o verifica tutti i casi di test .

Spiegazione:

   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)

Vedi questo mio suggerimento 05AB1E (sezione Come comprimere numeri interi grandi? E Come comprimere gli elenchi numeri interi? ) Per capire perché •4¡ˆ¶ü]₁η₃•è 82767635194143615015ed •4¡ˆ¶ü]₁η₃•₃вè [1,36,30,85,0,67,66,8,49,7,0].


•1ÃQWý₂Ýδ9•86в->•4¡ˆ¶ü]₁η₃•₃в
Grimmy,

@Grimy Thanks :)
Kevin Cruijssen,

2

Perl 5 ( -p), 53 , 51 byte

risparmiando 2 byte, usando de{#0ABTinvece di '(>DQbcucosì 61non più necessario

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

TIO

la prima risposta è stata

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

TIO


2

Japt , 24 23 byte

Soluzione Jelly di Port of Nick

;£EÅgYn" #T BA0 "cXc

Provalo

;£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

1

Retina 0.8.2 , 50 byte

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

Provalo online! Il link include casi di test. Spiegazione:

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

Fai la traslitterazione come descritto nella domanda. p(descritto di seguito) e ohanno un significato speciale per la Triscrittura, quindi devono essere citati.

.
$.`$* $&¶

Elenca ogni carattere sulla sua riga, preceduto da un numero di spazi in base al suo indice, ovvero quale sarebbe il contatore del programma.

+T`!p`~_p` .¶

Decrementa ripetutamente ciclicamente l'ultimo carattere su ogni riga, cancellando ogni volta lo spazio precedente, fino a quando tutti gli spazi non sono stati eliminati. È l' pacronimo di ASCII stampabile -~, vale a dire , tuttavia vogliamo che si mappi !in ~modo che sia prima traslitterato, e quindi _causi l'eliminazione dello spazio nella corrispondenza , mentre i caratteri rimanenti vengono traslitterati un codice di carattere alla volta.

Unisci tutti i personaggi di nuovo insieme.


1

Carbone , 23 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. La risposta JavaScript di Port of @ Arnauld. Spiegazione:

 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


1

Haskell , 135 byte

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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.