Brainf ** k ke Unary dan Back

15

Bahasa yang sangat berguna dalam sumber terbatas dan tantangan lainnya adalah Unary , turunan brainfuck di mana program ditulis dengan hanya satu karakter. Tugas Anda adalah menulis program untuk mengubah program dari brainfuck ke unary dan program untuk melakukan yang sebaliknya, kedua program dalam bahasa yang sama. Skor Anda akan menjadi jumlah dari panjang kedua program.

Bagaimana Anda mengubah dari brainfuck ke unary?

  • Pertama-tama ubah kode brainfuck Anda menjadi biner berdasarkan tabel ini:

Tabel Konversi

  • Sekarang menyatukan kode menjadi satu nomor biner raksasa dalam urutan kode.
  • Tambahkan a 1ke string untuk memastikan nomor biner yang unik.
  • Konversi dari angka biner ke angka unary menggunakan karakter apa saja.
  • Mis: +.akan 000000000000000000000000000000000000000000000000000000000000000000000000000000000000(84 nol).

Brainfuck -> Spesifikasi Unary

  • Karena program yang dihasilkan akan sangat besar, cetak bukan program yang sebenarnya tetapi hanya panjang dari program yang dihasilkan.
  • Ambil program brainfuck sebagai string melalui stdin, function arg, dll dan outputkan panjangnya.
  • Program ini akan selalu valid dan hanya memiliki 8 karakter di dalamnya.

Unary -> Spesifikasi Brainfuck

  • Anda harus menerapkan kebalikan dari algoritma di atas.
  • Sekali lagi karena ukurannya yang besar, inputnya berupa angka yang menjelaskan panjang kode Unary.
  • Aturan I / O yang sama seperti biasa.
  • Program ini akan selalu valid dan hanya memiliki 8 karakter di dalamnya.

Uji Kasus

  • Hello World - ++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+.=239234107117088762456728667968602154633390994619022073954825877681363348343524058579165785448174718768772358485472231582844556848101441556
  • Fibonacci - ++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++>++++++++++++++++>>+<<[>>>>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>[<+>-]>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<.>.>>[>>+<<-]>[>+<<+>-]>[<+>-]<<<-]<<++...=13067995222095367150854793937817629722033205198624522624687536186118993888926522550140580142585590431635487113180955099384652678100247403485397450658564826143160529351955621991895221530908461364045400531236124980271740502887704217664044858614821622360156740992393765239123681327824577149595724956207165558106099868913919959549896553103116795519592552089266360725543244154867904980260

Ini adalah kode-golf sehingga skor terendah dalam byte menang!

Adakah yang mencari solusi di Unary? ; P

Maltysen
sumber
7
Judul yang lebih tepat mungkin adalah "Brainfuck to Golunar and Back"
Sp3000
@ Sp3000 poin bagus, tapi saya pikir kebanyakan orang belum pernah mendengarnya (termasuk saya sendiri).
Maltysen
@Maltysen Saya tidak berpikir test case Anda benar. Sebagai contoh, digit utama dari angka pertama dalam biner adalah 10101010101010, ketika seharusnya1010010010010
isaacg
@isaacg maaf, mengeluarkan mereka dari situs web yang menggunakan mekanisme terjemahan yang berbeda, akan diperbaiki.
Maltysen
1
Bisakah kita mengonversikannya ke program yang tidak persis sama, tetapi melakukan hal yang persis sama?
jimmy23013

Jawaban:

12

Pyth, 17 + 17 = 34 byte

BF -> Unary, 17 byte

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

Unary -> BF, 17 byte

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

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

Karena ini jelas kehilangan solusi dalam bahasa terkait, berikut adalah solusi dalam brainfuck dan Golunar. Saya tidak dapat memposting jawaban di unary, karena itu akan membutuhkan memori fantastis jutaan kali lebih banyak daripada ada atom di alam semesta ^^

Rutin "kembali" tidak akan memeriksa apakah kode Golunar / Unary valid. Jika bit hitung mod 3! = 1 maka itu akan menjadi loop tak berujung yang mencetak banyak ">" s.

Terima kasih kepada Nitrodon karena membantu saya mendapatkan di bawah 300 karakter untuk bf ke kode unary

brainfuck ke unary

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

Cobalah online!

dan kembali

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

Cobalah online!

Golunar / digit-unary, 509 303 288 286 268 + 478 337 331 304 = 572 byte

brainfuck ke unary

2845581296974449674357817038179762273623136917867627972159702240227366875240878616687779429553529795902322625321040063298921498529640547483869509829184440577052825434462245755576011912505085065586076069824710351537537205287083477698633592357950165322060367940923703887

dan kembali

3775574485023133646619269732540391678811443648964274086227256847322821618228135493733703990523803451383315165001915937932498966394771849173263120467073642011339214182483748816052890450078070151307011943625602391238338941712116968736593594971620990210178757280976709140113340322124688909388916094040773207

