Brainf ** k до Унарії та Назад


15

Мова , який дуже корисний в обмеженому джерелі і інших подібних проблемах є унарна , Brainfuck похідним , в якому програми записуються з використанням тільки один символом. Ваше завдання полягає в тому, щоб написати програму для перетворення програм з головного мозку в одинарну і програму зробити навпаки, обидві програми однією і тією ж мовою. Ваша оцінка буде сумою тривалості двох програм.

Як ти перетворюєшся з мозку в одинарний?

  • Спершу перетворіть ваш код, що є мозком, у двійковий відповідно до цієї таблиці:

Таблиця переходів

  • Тепер об'єднайте код в одне гігантське двійкове число в порядку коду.
  • Додайте 1до рядка, щоб забезпечити унікальне двійкове число.
  • Перетворити з двійкового числа в одинарне число, використовуючи будь-який символ.
  • Наприклад: +.буде 000000000000000000000000000000000000000000000000000000000000000000000000000000000000(84 нулі).

Brainfuck -> Одинарні характеристики

  • Оскільки отримані програми будуть неможливо величезними, друкуйте не фактичну програму, а лише довжину отриманої програми.
  • Візьміть програму brainfuck як рядок через stdin, function arg тощо та виведіть довжину.
  • Програма завжди буде дійсною та матиме лише ті 8 символів.

Unary -> Характеристики Brainfuck

  • Вам доведеться реалізувати реверс вищевказаного алгоритму.
  • Знову через великі розміри, про які йдеться, вхідним числом буде число, що описує довжину коду Унар.
  • Ті ж правила вводу / виводу, як завжди.
  • Програма завжди буде дійсною та матиме лише ті 8 символів.

Випробування

  • Привіт Світ - ++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+.=239234107117088762456728667968602154633390994619022073954825877681363348343524058579165785448174718768772358485472231582844556848101441556
  • Фібоначчі - ++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++>++++++++++++++++>>+<<[>>>>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>[<+>-]>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<.>.>>[>>+<<-]>[>+<<+>-]>[<+>-]<<<-]<<++...=13067995222095367150854793937817629722033205198624522624687536186118993888926522550140580142585590431635487113180955099384652678100247403485397450658564826143160529351955621991895221530908461364045400531236124980271740502887704217664044858614821622360156740992393765239123681327824577149595724956207165558106099868913919959549896553103116795519592552089266360725543244154867904980260

Це кодовий гольф, тому найнижчий бал у байтах виграє!

Хтось шукає рішення в Унар? ; P


7
Більш підходящим заголовком, напевно, став би "Brainfuck to Golunar and Back"
Sp3000

@ Sp3000 хороший момент, але я вважаю, що більшість людей насправді не чули про це (як я включав).
Мальтісен

@Maltysen Я не думаю, що ваші тестові випадки є правильними. Наприклад, провідні цифри першого числа у двійковій 101010101010101010010010010
формі

@isaacg вибачте, вимкніть їх на веб-сайті, який використовував інший механізм перекладу, виправите.
Мальтісен

1
Чи можемо ми перетворити їх у програму, не зовсім рівну, але робить точно те саме?
jimmy23013

Відповіді:


12

Pyth, 17 + 17 = 34 байти

BF -> Одинарний, 17 байт

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

Одинарний -> BF, 17 байт

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

7

brainfuck , 563 335 318 316 296 + 529 373 366 336 = 632 байт

Оскільки це, очевидно, не вистачало рішення спорідненою мовою, ось це рішення в мозковій дусі та Голунарі. Я не міг опублікувати відповідь не одинаково, тому що для цього знадобиться в кілька фантастичних мільйонів більше пам’яті, ніж є атоми у Всесвіті ^^

Процедура "назад" не перевірить, чи дійсний код Голунар / Унар. Якщо біт лічильник mod 3! = 1, він зіткнеться з нескінченним циклом, що друкує багато ">" s.

Дякую Nitrodon за те, що він допоміг мені отримати менше 300 знаків для BF для одинакового коду

ебать мозку до одинаку

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

Спробуйте в Інтернеті!

і назад

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

Спробуйте в Інтернеті!

Голунар / унар -цифри, 509 303 288 286 268 + 478 337 331 304 = 572 байти

