Penerjemah Malbolge normal ke Malbolge

12

Dalam tugas ini, Anda akan menulis sebuah program / fungsi yang menggunakan program Normalized Malbolge dan mengeluarkan program Malbolge yang dihasilkan . (Ini adalah alat rahasia yang digunakan oleh semua programmer Malbolge!)

Memasukkan

Struktur data yang (entah bagaimana) mewakili program Normalized Malbolge.

Keluaran

Struktur data yang mewakili program Malbolge yang dihasilkan.

Contohnya

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|

Cara mengonversi

Ulangi program Malbolge yang dinormalisasi, dengan melakukan langkah-langkah berikut untuk setiap karakter:

  1. Ganti karakter dalam string *jpovi</dengan karakter yang sesuai di '(>DQbcu. (Yaitu, petakan *ke ', jke (, dan sebagainya.)

  2. Kemudian kurangi posisi penghitung program saat ini (yaitu jumlah karakter sebelum yang sekarang) dari kode ASCII karakter.

  3. Jika kode ASCII yang dihasilkan kurang dari 33, tambah dengan 94 dan ulangi hingga setidaknya 33.

  4. Tambahkan karakter yang dihasilkan ke output.

Aturan

  • Ini adalah kontes ; jawaban terpendek menang.
  • Tolong, jangan ada celah standar .
  • Metode I / O standar diizinkan.
  • Input hanya akan berisi karakter *jpovi</.
Ilmari Karonen
sumber
4
Apakah input hanya berisi karakter dari " *jpovi</"?
Joel
7
Saya tidak mengerti apa "Lalu, minus posisinya." cara. Saya mungkin bisa mencari tahu dari pseudocode, tetapi penjelasannya harus lengkap.
xnor
1
" Sementara kode ASCII representasi Malbolge sementara kurang dari 33, menambah char dengan 94. " Apa maksudmu dengan ini? Bagaimana saya memahami tantangannya adalah: 1) karakter peta; 2) dikonversi ke nilai unicode; 3) kurangi masing-masing dengan penghitung program (kami sekarang memiliki apa yang Anda sebut 'representasi Malbolge sementara' kode ASCII '); 4) jika ada nilai yang kurang dari 33, selisih dengan 94; 5) konversi nilai-nilai ini kembali ke karakter. Tetapi menggunakan pendekatan ini, outputnya jelas tidak benar. Jadi bisakah Anda menjelaskan apa yang Anda maksudkan dengan input yang lebih panjang dari 33 karakter?
Kevin Cruijssen
1
a: if ascii_code(temporary Malbolge representation) < 33: char := char + 94; goto a;
1
Saya akan dengan senang hati memberikan hadiah kepada siapa saja yang dapat menulis salah satu dari ini di Malbolge :)
JDL

Jawaban:

4

Jelly , 29 22 byte

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

Cobalah online!

Tautan monadik yang menggunakan string Jelly sebagai argumennya dan mengembalikan string Jelly.

Terima kasih kepada @JonathanAllan karena telah menghemat 2 byte!

Penjelasan

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
sumber
..._J‘ịØṖḊ¤menghemat satu byte.
Jonathan Allan
@Jonathan Allan terima kasih, panggilan yang bagus
Nick Kennedy
2
oh, dan kita dapat menambahkan di dalam pencarian kita>. < hemat byte lain:Oị“%þV DCµ2® ‘_JịØṖḊ¤
Jonathan Allan
6

Python 3 , 82 byte

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

Cobalah online!

Terima kasih kepada @ Joel untuk mengganti karakter jelek yang tidak patut dicetak di bytestring dengan yang dapat dicetak.

Saya mencari rantai mod untuk menggantikan "*jpovi<".find(c), tetapi saya tidak berpikir ada satu yang lebih pendek, dan pencarian brute-force yang tidak lengkap belum menemukan apa-apa sejauh ini.

82 byte

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

Cobalah online!