Kode sumber

brainfuck ke unary

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

dan kembali

[
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
]
Dorian
sumber
1
Saat mengonversi ke Unary, Anda dapat mengurangi 60 langsung dari sel input alih-alih memasukkannya ke dalam selnya sendiri terlebih dahulu, menghemat 16 byte. Lebih lanjut 4 byte dapat disimpan dengan tidak membuat 45 segera (sehingga memadatkan tata letak kaset lebih jauh). Selain itu, sedikit lebih golf untuk memeriksa byte input dalam urutan 01325467.
Nitrodon
Alternatif yang saya maksudkan adalah membuat 45 saat Anda menambahkan 15 ke sel input.
Nitrodon
6

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

Terima kasih kepada Sp3000 untuk banyak sarannya, menghemat banyak byte.

Brainfuck to Unary, 78 77 61 53 + 2 = 55 byte

Menambahkan dua byte ke akun untuk input yang ada di sekitarnya.

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)

Lihatlah ideone di sini.

Kade
sumber
3

CJam, 35 byte

Brainfuck to Unary, 17 byte

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

Cobalah online.

Bagaimana itu bekerja

 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>

Cobalah online.

Bagaimana itu bekerja

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.
Dennis
sumber
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-

Hasil tes:

$ echo "++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+." | ./b2u.sh
239234206933197750788456456928845900180965531636435002144714670872282710109774487453364223333807054152602699434658684117337034763550216789 
$ echo 239234206933197750788456456928845900180965531636435002144714670872282710109774487453364223333807054152602699434658684117337034763550216789 | ./u2b.sh
++++++[>++++++++++++<-[>.>++++++++++[>++++++++++<-[>+.+++++++..+++.>++++[>+++++++++++<-[>.<+++[>----<-[>.<<<<<+++[>+++++<-[>.>>.+++.------.--------.>>+.
$
Trauma Digital
sumber
1
tr -dc 0-9 (dan dalam kode golf Anda dapat menganggap itu ?baik-baik saja tidak
terhindarkan
1

Japt , 13 + 13 = 26 byte

Brainfuck to Unary

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

Cobalah!

Penjelasan:

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

Cobalah!

Penjelasan:

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

Catatan

Saya tidak dapat menemukan posting meta, tetapi jika ingatan saya berfungsi dengan benar, jawaban diizinkan membatasi I / O ke angka yang dapat didukung bahasa mereka, asalkan mereka menerapkan algoritma yang akan berfungsi jika bahasa mulai mendukung angka yang lebih besar. Itulah yang terjadi di sini, kemampuan Japt untuk memperlakukan string sebagai "basis nmenggunakan nkarakter ini untuk digit" hanya dapat menggunakan numbertipe data di sisi lain operasi, dan dengan demikian kotak uji tidak akan benar-benar berjalan dengan sukses; yang keluaran dari program pertama dan masukan dari program kedua akan memaksa nomor satu yang dapat direpresentasikan sebagai number, daripada menggunakan jumlah aktual. Untuk angka yang dapat diwakili dengan sempurna oleh Japt'snumbertipe data program ini akan bekerja seperti yang diinginkan, dan jika numbertipe data berubah untuk mendukung angka yang lebih besar maka program ini akan mulai mendukung angka-angka itu juga.

Kamil Drakari
sumber
0

05AB1E , 33 (17 + 16) byte

Brainfuck to Unary-length:

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

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

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

Panjangnya tidak sama dengan Brainfuck

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

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

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)
Kevin Cruijssen
sumber
0

Dart , 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);

Cobalah online!

Elcan
sumber
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));}

Cobalah online!

Menentukan arah yang akan diambil berdasarkan input ( i), menyimpan hasilnya dalam buffer yang diteruskan ( o). Perhatikan bahwa beberapa kompiler memungkinkan penghematan 4 byte berdasarkan pada urutan o ++ yang ditentukan implementasi. Dalam kasus ini solusi yang disediakan akan memotong karakter tambahan dari konversi Unary-> BF dan o[1]semuanya dapat diganti dengan *ountuk memulihkan perilaku.

LambdaBeta
sumber
Bahasanya harus "C (gcc) + GMP" di sini
ASCII-hanya
Juga, apakah ini lebih pendek sebagai satu program daripada 2? Dan saya juga merekomendasikan menempatkan #include <string.h>footer daripada header untuk menunjukkan itu berfungsi tanpa impor itu. Juga bukankah C ++ lebih pendek karena operatornya kelebihan beban? : P
ASCII-hanya
Juga tidak penting, tapi saya akan mengubah setiap siuntuk uimungkin
ASCII-hanya
*i>47&*i<58-> *i%48<10?
ASCII
juga mpz_init_set_str->mpz_set_str
ASCII-hanya