Normalisierter Übersetzer von Malbolge zu Malbolge

12

In dieser Aufgabe schreiben Sie ein Programm / eine Funktion, die ein normalisiertes Malbolge- Programm verwendet und das resultierende Malbolge- Programm ausgibt . (Dies ist ein geheimes Tool, das alle Malbolge-Programmierer verwenden!)

Eingang

Eine Datenstruktur, die (irgendwie) ein normalisiertes Malbolge-Programm darstellt.

Ausgabe

Eine Datenstruktur, die das resultierende Malbolge-Programm darstellt.

Beispiele

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|

Wie konvertiere ich?

Durchlaufen Sie das normalisierte Malbolge-Programm und führen Sie die folgenden Schritte für jedes Zeichen aus:

  1. Ersetzen Sie die Zeichen in der Zeichenfolge *jpovi</durch das entsprechende Zeichen in '(>DQbcu. (Das heißt, Karte *zu ', jzu (und so weiter.)

  2. Subtrahieren Sie dann die aktuelle Position des Programmzählers (dh die Anzahl der Zeichen vor dem aktuellen) vom ASCII-Code des Zeichens.

  3. Wenn der resultierende ASCII-Code kleiner als 33 ist, erhöhen Sie ihn um 94 und wiederholen Sie den Vorgang, bis er mindestens 33 beträgt.

  4. Hängen Sie das resultierende Zeichen an die Ausgabe an.

Regeln

  • Dies ist ein Wettbewerb; Die kürzeste Antwort gewinnt.
  • Bitte keine Standardlücken .
  • Die Standard-E / A-Methoden sind zulässig.
  • Die Eingabe enthält nur die Zeichen *jpovi</.
Ilmari Karonen
quelle
4
Enthält die Eingabe nur Zeichen von " *jpovi</"?
Joel
7
Ich verstehe nicht was "Dann, abzüglich der Position." meint. Ich könnte es wahrscheinlich aus dem Pseudocode herausfinden, aber die Erklärung sollte in sich geschlossen sein.
xnor
1
" Während der ASCII-Code der temporären Malbolge-Darstellungen kleiner als 33 ist, erhöhen Sie das Zeichen um 94. " Was meinen Sie damit? Wie ich die Herausforderung verstanden habe, ist: 1) Kartenzeichen; 2) in Unicode-Wert konvertieren; 3) verringern Sie jeweils um den Programmzähler (wir haben jetzt den sogenannten ASCII-Code 'temporäre Malbolge-Darstellungen'); 4) Wenn ein Wert kleiner als 33 ist, erhöhen Sie diesen um 94; 5) Konvertieren Sie diese Werte zurück in Zeichen. Bei diesem Ansatz ist die Ausgabe jedoch eindeutig nicht korrekt. Können Sie also klarstellen, was Sie damit für Eingaben mit mehr als 33 Zeichen meinen?
Kevin Cruijssen
1
a: if ascii_code(temporary Malbolge representation) < 33: char := char + 94; goto a;
1
Ich gebe gerne ein Kopfgeld an jeden, der eines dieser Dinge in Malbolge schreiben kann :)
JDL

Antworten:

4

Gelee , 29 22 Bytes

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

Probieren Sie es online aus!

Eine monadische Verbindung, die eine Jelly-Zeichenfolge als Argument verwendet und eine Jelly-Zeichenfolge zurückgibt.

Vielen Dank an @JonathanAllan für das Speichern von 2 Bytes!

Erläuterung

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
quelle
..._J‘ịØṖḊ¤spart ein Byte.
Jonathan Allan
@ JonathanAllan danke, guter Anruf!
Nick Kennedy
2
Oh, und wir können in unserer Suche>. <ein weiteres Byte speichern: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

Probieren Sie es online aus!

Vielen Dank an @Joel für das Ersetzen der hässlichen nicht druckbaren Zeichen im Bytestring durch druckbare.

Ich suche eine Mod-Kette zum Ersetzen "*jpovi<".find(c) ich , aber ich glaube nicht, dass es eine gibt, die kürzer ist, und eine nicht erschöpfende Brute-Force-Suche hat bisher nichts gefunden.

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)

Probieren Sie es online aus!

