Brainf ** k à Unary et Back

15

Unaire qui est très utile dans les sources restreintes et d'autres défis de ce type est Unary , un dérivé de brainfuck dans lequel les programmes sont écrits avec un seul caractère. Votre travail consiste à écrire un programme pour convertir des programmes de brainfuck en unaire et un programme pour faire le contraire, les deux programmes dans la même langue. Votre score sera la somme des durées des deux programmes.

Comment passez-vous du brainfuck au unary?

  • Convertissez d'abord votre code brainfuck en binaire selon ce tableau:

Table de conversion

  • Maintenant, concaténez le code en un nombre binaire géant dans l'ordre du code.
  • Ajoutez un 1à la chaîne pour garantir un nombre binaire unique.
  • Convertissez d'un nombre binaire en un nombre unaire en utilisant n'importe quel caractère.
  • Ex: +.serait 000000000000000000000000000000000000000000000000000000000000000000000000000000000000(84 zéros).

Brainfuck -> Spécifications unaires

  • Étant donné que les programmes résultants seront incroyablement énormes, n'imprimez pas le programme réel mais simplement la longueur du programme résultant.
  • Prenez le programme brainfuck sous forme de chaîne via stdin, la fonction arg, etc. et affichez la longueur.
  • Le programme sera toujours valide et ne comportera que ces 8 caractères.

Unaire -> Spécifications Brainfuck

  • Vous devrez implémenter l'inverse de l'algorithme ci-dessus.
  • Encore une fois, en raison des énormes tailles en question, l'entrée sera un nombre décrivant la longueur du code Unary.
  • Mêmes règles d'E / S que d'habitude.
  • Le programme sera toujours valide et ne comportera que ces 8 caractères.

Cas de test

  • Bonjour tout le monde - ++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+.=239234107117088762456728667968602154633390994619022073954825877681363348343524058579165785448174718768772358485472231582844556848101441556
  • Fibonacci - ++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++>++++++++++++++++>>+<<[>>>>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>[<+>-]>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<.>.>>[>>+<<-]>[>+<<+>-]>[<+>-]<<<-]<<++...=13067995222095367150854793937817629722033205198624522624687536186118993888926522550140580142585590431635487113180955099384652678100247403485397450658564826143160529351955621991895221530908461364045400531236124980271740502887704217664044858614821622360156740992393765239123681327824577149595724956207165558106099868913919959549896553103116795519592552089266360725543244154867904980260

C'est le code-golf donc le score le plus bas en octets gagne!

Quelqu'un veut une solution dans Unary? ; P

Maltysen
la source
7
Un titre plus approprié serait probablement "Brainfuck to Golunar and Back"
Sp3000
@ Sp3000 bon point, mais je pense que la plupart des gens n'en ont pas vraiment entendu parler (moi y compris).
Maltysen
@Maltysen Je ne pense pas que vos cas de test soient corrects. Par exemple, les premiers chiffres du premier nombre en binaire sont 10101010101010, lorsqu'ils devraient l'être1010010010010
isaacg
@isaacg désolé, les a retirés d'un site Web qui utilisait un mécanisme de traduction différent, corrigera.
Maltysen
1
Pouvons-nous les convertir en un programme qui n'est pas exactement égal, mais fait exactement la même chose?
jimmy23013

Réponses:

12

Pyth, 17 + 17 = 34 octets

BF -> Unaire, 17 octets

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

Unaire -> BF, 17 octets

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

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

Comme il manquait manifestement une solution dans une langue apparentée, voici la solution dans brainfuck et Golunar. Je ne pouvais pas poster une réponse à l'unaire, car cela nécessiterait quelques fantastiques milliards de fois plus de mémoire qu'il n'y a d'atomes dans l'univers ^^

La routine "retour" ne vérifiera pas si le code Golunar / Unary est valide. Si le nombre de bits mod 3! = 1, il s'exécutera dans une boucle sans fin imprimant beaucoup de ">".

Merci à Nitrodon de m'avoir aidé à descendre en dessous de 300 caractères pour le code bf en unaire

brainfuck to unary

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

Essayez-le en ligne!

et retour

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

Essayez-le en ligne!

Golunar / chiffres unaires, 509 303 288 286 268 + 478 337 331 304 = 572 octets

brainfuck to unary

2845581296974449674357817038179762273623136917867627972159702240227366875240878616687779429553529795902322625321040063298921498529640547483869509829184440577052825434462245755576011912505085065586076069824710351537537205287083477698633592357950165322060367940923703887

et retour

3775574485023133646619269732540391678811443648964274086227256847322821618228135493733703990523803451383315165001915937932498966394771849173263120467073642011339214182483748816052890450078070151307011943625602391238338941712116968736593594971620990210178757280976709140113340322124688909388916094040773207

