Tradutor Malbolge normalizado para Malbolge

12

Nesta tarefa, você escreverá um programa / função que pega um programa Malbolge Normalizado e gera o programa Malbolge resultante . (Esta é uma ferramenta secreta que todos os programadores de Malbolge estão usando!)

Entrada

Uma estrutura de dados que (de alguma forma) representa um programa Malbolge Normalizado.

Resultado

Uma estrutura de dados que representa o programa Malbolge resultante.

Exemplos

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 converter

Repita o programa Malbolge normalizado, executando as seguintes etapas para cada caractere:

  1. Substitua os caracteres na sequência *jpovi</pelo caractere correspondente em '(>DQbcu. (Ou seja, mapeie *para ', jpara (e assim por diante.)

  2. Subtraia a posição atual do contador de programa (ou seja, o número de caracteres antes do atual) do código ASCII do caractere.

  3. Se o código ASCII resultante for menor que 33, aumente-o em 94 e repita até que seja pelo menos 33.

  4. Anexe o caractere resultante à saída.

Regras

  • Este é um concurso de ; a resposta mais curta vence.
  • Sem brechas padrão, por favor.
  • Os métodos de E / S padrão são permitidos.
  • A entrada conterá apenas os caracteres *jpovi</.
Ilmari Karonen
fonte
4
A entrada contém apenas caracteres de " *jpovi</"?
Joel
7
Não entendo o que "Então, menos a posição". significa. Eu provavelmente poderia descobrir isso a partir do pseudocódigo, mas a explicação deve ser independente.
Xnor
1
" Enquanto o código ASCII das representações temporárias de Malbolge é menor que 33, aumente o caractere por 94. " O que você quer dizer com isso? Como eu entendi o desafio é: 1) caracteres do mapa; 2) converter para valor unicode; 3) diminuir cada um pelo contador de programa (agora temos o que você chama de 'código ASCII' das representações temporárias de Malbolge '); 4) se algum valor for menor que 33, aumente esse valor em 94; 5) converta esses valores novamente em caracteres. Mas, usando essa abordagem, a saída claramente não está correta. Então, você poderia esclarecer o que quer dizer com entradas com mais de 33 caracteres?
Kevin Cruijssen 28/08/19
1
a: if ascii_code(temporary Malbolge representation) < 33: char := char + 94; goto a;
1
Eu vou alegremente dar uma recompensa para quem pode escrever uma dessas coisas em Malbolge :)
JDL

Respostas:

4

Geléia , 29 22 bytes

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

Experimente online!

Um link monádico usando uma sequência Jelly como argumento e retornando uma sequência Jelly.

Obrigado a @ JonathanAllan por salvar 2 bytes!

Explicação

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
fonte
..._J‘ịØṖḊ¤salva um byte.
Jonathan Allan
@ JonathanAllan obrigado, boa chamada!
Nick Kennedy
2
. oh, e podemos incrementar dentro de nossa pesquisa> < salvar outro 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

Experimente online!

Agradecemos ao @Joel por substituir os caracteres feios e não imprimíveis na sequência de caracteres por caracteres imprimíveis.

Estou procurando uma corrente mod para substituir "*jpovi<".find(c), mas não acho que exista uma que seja mais curta, e uma busca não exaustiva por força bruta não encontrou nada até agora.

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)

Experimente online!

