Brainf ** k to Unary và Back


15

Một ngôn ngữ rất hữu ích trong nguồn bị hạn chế và các thách thức khác là Unary , một dẫn xuất brainfuck trong đó các chương trình được viết chỉ với một ký tự. Công việc của bạn là viết một chương trình để chuyển đổi các chương trình từ brainfuck sang unary và một chương trình để làm ngược lại, cả hai chương trình trong cùng một ngôn ngữ. Điểm của bạn sẽ là tổng độ dài của hai chương trình.

Làm thế nào để bạn chuyển đổi từ brainfuck sang unary?

  • Đầu tiên chuyển đổi mã não của bạn thành nhị phân theo bảng này:

Bảng chuyển đổi

  • Bây giờ ghép mã thành một số nhị phân khổng lồ theo thứ tự mã.
  • Chuẩn bị một 1chuỗi để đảm bảo một số nhị phân duy nhất.
  • Chuyển đổi từ số nhị phân sang số đơn nguyên sử dụng bất kỳ ký tự nào.
  • Ví dụ: +.sẽ là 000000000000000000000000000000000000000000000000000000000000000000000000000000000000(84 số không).

Brainfuck -> Thông số kỹ thuật đơn nhất

  • Vì các chương trình kết quả sẽ rất lớn, nên in không phải chương trình thực tế mà chỉ đơn thuần là độ dài của chương trình kết quả.
  • Lấy chương trình brainfuck làm một chuỗi thông qua stdin, hàm arg, v.v. và xuất độ dài.
  • Chương trình sẽ luôn có hiệu lực và chỉ có 8 ký tự trong đó.

Unary -> Thông số kỹ thuật Brainfuck

  • Bạn sẽ phải thực hiện ngược lại của thuật toán trên.
  • Một lần nữa vì kích thước khổng lồ trong câu hỏi, đầu vào sẽ là một số mô tả độ dài của mã Unary.
  • Quy tắc I / O giống như mọi khi.
  • Chương trình sẽ luôn có hiệu lực và chỉ có 8 ký tự trong đó.

Các trường hợp thử nghiệm

  • Xin chào thế giới - ++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+.=239234107117088762456728667968602154633390994619022073954825877681363348343524058579165785448174718768772358485472231582844556848101441556
  • Fibonacci - ++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++>++++++++++++++++>>+<<[>>>>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>[<+>-]>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<.>.>>[>>+<<-]>[>+<<+>-]>[<+>-]<<<-]<<++...=13067995222095367150854793937817629722033205198624522624687536186118993888926522550140580142585590431635487113180955099384652678100247403485397450658564826143160529351955621991895221530908461364045400531236124980271740502887704217664044858614821622360156740992393765239123681327824577149595724956207165558106099868913919959549896553103116795519592552089266360725543244154867904980260

Đây là môn đánh gôn để điểm số thấp nhất tính bằng byte!

Bất cứ ai lên cho một giải pháp trong Unary? ; P


7
Một tiêu đề phù hợp hơn có lẽ sẽ là "Brainfuck to Golunar and Back"
Sp3000 7/07/2015

@ Sp3000 điểm tốt, nhưng tôi nghĩ rằng hầu hết mọi người chưa thực sự nghe về điều đó (bao gồm cả bản thân tôi).
Maltysen 7/07/2015

@Maltysen Tôi không nghĩ các trường hợp thử nghiệm của bạn là chính xác. Chẳng hạn, các chữ số hàng đầu của số đầu tiên trong nhị phân là 10101010101010, khi chúng phải là1010010010010
isaacg

@isaacg xin lỗi, đã đưa họ ra khỏi một trang web đang sử dụng một cơ chế dịch thuật khác, sẽ sửa.
Maltysen 7/07/2015

1
Chúng ta có thể chuyển đổi chúng thành một chương trình không chính xác như nhau, nhưng chính xác là như vậy không?
jimmy23013

Câu trả lời:


12

Pyth, 17 + 17 = 34 byte

BF -> Unary, 17 byte

i+1xL"><+-.,[]"z8

Unary -> BF, 17 byte

s@L"><+-.,[]"tjQ8

7

brainfuck , 563 335 318 316 296 + 529 373 366 336 = 632 byte

Vì điều này rõ ràng là thiếu một giải pháp trong một ngôn ngữ liên quan, đây là giải pháp trong brainfuck và Golunar. Tôi không thể đăng câu trả lời một cách đơn phương, bởi vì điều đó sẽ cần bộ nhớ gấp vài triệu lần so với các nguyên tử trong vũ trụ ^^

