Мозг ** к Унару и обратно


15

Язык , который очень полезен в ограниченном источнике и других подобных проблемах является Унарным , Brainfuck производным , в котором программы записываются с использованием только один символом. Ваша работа состоит в том, чтобы написать программу для конвертации программ из brainfuck в унарные и программу для обратного - обе программы на одном языке. Ваша оценка будет суммой длин двух программ.

Как вы конвертируете из brainfuck в унарный?

  • Сначала преобразуйте ваш код в формате brainfuck в двоичный код в соответствии с таблицей

Таблица преобразования

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

Brainfuck -> Унарные характеристики

  • Поскольку результирующие программы будут невероятно огромными, выведите не саму программу, а только ее длину.
  • Возьмите программу brainfuck как строку через stdin, функцию arg и т. Д. И выведите длину.
  • Программа всегда будет действительной и в ней будут только эти 8 символов.

Унарный -> Brainfuck Specs

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

Тестовые случаи

  • Hello World - ++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+.=239234107117088762456728667968602154633390994619022073954825877681363348343524058579165785448174718768772358485472231582844556848101441556
  • Фибоначчи - ++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++>++++++++++++++++>>+<<[>>>>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>[<+>-]>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<.>.>>[>>+<<-]>[>+<<+>-]>[<+>-]<<<-]<<++...=13067995222095367150854793937817629722033205198624522624687536186118993888926522550140580142585590431635487113180955099384652678100247403485397450658564826143160529351955621991895221530908461364045400531236124980271740502887704217664044858614821622360156740992393765239123681327824577149595724956207165558106099868913919959549896553103116795519592552089266360725543244154867904980260

Это код-гольф, поэтому выигрывает самая низкая оценка в байтах!

Кто-нибудь ищет решение в Унарном? ;П


7
Более подходящее название, вероятно, будет « Головоломка на Голунар и обратно»
Sp3000

@ Sp3000 хорошая мысль, но я думаю, что большинство людей на самом деле не слышали об этом (включая меня).
Maltysen

@ Maltysen Я не думаю, что ваши тесты правильны. Например, первые цифры первого числа в двоичном виде 10101010101010, когда они должны быть1010010010010
isaacg

@isaacg извините, вытащил их с сайта, который использовал другой механизм перевода, исправлю.
Maltysen

1
Можем ли мы преобразовать их в программу, которая не совсем совпадает, но делает то же самое?
jimmy23013

Ответы:


12

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

BF -> Unary, 17 байт

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

Унарный -> BF, 17 байт

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

7

брейнфук , 563 335 318 316 296 + 529 373 366 336 = 632 байта

Поскольку это, очевидно, упускало решение на родственном языке, вот решение в Brainfuck и Golunar. Я не смог опубликовать ответ в унарном виде, потому что для этого потребовалось бы в несколько раз больше памяти, чем атомов во вселенной ^^

Процедура «назад» не проверяет, действителен ли голунарный / унарный код. Если число битов mod 3! = 1, то это приведет к бесконечному циклу печати большого количества символов «>».

Спасибо Nitrodon за то, что помог мне получить менее 300 символов для двоичного кода в унарный код

мозговой трах к одинарному

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

Попробуйте онлайн!

и назад

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

Попробуйте онлайн!

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

Альтернативой, которую я имел в виду, было создание 45, а вы добавляете 15 в ячейку ввода.
Нитродон

6

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

Спасибо Sp3000 за его многочисленные предложения, экономящие много байтов.

Brainfuck to Unary, 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 to Unary, 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.

Унарный Брейнфак, 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 байт

Brainfuck в Унар

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

Унарный Брейнфак

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, а не с помощью фактического числа. Для чисел, которые могут быть прекрасно представлены в ЯптnumberТип данных, эти программы будут работать по желанию, и если numberтип данных изменится для поддержки больших чисел, то эти программы также начнут поддерживать эти числа.


0

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

Brainfuck в одинарную длину:

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

Попробуйте онлайн!

Определяет, в каком направлении идти на основе input ( i), сохраняет результат в переданном буфере ( o). Обратите внимание, что некоторые компиляторы позволяют сохранять 4 байта в зависимости от порядка реализации ++. В этих случаях предоставленное решение будет обрезать дополнительный символ от преобразования 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.