Tidak
sumber
Karakter ASCII yang tidak dapat dicetak dapat diimbangi oleh 94 untuk dibuat menjadi karakter yang dapat dicetak agar lebih mudah dibaca.
Joel
Anda dapat mencoba menemukan fungsi matematika untuk menggantikan pemetaan b"de{#0ABT"["*jpovi<".find(c)]jika Anda memiliki program untuk itu.
Joel
1
@ Joel Sayangnya, saya pikir pemetaan itu terlalu luas ruang pencarian untuk fungsi aritmatika, setidaknya dengan alat yang saya miliki. Saya baru saja mencari rantai modulo seperti x%84%15%7untuk bagian kanan pemetaan, tapi saya pikir saya bisa mendaur ulang beberapa kode yang saya tulis untuk tantangan lain untuk pencarian termasuk *dan /istilah.
xnor
@ Joel Saya tidak menemukan apa pun mod-chain-style untuk menggunakan sisi kanan %dan *( //dengan Python 3 mungkin tidak layak.) Bahkan, tidak ada yang cocok dengan nilai 6 dari 7 pertama. Saya berharap ini akan berhasil karena perkiraan entropi kasar mengatakan mungkin ada cukup banyak ekspresi yang diakhiri dengan% 7, tetapi hampir. Dan mungkin rantai ini memberikan output yang jauh dari terdistribusi secara merata, terutama karena setelah dua input runtuh ke nilai yang sama, tidak ada operasi lebih lanjut yang dapat memisahkannya. Hal-hal yang saya coba masih terlalu bodoh untuk mencari ekspresi yang lebih besar, tetapi jika Anda punya ide, coba saja.
xnor
Saya pikir algoritma yang lebih baik mungkin diperlukan untuk input sewenang-wenang seperti map(ord, "*jpovi<"). Jika output tidak mempertahankan urutan untuk sebagian besar input (yaitu f(m)>=f(n)jika m>=n), beberapa konstanta yang dibuat dengan hati-hati untuk %dan *kemungkinan diperlukan dan pencarian dengan kekerasan tidak mungkin menghasilkan hasil yang positif.
Joel
6

Malbolge Unshackled (varian rotasi 20-trit), 7,784e6 byte

Ukuran jawaban ini melebihi ukuran program maksimum yang dapat diposkan (eh), jadi kodenya terletak di repositori GitHub saya .

Bagaimana cara menjalankannya?

Ini mungkin bagian yang sulit, karena juru bahasa Haskell yang naif akan membutuhkan waktu lama untuk menjalankannya. TIO memiliki juru bahasa Malbogle Unshackled yang layak, tetapi sayangnya saya tidak akan dapat menggunakannya (batasan).

Yang terbaik yang bisa saya temukan adalah varian lebar rotasi 20-trit tetap, yang berkinerja sangat baik, mengkonversi 0,5 karakter per detik .

Untuk membuat penerjemah sedikit lebih cepat, saya telah menghapus semua cek dari penerjemah Malbolge Unshackled milik Matthias Lutter.

Versi modifikasi saya dapat berjalan sekitar 6,3% lebih cepat.

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

Bekerja!

Bekerja

Krzysztof Szewczyk
sumber
2
Ini hanya gila.
MilkyWay90
Untuk orang yang lewat, jumlah byte adalah 7.784MB, bukan 7.784GB. Saya menafsirkan koma sebagai mengelompokkan ribuan daripada titik desimal pada awalnya.
Potato44
@ Potato44 kami menggunakan koma sebagai pemisah desimal di Polandia, menggunakan titik karena itu dilarang.
Krzysztof Szewczyk
5

Python 3 , 84 83 byte

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

Cobalah online!

Ini sebagian besar masalah matematika tentang menyederhanakan perhitungan, ditambah beberapa golf setelah menyelesaikan matematika. Versi kode yang tidak ditandai ditampilkan di bawah ini.

Versi tidak digabungkan, non-rekursif

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

Cobalah online!

Joel
sumber
5

JavaScript (Node.js) , 69 byte

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

Cobalah online!

Bagaimana?

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

Perl 6 , 65 55 53 byte

*.ords>>.&{(' #{T BAe0d'.ords[$_%11]-$++)%94+33}.chrs

Cobalah online!

Menggunakan trik mod 11 dari jawaban Arnaud

Jo King
sumber
3

05AB1E , 32 31 23 22 byte

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

-8 byte menciptakan port jawaban NickKennedy 's Jelly , jadi pastikan untuk meningkatkannya !!
-1 byte terima kasih kepada @Grimy.

Output sebagai daftar karakter.

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

   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)

Lihat tip tambang 05AB1E ini (bagian Bagaimana cara mengompresi bilangan bulat besar? Dan Cara mengompresi daftar bilangan bulat? ) Untuk memahami mengapa •4¡ˆ¶ü]₁η₃•ini 82767635194143615015dan •4¡ˆ¶ü]₁η₃•₃вsekarang [1,36,30,85,0,67,66,8,49,7,0].

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

Perl 5 ( -p), 53 , 51 byte

menghemat 2 byte, menggunakan de{#0ABTbukan '(>DQbcusehingga 61tidak lagi diperlukan

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

TIO

jawaban pertama adalah

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

TIO

Nahuel Fouilleul
sumber
2

Japt , 24 23 byte

Solusi Port of Nick's Jelly

;£EÅgYn" #T BA0 "cXc

Cobalah

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

Retina 0.8.2 , 50 byte

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

Cobalah online! Tautan termasuk kasus uji. Penjelasan:

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

Buat transliterasi seperti yang dijelaskan dalam pertanyaan. p(dijelaskan di bawah) dan omemiliki arti khusus untuk Transliterate sehingga mereka perlu dikutip.

.
$.`$* $&¶

Buat daftar setiap karakter pada barisnya sendiri, didahului oleh sejumlah spasi sesuai dengan indeksnya, seperti apa bentuk penghitung programnya.

+T`!p`~_p` .¶

Secara berulang-ulang mengurangi karakter terakhir pada setiap baris, menghapus ruang sebelumnya setiap kali, sampai semua ruang telah dihapus. The psingkatan dicetak ASCII yaitu -~, namun kami ingin !untuk memetakan ke ~sehingga yang transliterasi pertama, dan kemudian _menyebabkan ruang dalam pertandingan yang akan dihapus, sementara karakter yang tersisa bisa ditransliterasikan satu kode karakter pada satu waktu.

Gabungkan semua karakter kembali bersama.

Neil
sumber
1

Arang , 23 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Jawaban JavaScript Port @ Arnauld. Penjelasan:

 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
sumber
1

Haskell , 135 byte

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

Cobalah online!

David
sumber