Thói quen "quay lại" sẽ không kiểm tra xem mã Golunar / Unary có hợp lệ không. Nếu bit đếm mod 3! = 1 thì nó sẽ chạy thành một vòng lặp vô tận in rất nhiều ">" s.

Cảm ơn Nitrodon vì đã giúp tôi nhận được dưới 300 ký tự cho mã bf để unary mã

cân não

->+>>>>,[>+++[>+++++<-]>[<+<---->>-]<<--[<+>++[<<+>>>[<+>-]<[<->++[<<<+>->+>-[<->--[<<+>>>+++++++++[<----->-]<[<+>--]]]]]]]>[-]>>,]<<<<+[<+]>[>]->+[<]>+[[->+]->[->[<++>-[<++>-[<++>-[<++>-[<-------->>[-]++<-[<++>-]]]]]]<[>+<-]+>>]<<[<<]>[<]>-[[->+]->>+<[<<]>[<]]>+]>[>>]<<[+++++++[>++++++<-]>.<<<]

Hãy thử trực tuyến!

và quay lại

->>,[<++++++[>--------<-]+>>>>>>,]>->-<<<+[-<+]>[[->[->+<[->->+>]<[<<<]>]<+>>>[-<<+>>]<[>>>>++++++++++<<<<-]>>>]>>>+[->+]>-<+[-<+]-<[>>+[->+]-<++[-<+]-<[-]]<<<<<<[<<<<<]>>>>>>[<<]<[->>>]>>]>>>+[->+]<-<+[-[<++>-]<[<++>-]>+++[>+++++<-]>[<+<++++>>-]<<++<[>--<-[>>[<->-]<--<-[>++<-[>+<-[>--<-[>+[>+<-]>[<++>-]<+<-[>++<-]]]]]]]>.[-]>[-]<<<+]

Hãy thử trực tuyến!

Golunar / unary-chữ số, 509 303 288 286 268 + 478 337 331 304 = 572 byte

cân não

2845581296974449674357817038179762273623136917867627972159702240227366875240878616687779429553529795902322625321040063298921498529640547483869509829184440577052825434462245755576011912505085065586076069824710351537537205287083477698633592357950165322060367940923703887

và quay lại

3775574485023133646619269732540391678811443648964274086227256847322821618228135493733703990523803451383315165001915937932498966394771849173263120467073642011339214182483748816052890450078070151307011943625602391238338941712116968736593594971620990210178757280976709140113340322124688909388916094040773207

Mã nguồn

cân não

[
unary:
><+-.,[]
01234567

62 > 62
60 < -2
45 - 15
43 + 2
44 , 1
46 . 2
91 [ 45
93 ] 2

tape (while reading input): Left tape end marker/LTE, [binary data], input, 15, (15 multiplicator)
tape (while base conversion): LTE, [binary data], Value Start/VS, [decimal digits]

decimal digits: digit used/DU, value
]

-                       set LTE
>+                      set leading 1
>>>>,[                  while input
  >+++[>+++++<-]        set 15 (multiplicator)
  >[<+<---->>-]         set 15 and decrease input by 60

                    check for greater than
                        set current bits = 000 (greater than)
  <<--[                 if input != 62 try next char

                    check for less than
  <+>                   set current bits = 001 (less than)
  ++[                   if input != 60 try next char

                    check for minus
  <<+>>                 set current bits = 011 (minus)
  >[<+>-]<[             if input != 45 try next char

                    check for plus
  <->                   set current bits = 010 (plus)
  ++[                   if input != 43 try next char

                    check for comma
  <<<+>->+>             set current bits = 101 (comma)
  -[                    if input != 44 try next char

                    check for dot
  <->                   set current bits = 100 (dot)
  --[                   if input != 46 try next char

                    check for left bracket
  <<+>>                set current bits = 110 (left bracket)
  >+++++++++[<----->-]<[   if input != 91 go to next char


                    use right bracket
  <+>                   set current bits = 111 (right bracket)
  --                    decrease input by 2 / should be 0 now

  ]]]]]]]               close all ifs
  >[-]>>                delete 15 if still existant
  ,                     input next character
]
<<<<+[<+]>[>]           add one to each bit and delete LTE (for shorter search routine)

                    Start of binary to decimal routine

