Нормализованный переводчик Malbolge в Malbolge

12

В этой задаче вы напишите программу / функцию, которая берет программу нормализованного Malbolge и выводит результирующую программу Malbolge . (Это секретный инструмент, который используют все программисты Malbolge!)

вход

Структура данных, которая (каким-то образом) представляет нормализованную программу Malbolge.

Выход

Структура данных, которая представляет результирующую программу Malbolge.

Примеры

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|

Как конвертировать

Выполните итерацию по нормализованной программе Malbolge, выполнив следующие шаги для каждого символа:

  1. Замените символы в строке *jpovi</соответствующими символами в '(>DQbcu. (То есть, карта *с ', jк (, и так далее.)

  2. Затем вычтите текущую позицию счетчика программы (т.е. количество символов перед текущей) из кода ASCII символа.

  3. Если полученный ASCII-код меньше 33, увеличьте его на 94 и повторяйте, пока он не станет не менее 33.

  4. Добавьте полученный символ к выводу.

правила

  • Это соревнование по ; самый короткий ответ выигрывает.
  • Никаких стандартных лазеек, пожалуйста.
  • Методы ввода / вывода по умолчанию разрешены.
  • Ввод будет содержать только символы *jpovi</.
Илмари Каронен
источник
4
Вход содержит только символы из " *jpovi</"?
Джоэл
7
Я не понимаю, что "Тогда, минус положение". означает. Я, вероятно, мог бы понять это из псевдокода, но объяснение должно быть автономным.
xnor
1
« В то время как код ASCII временных представлений Malbolge меньше 33, увеличьте char на 94. « Что вы подразумеваете под этим? Насколько я понял задача состоит в следующем: 1) карта персонажей; 2) преобразовать в Unicode-значение; 3) уменьшить каждый на счетчик программы (теперь у нас есть то, что вы называете «ASCII-кодом временных представлений Malbolge»); 4) если любое значение меньше 33, увеличьте его на 94; 5) преобразовать эти значения обратно в символы. Но при использовании этого подхода выходные данные явно не верны. Итак, не могли бы вы уточнить, что вы подразумеваете под этим для ввода длиной более 33 символов?
Кевин Круйссен
1
a: if ascii_code(temporary Malbolge representation) < 33: char := char + 94; goto a;
1
Я с радостью дам щедрость любому, кто может написать одну из этих вещей в Malbolge :)
JDL

Ответы:

4

Желе , 29 22 байта

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

Попробуйте онлайн!

Монадическая ссылка, принимающая строку Jelly в качестве аргумента и возвращающая строку Jelly.

Спасибо @JonathanAllan за сохранение 2 байта!

объяснение

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‘ịØṖḊ¤сохраняет один байт.
Джонатан Аллан
@JonathanAllan спасибо, хороший звонок!
Ник Кеннеди
2
о, и мы можем увеличивать наш поиск>. < сохраняя еще один байт:Oị“%þV DCµ2® ‘_JịØṖḊ¤
Джонатан Аллан
6

Python 3 , 82 байта

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

Попробуйте онлайн!

Спасибо @Joel за замену уродливых непечатных символов в строке байтов на печатные.

Я ищу замену мод-цепочки "*jpovi<".find(c), но я не думаю, что есть такая, которая короче, и неисчерпывающий поиск грубой силы ничего не нашел до сих пор.

82 байта

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

Попробуйте онлайн!