xnor
quelle
Die nicht druckbaren ASCII-Zeichen können um 94 versetzt werden, um zur besseren Lesbarkeit in druckbare Zeichen umgewandelt zu werden.
Joel
Sie könnten versuchen, eine mathematische Funktion zu finden, um das Mapping zu ersetzen, b"de{#0ABT"["*jpovi<".find(c)]wenn Sie ein Programm dafür haben.
Joel
1
@Joel Leider denke ich, dass das Mapping ein viel zu großer Suchraum für eine arithmetische Funktion ist, zumindest mit den Tools, die ich habe. Ich habe gerade Modulo-Ketten wie x%84%15%7für die rechte Hälfte des Mappings durchsucht , aber ich denke, ich kann Code, den ich geschrieben habe, für eine weitere Herausforderung bei der Suche einschließlich *und nach /Begriffen recyceln .
xnor
@Joel Ich finde nichts Mod-Chain-Stil für die rechte Seite mit %und *( //in Python 3 ist es wahrscheinlich nicht wert.) Tatsächlich hat nichts die ersten 6 von 7 Werten erreicht. Ich hoffte, dass dies funktionieren würde, da eine grobe Entropieschätzung besagt, dass wahrscheinlich genug Ausdrücke mit% 7` enden, aber es ist nah. Und vielleicht liefern diese Ketten Ausgaben, die bei weitem nicht gleichmäßig verteilt sind, zumal, sobald zwei Eingaben auf den gleichen Wert zusammenfallen, keine weiteren Operationen sie trennen können. Das Zeug, das ich versuche, ist immer noch viel zu dumm, um den größeren Ausdruck zu suchen, aber wenn Sie irgendwelche Ideen haben, versuchen Sie es.
xnor
Ich denke, ein besserer Algorithmus wird wahrscheinlich für beliebige Eingaben wie benötigt map(ord, "*jpovi<"). Wenn die Ausgabe die Reihenfolge für die meisten Eingaben nicht beibehält (dh f(m)>=f(n)wenn m>=n), werden einige sorgfältig ausgearbeitete Konstanten für %und *wahrscheinlich benötigt, und eine Brute-Force-Suche führt wahrscheinlich nicht zu einem positiven Ergebnis.
Joel
6

Malbolge Unshackled (20-Trit-Rotationsvariante), 7.784e6 Bytes

Die Größe dieser Antwort überschreitet die maximale Größe des postbaren Programms (eh), sodass sich der Code in meinem GitHub-Repository befindet .

Wie führe ich das aus?

Dies könnte ein schwieriger Teil sein, da der naive Haskell-Dolmetscher ewig brauchen wird, um dies auszuführen. TIO hat einen anständigen Malbogle Unshackled-Interpreter, aber leider kann ich ihn nicht verwenden (Einschränkungen).

Das beste, das ich finden konnte, ist die Variante mit fester 20-Trit-Rotationsbreite, die sehr gut funktioniert und 0,5 Zeichen pro Sekunde konvertiert .

Um den Dolmetscher etwas schneller zu machen, habe ich alle Schecks von Matthias Lutters Malbolge Unshackled-Dolmetscher entfernt.

Meine modifizierte Version kann ungefähr 6,3% schneller laufen.

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

Es funktioniert!

Es funktioniert

Krzysztof Szewczyk
quelle
2
Das ist einfach verrückt.
MilkyWay90
Für Passanten beträgt die Byteanzahl 7,784 MB, nicht 7,784 GB. Ich interpretierte das Komma zunächst als Gruppierung der Tausender und nicht als Dezimalpunkt.
Potato44
@ Potato44 In Polen verwenden wir Komma als Dezimaltrennzeichen. Die Verwendung von Punkten als solche ist verboten.
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)

Probieren Sie es online aus!

Dies ist hauptsächlich ein mathematisches Problem bei der Vereinfachung der Berechnung sowie beim Golfen, nachdem die Mathematik abgeschlossen wurde. Die ungolfed Version des Codes wird unten gezeigt.

Ungolfed, nicht rekursive Version

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

Probieren Sie es online aus!

Joel
quelle
5

JavaScript (Node.js) , 69 Byte

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

Probieren Sie es online aus!

Wie?

[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
quelle
3

05AB1E , 32 31 23 22 Bytes

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

-8 Bytes, die einen Port von NickKennedys Jelly-Antwort erstellen , also stellen Sie sicher, dass Sie ihn positiv bewerten !!
-1 Byte dank @Grimy.

Gibt als Liste von Zeichen aus.

Probieren Sie es online aus oder überprüfen Sie alle Testfälle .

Erläuterung:

   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)

Sehen Sie diese 05AB1E Spitze Mine (Abschnitt Wie große natürliche Zahlen zu komprimieren? Und Wie zu komprimieren integer Listen? ) Zu verstehen , warum •4¡ˆ¶ü]₁η₃•ist 82767635194143615015und •4¡ˆ¶ü]₁η₃•₃вist [1,36,30,85,0,67,66,8,49,7,0].

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

Perl 5 ( -p), 53 , 51 Bytes

Speichern Sie 2 Bytes, indem Sie de{#0ABTstatt verwenden, '(>DQbcudamit 61nicht mehr benötigt

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

TIO

Die erste Antwort war

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

TIO

Nahuel Fouilleul
quelle
2

Japt , 24 23 Bytes

Port of Nick's Jelly-Lösung

;£EÅgYn" #T BA0 "cXc

Versuch es

;£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
Zottelig
quelle
1

Retina 0,8,2 , 50 Bytes

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

Probieren Sie es online aus! Link enthält Testfälle. Erläuterung:

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

Führen Sie die Transliteration wie in der Frage beschrieben durch. p(unten beschrieben) und ohaben eine besondere Bedeutung für die TÜbersetzung, daher müssen sie zitiert werden.

.
$.`$* $&¶

Listen Sie jedes Zeichen in einer eigenen Zeile auf, gefolgt von einer Anzahl von Leerzeichen gemäß seinem Index, dh dem Programmzähler.

+T`!p`~_p` .¶

Dekrementieren Sie das letzte Zeichen in jeder Zeile wiederholt zyklisch und löschen Sie jedes Mal das vorhergehende Leerzeichen, bis alle Leerzeichen gelöscht wurden. Das psteht für druckbares ASCII, dh -~wir möchten, dass das !Mapping ~so zugeordnet wird, dass es zuerst transliteriert wird, und dann _wird das Leerzeichen in der Übereinstimmung gelöscht, während die verbleibenden Zeichen jeweils um einen Zeichencode transkribiert werden.

Verbinde alle Charaktere wieder miteinander.

Neil
quelle
1

Holzkohle , 23 Bytes

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

Probieren Sie es online aus! Der Link führt zur ausführlichen Version des Codes. Port of @ Arnauld's JavaScript-Antwort. Erläuterung:

 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
quelle