-                       set value start marker (VS)
>+                      set digit used marker (DU)
[<]                     go to LTE

                    binary to decimal loop: use "double and add algorithm" to calculate the digits of the decimal value
>+[                     if not on VS then
  [->+]-                restore current bit value and go to VS
  >                     go to first DU
  [                     digit doubling loop
    ->                  remove DU and go to corresponding digit
    [
      <++>-             decrement current value and add 2 to temp value four times
      [
        <++>-
        [
          <++>-
          [
            <++>-
            [                   if value was greater than 4 then
              <---- ----        subtract 8 from temp
              >>[-]++           set next digit temp = 2 (DU plus 1)
              <-                decrement current digit
              [<++>-]           set temp = remaining value * 2
            ]
          ]
        ]
      ]
    ]
    <[>+<-]             set current digit = temp
    +                   set DU
    >>                  go to next digit
  ]                     end of digit doubling loop
  <<[<<]>[<]>           go to current bit
  -[                    if bit is 2 (used plus 1)
    [->+]-              delete bit and go to VS
    >>+                 increment least significant digit
    <[<<]>[<]           go to current bit
  ]
  >+                    if not on VS then repeat  
]                   end of binary to decimal loop

>[>>]<                  go to most significant digit
<[                  printing loop: for each DU print corresponding value
  +++++++[>++++++<-]>.  add 48 to value (ASCII 0) and print
  <<<                   go to next DU
]

và quay lại

[
tape: left tape end marker/LTE(-1), [digits], digit end marker/DE(0), carry, SB(-1), [binary data], 60, 15
digits: digit used marker/DU(1), digit, remainder, solution, 0
        else]                                    [exit else, exit if
binary data: value (, else, exit if, exit else)
]

                    input decimal value
->>                     set LTE
,[                      while input
  <++++++[>--------<-]  decrease input by 48
  +                     set DU
  >>>>> >,              input next digit
]
>->-                    set start of bits (SB) and first CCB
<<<+[-<+]>              delete LTE and go to first DU

                    division loop: calculate the remainders of the input divided by 2 repeatedly to get the (inverted) bits
[
                        divide each digit by 2
  [                     for each DU
    -                   delete DU (for exit if)
    >                   go to digit
    [->+<               dec digit / set remainder
      [->->+>]          if digit gt 0: dec digit / del remainder / inc solution / goto 0
                        pointer: (value(0) remainder is set) or (0 solution gt 1)
      <[<<<]            go to DU
      >                 go to digit
    ]
    <+                  set DU
    >>>[-<<+>>]         move solution to digit
    <[                  if remainder
      >>>>              go to next digit
      +++++ +++++       add 10 to digit/carry
      <<<<-             go back and delete remainder
    ]
    >>>                 go to next DU
  ]

                    append new bit
  >>>+[->+]             go to and delete CCB
  >-                    set new CCB
  <+[-<+]-<             go to carry
  [                     if carry
    >>+[->+]-<+         set last bit
    +[-<+]-<[-]         go to and clear carry
  ]

                    check if first digit became 0 / neccessary to check if value has been completely processed
  < <<<<<[<<<<<]>>>>>   go to first DU
  >[                    if digit gt 0
    <<                  go to exit if
  ]<[                   else
    -                   delete DU
    >>>                 go to exit else of next digit
  ]
  >>                    go to DU / DE if all digits processed
]                   end of division loop

                    decode binary values
>>>+[->+]               go to and delete CCB (after last bit)
<-                      delete leading 1
<                       go to first bit


                    Start of bit decoder
[
unary:
><+-.,[]
01234567

62 > 62
60 < -2
43 + -17
45 - 2
46 . 1
44 , -2
91 [ 47
93 ] 2

tape: start of bytes marker/SB(-1), [binary data], 60(print char/PC), 15
]

