Traducteur normalisé Malbolge vers Malbolge

12

Dans cette tâche, vous allez écrire un programme / une fonction qui prend un programme Malbolge normalisé et génère le programme Malbolge résultant . (Ceci est un outil secret que tous les programmeurs Malbolge utilisent!)

Contribution

Une structure de données qui (en quelque sorte) représente un programme Malbolge normalisé.

Production

Une structure de données qui représente le programme Malbolge résultant.

Exemples

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|

Comment convertir

Itérer sur le programme Malbolge normalisé, en effectuant les étapes suivantes pour chaque personnage:

  1. Remplacez les caractères de la chaîne *jpovi</par le caractère correspondant dans '(>DQbcu. (C'est-à-dire mapper *vers ', jvers (, etc.).

  2. Soustrayez ensuite la position actuelle du compteur de programme (c'est-à-dire le nombre de caractères avant celui en cours) du code ASCII du caractère.

  3. Si le code ASCII résultant est inférieur à 33, incrémentez-le de 94 et répétez jusqu'à ce qu'il soit au moins 33.

  4. Ajoutez le caractère résultant à la sortie.

Règles

  • Il s'agit d'un concours de ; la réponse la plus courte l'emporte.
  • Pas de failles standard s'il vous plaît.
  • Les méthodes d'E / S par défaut sont autorisées.
  • L'entrée ne contiendra que les caractères *jpovi</.
Ilmari Karonen
la source
4
L'entrée contient-elle uniquement des caractères de " *jpovi</"?
Joel
7
Je ne comprends pas ce que "Alors, moins la position." veux dire. Je pourrais probablement le comprendre à partir du pseudocode, mais l'explication devrait être autonome.
xnor
1
" Bien que le code ASCII des représentations temporaires de Malbolge soit inférieur à 33, incrémentez le caractère de 94. " Que voulez-vous dire par là? Voici comment j'ai compris le défi: 1) les personnages de la carte; 2) convertir en valeur unicode; 3) diminuez chacun par le compteur de programme (nous avons maintenant ce que vous appelez le code ASCII des représentations temporaires de Malbolge); 4) si une valeur est inférieure à 33, incrémentez-la de 94; 5) reconvertissez ces valeurs en caractères. Mais en utilisant cette approche, la sortie n'est clairement pas correcte. Pourriez-vous clarifier ce que vous entendez par là pour les entrées de plus de 33 caractères?
Kevin Cruijssen
1
a: if ascii_code(temporary Malbolge representation) < 33: char := char + 94; goto a;
1
Je donnerai volontiers une prime à tous ceux qui peuvent écrire une de ces choses dans Malbolge :)
JDL

Réponses:

4

Gelée , 29 22 octets

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

Essayez-le en ligne!

Un lien monadique prenant une chaîne Jelly comme argument et renvoyant une chaîne Jelly.

Merci à @JonathanAllan pour avoir économisé 2 octets!

Explication

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
la source
..._J‘ịØṖḊ¤enregistre un octet.
Jonathan Allan
@JonathanAllan merci, bon appel!
Nick Kennedy
2
oh, et nous pouvons incrémenter dans notre recherche>. < enregistrer un autre octet:Oị“%þV DCµ2® ‘_JịØṖḊ¤
Jonathan Allan
6

Python 3 , 82 octets

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

Essayez-le en ligne!

Merci à @Joel d'avoir remplacé les vilains caractères non imprimables du bytestring par des caractères imprimables.

Je cherche une chaîne de mod à remplacer "*jpovi<".find(c), mais je ne pense pas qu'il y en ait une plus courte, et une recherche par force brute non exhaustive n'a rien trouvé jusqu'à présent.

82 octets

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

Essayez-le en ligne!

