정규화 된 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</"의 문자 만 포함되어 있습니까?
Joel

7
나는 "그런 다음, 위치를 뺀 것"을 이해하지 못한다. 방법. 아마도 의사 코드에서 알아낼 수는 있지만 설명은 독립적이어야합니다.
xnor

1
" 임시 Malbolge 표현의 ASCII 코드는 33보다 작지만 문자를 94 씩 증가시킵니다. "이것은 무엇을 의미합니까? 내가 도전을 이해 한 방법은 다음과 같습니다. 1)지도 캐릭터; 2) 유니 코드 값으로 변환; 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
나는 Malbolge에서 이러한 것들 중 하나를 쓸 수있는 사람에게 행복하게 현상금을 줄 것이다 :)
JDL

답변:


4

젤리 , 29 22 바이트

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

온라인으로 사용해보십시오!

젤리 문자열을 인수로 받아서 젤리 문자열을 반환하는 모나드 링크.

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 바이트를 저장합니다.
Jonathan Allan

@JonathanAllan 감사합니다, 좋은 전화!
Nick Kennedy

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에게 감사합니다.

나는 교체 할 mod-chain을 찾고 "*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로 오프셋 될 수 있습니다.
Joel

b"de{#0ABT"["*jpovi<".find(c)]프로그램이 있다면 맵핑을 대체 할 수학 함수를 찾을 수 있습니다.
Joel

1
@Joel 불행히도, 매핑은 적어도 내가 가지고있는 도구로는 산술 함수를위한 검색 공간이 너무 넓습니다. 방금 x%84%15%7매핑의 오른쪽 절반 과 같은 모듈로 체인을 검색 했지만, 포함 */용어 를 검색하는 또 다른 도전을 위해 작성한 코드를 재활용 할 수 있다고 생각 합니다.
xnor

내가 사용 오른쪽을 위해 아무것도 모드 연쇄 스타일을 찾는 게 아니에요 @Joel %*( //사실 파이썬 3 것은 아마 가치. 아니다), 아무것도 첫 6 7의 값과 일치하지 않았다. 대략적인 엔트로피 추정치에 따르면 아마도 % 7로 끝나는 표현이 충분하다고 말했기 때문에 이것이 효과가 있기를 바랍니다. 그리고 이러한 체인은 고르게 분포되지 않은 출력을 제공 할 수 있습니다. 특히 두 개의 입력이 동일한 값으로 축소되면 더 이상 조작을 통해 분리 할 수 ​​없습니다. 내가 시도하고있는 것은 여전히 ​​더 큰 표현을 찾기에는 너무 멍청하지만 아이디어가 있다면 그것을 찾으십시오.
xnor

나는 같은 임의의 입력에 더 나은 알고리즘이 필요할 것이라고 생각합니다 map(ord, "*jpovi<"). 출력이 입력의 대부분을위한 순서를 보존하지 않는 경우 (예 : f(m)>=f(n)경우 m>=n), 일부는 조심스럽게 상수를 제작 %하고 *가능성이 필요하며 무차별 검색은 긍정적 인 결과를 얻을 가능성이있다.
Joel

6

Malbolge Unshackled, 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
이것은 단지 미쳤다.
MilkyWay90

통행인에게 바이트 수는 7.784GB가 아닌 7.784MB입니다. 쉼표는 처음에는 소수점이 아닌 수천을 그룹화하는 것으로 해석했습니다.
Potato44

@ Potato44 폴란드에서는 소수점을 쉼표로 사용하고 점을 사용하는 것은 금지되어 있습니다.
Krzysztof Szewczyk

5

파이썬 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

온라인으로 사용해보십시오!




3

05AB1E , 32 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 감사합니다 :)
케빈 Cruijssen

2

Perl 5 ( -p), 53 , 51 바이트

더 이상 필요하지 않도록 de{#0ABT대신 2 바이트 저장'(>DQbcu61

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

TIO

첫 번째 대답은

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

TIO


2

apt , 24 23 바이트

Nick의 젤리 솔루션 포트

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


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.