+[-                     while not SB

                    Set least significant to octal value of three bits
  [<++>-]               if first bit set add 2 to second bit
  <[<++>-]              for each second bit add 2 to third bit

  >+++[>+++++<-]        multiplier 15
  >[<+<++++>>-]         setup table 60 15

                    run through the 8 possibilities

                    0 greater than
  <<++                  set PC = 62 (greater than)
  <[                    if value gt 0 go to next char

                    1 less than
  >--                   set PC = 60 (less than)
  <-[                   if value gt 1 go to next char

                    2 plus
  >>[<->-]<--           set PC = 43 (plus)
  <-[                   if value gt 1 go to next char

                    3 minus
  >++                   set PC = 45 (minus)
  <-[                   if value gt 1 go to next char

                    4 dot
  >+                    set PC = 46 (dot)
  <-[                   if value gt 1 go to next char

                    5 comma
  >--                   set PC = 44 (comma)
  <-[                   if value gt 1 go to next char

                    6 left bracket
  >+[>+<-]>[<++>-]<+    set PC = 91 (left bracket) (inc (45) / double (90) / inc (91))
  <-[                   if value gt 1 go to next char

                    7 right bracket
  >++                   set PC = 93 (right bracket)
  <-                    decrease value the last time to exit if

  ]]]]]]]               close all ifs
  >.[-]                 print char and clear PC
  >[-]                  clear 15 if still existant

  <<<                   go to next bits
  +                     repeat if not SB
]

1
Khi chuyển đổi sang Unary, bạn có thể trừ 60 trực tiếp từ ô nhập thay vì đặt nó vào ô riêng trước, tiết kiệm 16 byte. Có thể lưu thêm 4 byte bằng cách không tạo 45 ngay lập tức (do đó nén bố cục băng hơn nữa). Ngoài ra, việc kiểm tra các byte đầu vào theo thứ tự 01325467.
Nitrodon

Cách khác tôi muốn nói là tạo 45 trong khi bạn thêm 15 vào ô nhập.
Nitrodon

6

Python 2, 80 79 63 55 + 86 64 = 119 byte

Cảm ơn Sp3000 vì rất nhiều đề xuất của anh ấy , tiết kiệm rất nhiều byte.

Brainfuck thành Unary, 78 77 61 53 + 2 = 55 byte

Đã thêm hai byte vào tài khoản cho các xung quanh trên đầu vào.

print int(`[1]+map("><+-.,[]".find,input())`[1::3],8)

Unary to Brainfuck, 86 64 byte

print''.join("><+-.,[]"[int(i)]for i in oct(input())[2:]if'L'>i)

Kiểm tra nó trên ideone ở đây.



3

CJam, 35 byte

Brainfuck thành Unary, 17 byte

1r"><+-.,[]"f#+8b

Hãy thử trực tuyến.

Làm thế nào nó hoạt động

 r                e# Read a whitespace-separated token from STDIN.
            f     e# For each character in the token:
  "><+-.,[]" #    e#     Find its index in this string.
1             +   e# Prepend a 1 to the results.
               8b e# Convert to integer, using base 8 conversion.

Unary to Brainfuck, 18 byte

ri8b"><+-.,[]"f=1>

Hãy thử trực tuyến.

Làm thế nào nó hoạt động

r                  e# Read a whitespace separated token from STDIN.
 i                 e# Interpret as integer.
  8b               e# Convert to array using base 8 conversion.
              f    e# For each digit:
    "><+-.,[]" =   e#     Select the corresponding character from the string.
                1> e# Discard the first character.

2

Bash + lõi, 39 + 47 = 86

b2u.sh:

dc -e8i1`tr '<>+-.,[]' 0-7`p|tr -dc 0-9

u2b.sh:

dc -e8o?p|tr -dc 0-9|tr 0-7 '<>+-.,[]'|cut -c2-

Đầu ra thử nghiệm:

$ echo "++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+." | ./b2u.sh
239234206933197750788456456928845900180965531636435002144714670872282710109774487453364223333807054152602699434658684117337034763550216789 
$ echo 239234206933197750788456456928845900180965531636435002144714670872282710109774487453364223333807054152602699434658684117337034763550216789 | ./u2b.sh
++++++[>++++++++++++<-[>.>++++++++++[>++++++++++<-[>+.+++++++..+++.>++++[>+++++++++++<-[>.<+++[>----<-[>.<<<<<+++[>+++++<-[>.>>.+++.------.--------.>>+.
$

1
tr -dc 0-9 (và trong môn đánh gôn, bạn có thể cho rằng điều đó không ?bị
hủy bỏ

1

Japt , 13 + 13 = 26 byte

Brainfuck để Unary

i< n"><+-.,[]

Thử nó!

Giải trình:

i<               :Insert a "<" at the start of the string (representing 1)
   n             :Convert string to decimal by interpreting as:
    "><+-.,[]    : A base 8 number represented by the 8 characters of BF

Unary to Brainfuck

s"><+-.,[]" Å

Thử nó!

Giải trình:

s                :Convert decimal to string representation of:
 "><+-.,[]"      : Base 8 using the BF characters to represent the 8 digits
            Å    :Remove the extra "<" at the front

Ghi chú

Tôi không thể tìm thấy bài đăng meta, nhưng nếu bộ nhớ của tôi phục vụ các câu trả lời chính xác được phép giới hạn I / O ở các số mà ngôn ngữ của họ có thể hỗ trợ, miễn là họ thực hiện thuật toán sẽ hoạt động nếu ngôn ngữ bắt đầu hỗ trợ số lớn hơn. Đó là trường hợp ở đây, khả năng của Japt coi một chuỗi là "cơ sở nsử dụng các nký tự này cho các chữ số" chỉ có thể sử dụng numberkiểu dữ liệu ở phía bên kia của hoạt động và do đó, các trường hợp thử nghiệm sẽ không thực sự chạy thành công; các đầu ra của chương trình đầu tiên và đầu vào của chương trình thứ hai sẽ cưỡng chế số một mà có thể được biểu diễn như một number, thay vì sử dụng các con số thực tế. Đối với các số có thể được đại diện hoàn hảo bởi Japt'snumberkiểu dữ liệu các chương trình này sẽ hoạt động như mong muốn và nếu numberkiểu dữ liệu thay đổi để hỗ trợ số lớn hơn thì các chương trình này cũng sẽ bắt đầu hỗ trợ các số đó.


0

05AB1E , 33 (17 + 16) byte

Brainfuck đến Unary-length:

"><+-.,[]"sSk1š8β

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

"><+-.,[]"           # Push string "><+-.,[]"
          s          # Swap to take the (implicit) input
           S         # Convert it to a list of characters
            k        # Check for each the index in the string
             1š      # Prepend a 1 to the list of indices
               8β    # Convert the list to Base-8 (and output implicitly)

Unary-length đến Brainfuck

8в¦"><+-.,[]"sèJ

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

8в                  # Convert the (implicit) input-list from Base-8 to Base-10
  ¦                 # Remove the first 1
   "><+-.,[]"       # Push string "><+-.,[]"
             s      # Swap the list and string on the stack
              è     # Index each integer into this string
               J    # Join everything together (and output implicitly)

0

Phi tiêu , 77 + 142 = 219 byte

f(s)=>BigInt.parse('1'+s.split('').map('><+-.,[]'.indexOf).join(''),radix:8);

F(n)=>BigInt.parse(n).toRadixString(8).split('').map((s)=>'><+-.,[]'.substring(int.parse(s),int.parse(s)+1)).join('').toString().substring(1);

Hãy thử trực tuyến!


0

C (gcc) , 254 byte

#include"gmp.h"
f(i,o)char*i,*o;{mpz_t l;char*c="><+-.,[]";if(*i>47&*i<58)for(mpz_init_set_str(l,i,0),mpz_get_str(o,8,l);*o;*o++=o[1]?c[o[1]-48]:0);else for(mpz_init_set_si(l,1);mpz_get_str(o,10,l),*i;mpz_mul_si(l,l,8),mpz_add_ui(l,l,strchr(c,*i++)-c));}

Hãy thử trực tuyến!

Xác định hướng đi nào dựa trên đầu vào ( i), lưu kết quả vào bộ đệm đã truyền ( o). Lưu ý rằng một số trình biên dịch cho phép lưu 4 byte dựa trên thứ tự được xác định theo thực hiện của o ++. Trong những trường hợp này, giải pháp được cung cấp sẽ cắt bớt một ký tự phụ của chuyển đổi Unary-> BF và o[1]tất cả có thể được thay thế bằng cách *ophục hồi hành vi.


Ngôn ngữ phải là "C (gcc) + GMP" tại đây
ASCII - chỉ

Ngoài ra, đây có phải là một chương trình ngắn hơn 2? Và tôi cũng khuyên bạn nên đặt #include <string.h>chân trang thay vì tiêu đề để hiển thị nó hoạt động mà không cần nhập. C ++ cũng sẽ ngắn hơn vì quá tải toán tử? : P
ASCII - chỉ

Cũng không quan trọng, nhưng tôi muốn thay đổi tất cả siđể uicó thể
ASCII chỉ

*i>47&*i<58-> *i%48<10?
ASCII chỉ

cũng mpz_init_set_str->mpz_set_str
ASCII - chỉ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.