XNOR
источник
Непечатаемые символы ASCII можно сместить на 94, чтобы сделать их печатными для лучшей читаемости.
Джоэл
Вы можете попытаться найти математическую функцию, чтобы заменить отображение, b"de{#0ABT"["*jpovi<".find(c)]если у вас есть программа для этого.
Джоэл
1
@Joel К сожалению, я думаю, что отображение слишком широкое пространство поиска для арифметической функции, по крайней мере, с помощью инструментов, которые у меня есть. Я просто искал по модулю цепочки , как x%84%15%7для правой части отображения, но я думаю , что я могу переработать код , который я написал для еще один вызов для поиска , включая *и /условия.
xnor
@Joel Я не нахожу ничего в стиле мод-цепочки для правой стороны, использующего %и *( //в Python 3, вероятно, оно того не стоит). Фактически, ничто не соответствует первым 6 из 7 значений. Я надеялся, что это сработает, потому что приблизительная оценка энтропии говорит, что, вероятно, достаточно выражений, заканчивающихся на% 7`, но это близко. И, возможно, эти цепочки дают выходы, которые далеко не равномерно распределены, тем более что, если два входа сворачиваются до одного значения, никакие дальнейшие операции не могут их разделить. То, что я пробую, все еще слишком глупо, чтобы искать более широкое выражение, но если у вас есть какие-либо идеи, воспользуйтесь им.
xnor
Я думаю, что лучший алгоритм, вероятно, необходим для произвольных входов, таких как map(ord, "*jpovi<"). Если выходные данные не сохраняют порядок для большинства входных данных (т. Е. f(m)>=f(n)Если m>=n), некоторые тщательно созданные константы для% и *, вероятно, необходимы, и поиск методом грубой силы вряд ли даст положительный результат.
Джоэл
6

Malbolge Unshackled (вариант с 20-кратным вращением), 7,784e6 байт

Размер этого ответа превышает максимально допустимый размер программы (eh), поэтому код находится в моем репозитории GitHub .

Как запустить это?

Это может быть непростой задачей, потому что наивному интерпретатору Haskell понадобятся годы, чтобы запустить это. У TIO есть приличный интерпретатор Malbogle Unshackled, но, к сожалению, я не смогу его использовать (ограничения).

Лучший вариант, который я смог найти, это фиксированный вариант ширины поворота в 20 трит, который работает очень хорошо, преобразуя 0,5 символа в секунду .

Чтобы сделать переводчика немного быстрее, я удалил все проверки из интерпретатора Мэттиласа Люттера «Малболж».

Моя модифицированная версия может работать примерно на 6,3% быстрее.

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

Это работает!

Это работает

Кшиштоф Шевчик
источник
2
Это просто безумие.
MilkyWay90
Для прохожих число байтов составляет 7,784 МБ, а не 7,784 ГБ. Сначала я интерпретировал запятую как группировку тысяч, а не десятичную точку.
Potato44
@ Potato44 мы используем запятую в качестве десятичного разделителя в Польше, использование точки как таковой запрещено.
Кшиштоф Шевчик
5

Python 3 , 84 83 байта

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

Попробуйте онлайн!

Это в основном математическая задача об упрощении вычислений, плюс немного игры в гольф после выполнения математики. Развернутая версия кода показана ниже.

Ungolfed, нерекурсивная версия

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

Попробуйте онлайн!

Joel
источник
5

JavaScript (Node.js) , 69 байт

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

Попробуйте онлайн!

Как?

[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
источник
3

05AB1E , 32 31 23 22 байта

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

-8 байт, создающих порт ответа JellyKennedy 's Jelly , так что обязательно поставьте его на голос!
-1 байт благодаря @Grimy.

Выходы в виде списка символов.

Попробуйте онлайн или проверьте все контрольные примеры .

Объяснение:

   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)

Посмотрите эту подсказку 05AB1E (раздел Как сжимать большие целые числа? И Как сжимать целочисленные списки? ), Чтобы понять, почему •4¡ˆ¶ü]₁η₃•есть 82767635194143615015и •4¡ˆ¶ü]₁η₃•₃весть [1,36,30,85,0,67,66,8,49,7,0].

Кевин Круйссен
источник
•1ÃQWý₂Ýδ9•86в->•4¡ˆ¶ü]₁η₃•₃в
Grimmy
@Grimy Спасибо :)
Кевин Круйссен
2

Perl 5 ( -p), 53 , 51 байт

сохранение 2 байта, используя de{#0ABTвместо того, '(>DQbcuчтобы 61больше не нужно

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

TIO

первый ответ был

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

TIO

Науэль Фуйе
источник
2

Japt , 24 23 байта

Порт Желе от Ника

;£EÅgYn" #T BA0 "cXc

Попробуй

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

Сетчатка 0.8.2 , 50 байт

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

Попробуйте онлайн! Ссылка включает в себя тестовые случаи. Объяснение:

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

Сделайте транслитерацию, как описано в вопросе. p(описано ниже) и oимеют особое значение для Tтранслитерации, поэтому их нужно заключать в кавычки.

.
$.`$* $&¶

Перечислите каждый символ в отдельной строке, которому предшествует количество пробелов в соответствии с его индексом, т. Е. Счетчиком программы.

+T`!p`~_p` .¶

Неоднократно циклически уменьшайте последний символ в каждой строке, каждый раз удаляя предыдущий пробел, пока все пробелы не будут удалены. На pстендах для печати ASCII то есть -~, однако мы хотим, !чтобы сопоставить , ~так что транслитерируются первым, а затем _вызывает пространство в матче будет удалено, а остальные символы получают транслитерации один код символа в то время.

Присоединяйтесь ко всем персонажам вместе.

Нил
источник
1

Древесный уголь , 23 байта

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

Попробуйте онлайн! Ссылка на подробную версию кода. Порт @ Арно, ответ JavaScript. Объяснение:

 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
Нил
источник