xnor
la source
Les caractères ASCII non imprimables peuvent être décalés de 94 pour être transformés en caractères imprimables pour une meilleure lisibilité.
Joel
Vous pouvez essayer de trouver une fonction mathématique pour remplacer le mappage b"de{#0ABT"["*jpovi<".find(c)]si vous avez un programme pour cela.
Joel
1
@ Joel Malheureusement, je pense que la cartographie est un espace de recherche beaucoup trop large pour une fonction arithmétique, du moins avec les outils dont je dispose. Je venais cherché modulo chaînes comme x%84%15%7pour la moitié droite de la cartographie, mais je pense que je peux recycler un code que j'ai écrit pour un autre défi pour la recherche , y compris *et /termes.
xnor
@Joel Je ne trouve rien de mod-chain-style pour le côté droit en utilisant %et *( //en Python 3 n'en vaut probablement pas la peine.) En fait, rien n'a correspondu aux 6 premières des 7 valeurs. J'espérais que cela fonctionnerait parce qu'une estimation d'entropie approximative indique qu'il y a probablement suffisamment d'expressions se terminant par% 7`, mais c'est proche. Et peut-être que ces chaînes donnent des sorties qui sont loin d'être uniformément réparties, d'autant plus qu'une fois que deux entrées se réduisent à la même valeur, aucune autre opération ne peut les séparer. Ce que j'essaie est encore bien trop stupide pour rechercher l'expression plus large, mais si vous avez des idées, allez-y.
xnor
Je pense qu'un meilleur algorithme est probablement nécessaire pour des entrées arbitraires comme map(ord, "*jpovi<"). Si la sortie ne préserve pas l'ordre de la plupart des entrées (c'est-à f(m)>=f(n)- dire si m>=n), certaines constantes soigneusement conçues pour %et *sont probablement nécessaires et une recherche par force brute est peu susceptible de donner un résultat positif.
Joel
6

Malbolge Unshackled (variante de rotation de 20 trits), 7 784e6 octets

La taille de cette réponse dépasse la taille maximale du programme (eh), donc le code se trouve dans mon référentiel GitHub .

Comment faire ça?

Cela pourrait être une partie délicate, car un interprète naïf de Haskell prendra des âges pour exécuter cela. TIO a un interprète Malbogle Unshackled décent, mais malheureusement je ne pourrai pas l'utiliser (limitations).

Le meilleur que j'ai pu trouver est la variante de largeur de rotation fixe de 20 trits, qui fonctionne très bien, convertissant 0,5 caractère par seconde .

Pour rendre l'interprète un peu plus rapide, j'ai supprimé toutes les vérifications de l'interpréteur Malbolge Unshackled de Matthias Lutter.

Ma version modifiée peut fonctionner environ 6,3% plus rapidement.

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

Ça marche!

Ça marche

Krzysztof Szewczyk
la source
2
C'est tout simplement fou.
MilkyWay90
Pour les passants, le nombre d'octets est de 7,784 Mo et non de 7,784 Go. J'ai interprété la virgule comme un regroupement des milliers plutôt qu'un point décimal au début.
Potato44
@ Potato44 nous utilisons la virgule comme séparateur décimal en Pologne, l'utilisation de point en tant que tel est interdite.
Krzysztof Szewczyk
5

Python 3 , 84 83 octets

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

Essayez-le en ligne!

Il s'agit principalement d'un problème mathématique lié à la simplification du calcul, plus un peu de golf après avoir effectué les calculs. La version non golfée du code est présentée ci-dessous.

Version non golfée, non récursive

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

Essayez-le en ligne!

Joel
la source
5

JavaScript (Node.js) , 69 octets

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

Essayez-le en ligne!

Comment?

[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
la source
3

05AB1E , 32 31 23 22 octets

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

-8 octets créant un portage de la réponse Jelly de NickKennedy , alors assurez-vous de lui donner une note positive !!
-1 octet grâce à @Grimy.

Sorties sous forme de liste de caractères.

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

   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)

Voir cette astuce 05AB1E (section Comment compresser les grands entiers? Et Comment compresser les listes d'entiers? ) Pour comprendre pourquoi •4¡ˆ¶ü]₁η₃•est 82767635194143615015et •4¡ˆ¶ü]₁η₃•₃вest [1,36,30,85,0,67,66,8,49,7,0].

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

Perl 5 ( -p), 53 , 51 octets

économiser 2 octets, en utilisant de{#0ABTau lieu de de '(>DQbcusorte que 61plus nécessaire

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

TIO

la première réponse était

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

TIO

Nahuel Fouilleul
la source
2

Japt , 24 23 octets

Port of Nick's Jelly solution

;£EÅgYn" #T BA0 "cXc

Essayez-le

;£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
Hirsute
la source
1

Retina 0.8.2 , 50 octets

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

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

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

Effectuez la translittération comme décrit dans la question. p(décrit ci-dessous) et oont une signification particulière pour Transliter donc ils doivent être cités.

.
$.`$* $&¶

Énumérez chaque caractère sur sa propre ligne, précédé d'un certain nombre d'espaces selon son index, c'est-à-dire ce que serait le compteur de programme.

+T`!p`~_p` .¶

Décrémentez de manière cyclique et répétée le dernier caractère de chaque ligne, en supprimant à chaque fois l'espace précédent, jusqu'à ce que tous les espaces aient été supprimés. Le psignifie ASCII imprimable -~, c'est -à- dire que nous voulons que le! mappage ~soit translittéré en premier, puis le _provoque la suppression de l'espace dans la correspondance , tandis que les caractères restants sont translittérés un code de caractère à la fois.

Regroupez tous les personnages.

Neil
la source
1

Fusain , 23 octets

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

Essayez-le en ligne! Le lien est vers la version détaillée du code. Port de la réponse JavaScript de @ Arnauld. Explication:

 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
la source
1

Haskell , 135 octets

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

Essayez-le en ligne!

David
la source