xnor
fonte
Os caracteres ASCII não imprimíveis podem ser deslocados em 94 para serem transformados em caracteres imprimíveis para melhor legibilidade.
Joel
Você pode tentar encontrar uma função matemática para substituir o mapeamento, b"de{#0ABT"["*jpovi<".find(c)]se tiver um programa para isso.
Joel
1
@ Joel Infelizmente, acho que o mapeamento é um espaço de pesquisa muito amplo para uma função aritmética, pelo menos com as ferramentas que tenho. Eu tinha acabado de pesquisar cadeias de módulos como x%84%15%7na metade direita do mapeamento, mas acho que posso reciclar algum código que escrevi para outro desafio de pesquisar termos *e /condições.
xnor
@ Joel Não estou encontrando nada do estilo mod-chain para o lado direito usando %e *( //no Python 3 provavelmente não vale a pena.) De fato, nada correspondeu aos 6 primeiros de 7 valores. Eu esperava que isso funcionasse porque uma estimativa aproximada da entropia diz que provavelmente há expressões suficientes terminando em% 7`, mas está próximo. E talvez essas cadeias ofereçam resultados que estão longe de serem distribuídos uniformemente, especialmente porque quando duas entradas entram em colapso para o mesmo valor, nenhuma operação adicional pode separá-las. As coisas que estou tentando ainda são burras demais para procurar a expressão maior, mas se você tiver alguma idéia, vá em frente.
xnor
Eu acho que um algoritmo melhor provavelmente é necessário para entradas arbitrárias como map(ord, "*jpovi<"). Se a saída não preservar a ordem da maioria das entradas (por exemplo, f(m)>=f(n)se m>=n), algumas constantes cuidadosamente criadas para %e *provavelmente são necessárias e é improvável que uma busca por força bruta produza um resultado positivo.
Joel
6

Malbolge Unshackled (variante de rotação de 20 trit), 7.784e6 bytes

O tamanho desta resposta excede o tamanho máximo do programa postável (eh); portanto, o código está localizado no meu repositório GitHub .

Como executar isso?

Isso pode ser uma parte complicada, porque o intérprete ingênuo de Haskell levará anos e anos para executá-lo. O TIO possui um intérprete decente do Malbogle Unshackled, mas, infelizmente, não poderei usá-lo (limitações).

O melhor que eu pude encontrar é a variante fixa de largura de rotação de 20 trit, que executa muito bem, convertendo 0,5 caracteres por segundo .

Para tornar o intérprete um pouco mais rápido, removi todas as verificações do interpretador Malbolge Unshackled de Matthias Lutter.

Minha versão modificada pode executar cerca de 6,3% mais 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;
}

Está funcionando!

Está funcionando

Krzysztof Szewczyk
fonte
2
Isso é insano.
MilkyWay90
Para os transeuntes, a contagem de bytes é 7.784MB, não 7.784GB. Interpretei a vírgula como agrupando milhares, em vez de um ponto decimal no início.
Potato44
@ Potato44 usamos vírgula como separador decimal na Polônia, usando ponto como tal é proibido.
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)

Experimente online!

Isso é principalmente um problema de matemática sobre a simplificação do cálculo, além de um pouco de golfe após a conclusão da matemática. A versão sem código do código é mostrada abaixo.

Versão não-gasta e não recursiva

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

Experimente online!

Joel
fonte
5

JavaScript (Node.js) , 69 bytes

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

Experimente online!

Quão?

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

05AB1E , 32 31 23 22 bytes

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

-8 bytes criando uma porta da resposta de NickKennedy 's Jelly , portanto, faça um voto positivo !
-1 byte graças a @Grimy.

Saída como uma lista de caracteres.

Experimente online ou verifique todos os casos de teste .

Explicação:

   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)

Consulte esta minha dica do 05AB1E (seção Como compactar números inteiros grandes? E Como compactar listas de números inteiros? ) Para entender por que •4¡ˆ¶ü]₁η₃•é 82767635194143615015e •4¡ˆ¶ü]₁η₃•₃вé [1,36,30,85,0,67,66,8,49,7,0].

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

Perl 5 ( -p), 53 , 51 bytes

economizando 2 bytes, usando em de{#0ABTvez de '(>DQbcupara que 61não seja mais necessário

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

TIO

primeira resposta foi

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

TIO

Nahuel Fouilleul
fonte
2

Japonês , 24 23 bytes

Solução de porta de geléia de Nick

;£EÅgYn" #T BA0 "cXc

Tente

;£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
Shaggy
fonte
1

Retina 0.8.2 , 50 bytes

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

Experimente online! O link inclui casos de teste. Explicação:

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

Faça a transliteração conforme descrito na pergunta. p(descrito abaixo) e otêm um significado especial para Ttraduzir novamente, de modo que precisam ser citados.

.
$.`$* $&¶

Liste cada caractere em sua própria linha, precedido por vários espaços de acordo com seu índice, ou seja, qual seria o contador do programa.

+T`!p`~_p` .¶

Reduza repetidamente ciclicamente o último caractere em cada linha, excluindo o espaço anterior a cada vez, até que todos os espaços tenham sido excluídos. O psuporte para ASCII imprimível, ou seja, -~ , no entanto queremos que o !de mapear a ~forma que é transliterado primeiro, e depois o _faz com que o espaço no jogo a ser excluída, enquanto os restantes caracteres se transliterado um código de caracteres de cada vez.

Junte todos os personagens novamente.

Neil
fonte
1

Carvão , 23 bytes

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

Experimente online! Link é a versão detalhada do código. Porto da resposta JavaScript de @ Arnauld. Explicação:

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

Experimente online!

david
fonte