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. 結果の文字を出力に追加します。

ルール

  • これは、コンテストです。最短の答えが勝ちます。
  • 標準的な抜け穴はありません。
  • デフォルトのI / Oメソッドが許可されています。
  • 入力には文字のみが含まれます*jpovi</

4
入力に「*jpovi</」の文字のみが含まれていますか?
ジョエル

7
「それでは、マイナスの位置」がわかりません。手段。私はおそらく擬似コードからそれを理解できましたが、説明は自己完結型でなければなりません。
xnor

1
一時的なMalbolge表現のASCIIコードは33未満ですが、charを94増やします。」これはどういう意味ですか?課題の理解方法は次のとおりです。1)マップキャラクター。2)Unicode値に変換します。3)プログラムカウンタごとにそれぞれを減らします(「一時的なマルボルジ表現」ASCIIコードと呼ぶものがあります)。4)値が33未満の場合は、94ずつ増やします。5)これらの値を文字に変換します。しかし、このアプローチを使用すると、出力は明らかに正しくありません。33文字を超える入力について、これが何を意味するのかを明確にできますか。
ケビンクルーッセン

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

1
Malbolgeでこれらのことの1つを書くことができる人には喜んで報奨金を差し上げます:)
JDL

回答:


4

ゼリー29 22バイト

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

オンラインでお試しください!

Jelly文字列を引数として受け取り、Jelly文字列を返すモナドリンク。

2バイトを節約してくれた@JonathanAllanに感謝します!

説明

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‘ịØṖḊ¤1バイト節約します。
ジョナサンアラン

@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

オンラインでお試しください!

バイト文字列のbyteい印刷不能文字を印刷可能文字に置き換えてくれた@Joelに感謝します。

私は、置き換えるためのmodチェーンを探し"*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私は%、and *//Python 3ではおそらく価値がない)を使用して、右側のmod-chain-styleを見つけていません。実際、7つの値のうち最初の6に一致するものはありません。大まかなエントロピーの推定では、おそらく%7`で終わる表現が十分にあると言われているので、これが機能することを願っていますが、近いです。そして、これらのチェーンは、特に2つの入力が同じ値に折りたたまれると、それ以上の操作でそれらを分離できないため、均等に分散された出力からはほど遠いかもしれません。私がやろうとしているものはまだ大きな表現を検索するにはあまりにも馬鹿げていますが、アイデアがあればそれを探してください。
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文字を変換する非常に優れたパフォーマンスを発揮します。

インタープリターを少し速くするために、Matthias LutterのMalbolge Unshackledインタープリターからすべてのチェックを削除しました。

変更したバージョンは、約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.784GBではなく7.784MBです。カンマは、最初は小数点ではなく数千をグループ化するものとして解釈しました。
ポテト44

@ Potato44では、ポーランドでは小数点としてカンマを使用します。ドットを使用することは禁止されています。
クシシュトフシェフチク

5

Pythonの384の 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

05AB1E32 31 23 22 バイト

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

NickKennedyのJelly回答のポートを作成する-8バイトなので、必ず彼に投票してください!!
@Grimyのおかげで-1バイト。

文字のリストとして出力します。

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明:

   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¡ˆ¶ü]₁η₃•₃в
グリムミー

@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



1

Retina 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文字コード変換します。

すべてのキャラクターを一緒に戻します。


1

、23バイト

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

オンラインでお試しください!リンクは、コードの詳細バージョンです。@Arnauldの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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.