ебать мозку до одинаку

2845581296974449674357817038179762273623136917867627972159702240227366875240878616687779429553529795902322625321040063298921498529640547483869509829184440577052825434462245755576011912505085065586076069824710351537537205287083477698633592357950165322060367940923703887

і назад

3775574485023133646619269732540391678811443648964274086227256847322821618228135493733703990523803451383315165001915937932498966394771849173263120467073642011339214182483748816052890450078070151307011943625602391238338941712116968736593594971620990210178757280976709140113340322124688909388916094040773207

Вихідні коди

ебать мозку до одинаку

[
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
]

і назад

[
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
При переході в Unary ви можете відняти 60 безпосередньо з вхідної комірки, а не помістити її спочатку у свою комірку, заощадивши 16 байт. Ще 4 байти можна зберегти, не створивши 45 одразу (тим самим ще більше ущільнивши макет стрічки). Крім того, трохи побільше перевірити вхідні байти в порядку 01325467.
Nitrodon

Альтернатива, яку я мав на увазі, - створити 45, поки ви додаєте 15 до вхідної комірки.
Нітродон

6

Python 2, 80 79 63 55 + 86 64 = 119 Байт

Завдяки Sp3000 за численні пропозиції, економив багато байтів.

Brainfuck до Unar, 78 77 61 53 + 2 = 55 байт

Додано два байти для обліку оточуючих "вхідних даних".

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

Unary to Brainfuck, 86 64 байт

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

Перевірте це на ideone тут.



3

CJam, 35 байт

Brainfuck до Unar, 17 байт

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

Спробуйте в Інтернеті.

Як це працює

 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.

Унарна до Brainfuck, 18 байт

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

Спробуйте в Інтернеті.

Як це працює

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 + coreutils, 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-

Тестовий вихід:

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

1
tr -dc 0-9 (і в коді гольфу ви можете припустити, що ?це нормально без
змін

1

Japt , 13 + 13 = 26 байт

Мозговий ебать до Унар

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

Спробуй це!

Пояснення:

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

Одинарний до Brainfuck

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

Спробуй це!

Пояснення:

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

Примітки

Я не можу знайти мета-повідомлення, але якщо моя пам'ять служить правильно, відповіді дозволяють обмежувати введення-виведення на числа, які може підтримувати їх мова, якщо вони реалізують алгоритм, який би працював, якщо мова почне підтримувати більші числа. Ось такий випадок, що можливість Japt трактувати рядок як "базу, що nвикористовує ці nсимволи для цифр" може використовувати лише numberтип даних на іншій стороні операції, і, таким чином, тестові випадки насправді не запускаються успішно; вихід першої програми і введення другої програми будуть примушувати номер на той , який може бути представлений у вигляді number, а не з допомогою фактичного числа. Для номерів, які можуть бути ідеально представлені Japt'snumberтип даних ці програми працюватимуть за бажанням, і якщо numberтип даних зміниться для підтримки більшої кількості, то ці програми також почнуть підтримувати ці числа.


0

05AB1E , 33 (17 + 16) байт

Мозговий ебать до унарної довжини:

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

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

"><+-.,[]"           # 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)

Одинарна довжина до Brainfuck

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

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

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

C (gcc) , 254 байт

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

Спробуйте в Інтернеті!

Визначає, в якому напрямку рухатися на основі введення ( i), зберігає результат у переданому буфері ( o). Зауважте, що деякі компілятори дозволяють зберегти 4 байти на основі впорядкованого впорядкування o ++. У цих випадках запропоноване рішення дозволить урізати додатковий символ від перетворення Unary-> BF, і все це o[1]може бути замінено *oна відновлення поведінки.


Мова повинна бути "C (gcc) + GMP" тут
ASCII лише

Крім того, це коротше як одна програма, ніж як 2? І я також рекомендую ввести #include <string.h>колонтитул замість заголовка, щоб показати, що він працює без цього імпорту. Також не став би C ++ коротшим через його перевантаження оператором? : P
лише ASCII

Також не важливо, але я б змінив кожного siна uiможливо
ASCII лише

*i>47&*i<58-> *i%48<10?
ASCII лише

також mpz_init_set_str->mpz_set_str
лише ASCII
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.