Codes sources

brainfuck to 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
]

et retour

[
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
la source
1
Lors de la conversion en Unary, vous pouvez soustraire le 60 directement de la cellule d'entrée au lieu de le placer dans sa propre cellule en premier, économisant 16 octets. Il est possible d'économiser 4 octets supplémentaires en ne créant pas le 45 immédiatement (ce qui compacte encore la disposition de la bande). De plus, il est légèrement golfeur de vérifier les octets d'entrée dans l'ordre 01325467.
Nitrodon
L'alternative que je voulais dire était de créer le 45 pendant que vous ajoutez 15 à la cellule d'entrée.
Nitrodon
6

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

Merci à Sp3000 pour ses nombreuses suggestions, permettant d' économiser beaucoup d'octets.

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

Ajout de deux octets pour tenir compte de l'entourage "en entrée.

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

Unaire à Brainfuck, 86 64 octets

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

Découvrez-le sur ideone ici.

Kade
la source
3

CJam, 35 octets

Brainfuck à Unary, 17 octets

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

Essayez-le en ligne.

Comment ça fonctionne

 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.

Unaire à Brainfuck, 18 octets

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

Essayez-le en ligne.

Comment ça fonctionne

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
la source
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-

Sortie de test:

$ echo "++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+." | ./b2u.sh
239234206933197750788456456928845900180965531636435002144714670872282710109774487453364223333807054152602699434658684117337034763550216789 
$ echo 239234206933197750788456456928845900180965531636435002144714670872282710109774487453364223333807054152602699434658684117337034763550216789 | ./u2b.sh
++++++[>++++++++++++<-[>.>++++++++++[>++++++++++<-[>+.+++++++..+++.>++++[>+++++++++++<-[>.<+++[>----<-[>.<<<<<+++[>+++++<-[>.>>.+++.------.--------.>>+.
$
Traumatisme numérique
la source
1
tr -dc 0-9 (et dans le golf de code, vous pouvez supposer que tout ?va bien)
izabera
1

Japt , 13 + 13 = 26 octets

Brainfuck to Unary

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

Essayez!

Explication:

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

Unaire à Brainfuck

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

Essayez!

Explication:

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

Remarques

Je ne trouve pas la méta-publication, mais si ma mémoire est correcte, les réponses sont autorisées à limiter les E / S aux nombres que leur langue peut prendre en charge, tant qu'ils implémentent un algorithme qui fonctionnerait si la langue commençait à prendre en charge des nombres plus importants. C'est le cas ici, la capacité de Japt à traiter une chaîne comme "base nutilisant ces ncaractères pour les chiffres" ne peut utiliser que le numbertype de données de l'autre côté de l'opération, et donc les cas de test ne s'exécuteront pas correctement; la sortie du premier programme et l' entrée du deuxième programme contraindront le nombre à un qui peut être représenté comme un number, plutôt que d'utiliser le nombre réel. Pour les nombres qui peuvent être parfaitement représentés par Japtnumbertype de données ces programmes fonctionneront comme vous le souhaitez et si le numbertype de données change pour prendre en charge de plus grands nombres, ces programmes commenceront également à prendre en charge ces nombres.

Kamil Drakari
la source
0

05AB1E , 33 (17 + 16) octets

Brainfuck à Unary-length:

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

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

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

Unaire à Brainfuck

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

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

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
la source
0

Fléchette , 77 + 142 = 219 octets

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

Essayez-le en ligne!

Elcan
la source
0

C (gcc) , 254 octets

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

Essayez-le en ligne!

Détermine la direction à prendre en fonction de input ( i), stocke le résultat dans le tampon passé ( o). Notez que certains compilateurs permettent d'économiser 4 octets en fonction de l'ordre défini par l'implémentation de l'o ++. Dans ces cas, la solution fournie tronquera un caractère supplémentaire de la conversion Unary-> BF et o[1]tous les caractères peuvent être remplacés par *opour récupérer le comportement.

LambdaBeta
la source
Le langage devrait être "C (gcc) + GMP" ici
ASCII uniquement
De plus, est-ce plus court en un programme qu'en deux? Et je recommanderais également de mettre #include <string.h>le pied de page au lieu de l'en-tête pour montrer que cela fonctionne sans cette importation. De plus, le C ++ ne serait-il pas plus court en raison de la surcharge de son opérateur? : P
ASCII uniquement
Pas important non plus, mais je changerais chaque sien uipeut
ASCII uniquement
*i>47&*i<58-> *i%48<10?
ASCII uniquement
aussi mpz_init_set_str->mpz_set_str
ASCII uniquement