归一化Malbolge到Malbolge转换器


12

在此任务中,您将编写一个程序/函数,该程序/函数采用Normalized Malbolge程序并输出生成的Malbolge程序。(这是所有Malbolge程序员都在使用的秘密工具!)

输入值

(以某种方式)表示Normalized 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
我不明白“然后,减去职位”。手段。我可能可以从伪代码中找出来,但是说明应该是独立的。
xnor19年

1
当临时的Malbolge表示形式的ASCII码小于33时,将字符增加94。 ”这是什么意思?我对挑战的理解是:1)地图角色;2)转换为unicode值;3)通过程序计数器减少每个计数器(我们现在有了所谓的“临时Malbolge表示形式的ASCII码”);4)如果任何值小于33,则将其增加94;5)将这些值转换回字符。但是使用这种方法输出显然是不正确的。.那么,您能否弄清楚对于超过33个字符的输入,这意味着什么?
凯文·克鲁伊森

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

1
我会很高兴地向可以在Malbolge中写这些东西之一的人提供赏金:)
JDL

Answers:


4

果冻29 22字节

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

在线尝试!

以果冻字符串为参数并返回果冻字符串的单子链接。

感谢@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谢谢,打个招呼!
尼克·肯尼迪


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用可打印的字符替换了字节串中难看的不可打印的字符。

我正在寻找要替换的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映射的右半部分,但是我想我可以回收为应对包括*/术语在内的另一项挑战而编写的代码。
xnor19

@Joel我没有在右侧使用%and 找到任何mod-chain样式*//在Python 3中可能不值得。)实际上,没有任何东西与7个值中的前6个匹配。我希望这会起作用,因为粗略的熵估计表明可能有足够的表达式以%7`结尾,但是已经很接近了。也许这些链给出的输出远非均匀分布,尤其是因为一旦两个输入崩溃到相同的值,就无法再进行进一步的操作将它们分开。我正在尝试的东西仍然太笨了,无法搜索更大的表达式,但是如果您有任何想法,请继续尝试。
xnor19

我认为对于类似的任意输入,可能需要更好的算法map(ord, "*jpovi<")。如果输出没有保留大多数输入的顺序(即f(m)>=f(n)if m>=n),则可能需要一些精心设计的常数,%并且*可能会进行蛮力搜索,不太可能产生积极的结果。
乔尔,

6

Malbolge Unshackled(20次旋转旋转变体),7,784e6字节

该答案的大小超过了可发布的最大程序大小(eh),因此代码位于我的GitHub存储库中

如何运行呢?

这可能是一个棘手的部分,因为幼稚的Haskell解释器将不时地运行它。TIO有不错的Malbogle Unshackled解释器,但可惜我无法使用它(限制)。

我能找到的最好的是固定的20-trit旋转宽度变体,它的效果非常好,每秒可转换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
这太疯狂了。
MilkyWay19年

对于路人,字节数为7.784MB,而不是7.784GB。我将逗号解释为首先将千位而不是小数点分组。
土豆

@ Potato44我们在波兰使用逗号作为小数点分隔符,因此禁止使用点号。
Krzysztof Szewczyk

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

在线尝试!


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


3

05AB1E32 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¡ˆ¶ü]₁η₃•is 82767635194143615015•4¡ˆ¶ü]₁η₃•₃вis [1,36,30,85,0,67,66,8,49,7,0]


•1ÃQWý₂Ýδ9•86в->•4¡ˆ¶ü]₁η₃•₃в
Grimmy

@Grimy谢谢:)
凯文·克鲁伊森


2

Japt24 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 ℅ικ

在线尝试!链接是详细版本的代码。@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


1

Haskell,135个字节

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

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.