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


12

У цьому завданні ви напишете програму / функцію, яка приймає програму Normalized 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, збільшуйте знаки на 94. " Що ви маєте на увазі під цим? Як я зрозумів виклик: 1) символи карти; 2) перетворити в значення unicode; 3) зменшуйте кожен за лічильником програми (тепер у нас є те, що ви називаєте "тимчасові представлення Malbolge" код ASCII); 4) якщо якесь значення менше 33, приріст на 94; 5) перетворити ці значення назад у символи. Але, використовуючи такий підхід, висновок явно невірний. Тож ви могли б уточнити, що ви розумієте під цим введенням довше 33 символів?
Kevin Cruijssen

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

1
Я із задоволенням дарую винагороду всім, хто може написати одну з таких речей у Мальболге :)
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

Пітон 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)

Спробуйте в Інтернеті!


Недруковані символи 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

Мальболж Несхилений (варіант обертання на 20 тріт), 7 784е6 байт

Розмір цієї відповіді перевищує максимальний розмір програми, що висилається (eh), тому код знаходиться у моєму сховищі GitHub .

Як це запустити?

Це може бути складним, тому що наївний перекладач Хаскелла віками буде віком для цього. 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 ГБ. Кому я трактував спочатку як групування тисяч, а не десяткову точку.
Картопля44

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

Спробуйте в Інтернеті!

Це здебільшого математична проблема щодо спрощення обчислень, а також деякого гольфу після отримання математики. Невикольована версія коду показана нижче.

Нерельєфна, нерекурсивна версія

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

Спробуйте в Інтернеті!




3

05AB1E , 32 31 23 22 байт

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

-8 байт, створюючи порт відповіді NickKennedy 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 Спасибі :)
Kevin Cruijssen

2

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

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

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

ТІО

Перша відповідь була

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

ТІО


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 на порт @ Arnauld. Пояснення:

 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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.