Brainf ** k a Unary y Back


15

Un lenguaje que es muy útil en fuentes restringidas y otros desafíos similares es Unary , un derivado de brainfuck en el que los programas se escriben con un solo carácter. Su trabajo es escribir un programa para convertir programas de brainfuck a unary y un programa para hacer lo contrario, ambos programas en el mismo idioma. Su puntaje será la suma de las duraciones de los dos programas.

¿Cómo se convierte de brainfuck a unario?

  • Primero convierta su código de brainfuck a binario de acuerdo con esta tabla:

Tabla de conversión

  • Ahora concatene el código en un número binario gigante en el orden del código.
  • Anteponga a 1a la cadena para asegurar un número binario único.
  • Convierte de un número binario a un número unario usando cualquier carácter.
  • Ej: +.sería 000000000000000000000000000000000000000000000000000000000000000000000000000000000000(84 ceros).

Brainfuck -> Especificaciones Unarias

  • Dado que los programas resultantes serán imposiblemente enormes, no imprima el programa real sino simplemente la duración del programa resultante.
  • Tome el programa brainfuck como una cadena a través de stdin, función arg, etc. y genere la longitud.
  • El programa siempre será válido y solo tendrá esos 8 caracteres.

Unary -> Especificaciones Brainfuck

  • Tendrá que implementar el reverso del algoritmo anterior.
  • Nuevamente, debido a los enormes tamaños en cuestión, la entrada será un número que describa la longitud del código Unary.
  • Las mismas reglas de E / S que siempre.
  • El programa siempre será válido y solo tendrá esos 8 caracteres.

Casos de prueba

  • Hola mundo - ++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+.=239234107117088762456728667968602154633390994619022073954825877681363348343524058579165785448174718768772358485472231582844556848101441556
  • Fibonacci - ++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++>++++++++++++++++>>+<<[>>>>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>[<+>-]>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<.>.>>[>>+<<-]>[>+<<+>-]>[<+>-]<<<-]<<++...=13067995222095367150854793937817629722033205198624522624687536186118993888926522550140580142585590431635487113180955099384652678100247403485397450658564826143160529351955621991895221530908461364045400531236124980271740502887704217664044858614821622360156740992393765239123681327824577149595724956207165558106099868913919959549896553103116795519592552089266360725543244154867904980260

Este es el código de golf, por lo que gana la puntuación más baja en bytes.

¿Alguien quiere una solución en Unary? ;PAG


77
Un título más apropiado probablemente sería "Brainfuck to Golunar and Back"
Sp3000

@ Sp3000 buen punto, pero creo que la mayoría de la gente realmente no ha oído hablar de eso (incluido yo).
Maltysen

@ Maltysen No creo que sus casos de prueba sean correctos. Por ejemplo, los dígitos 101010101010101010010010010
iniciales

@isaacg lo siento, los arreglé de un sitio web que estaba usando un mecanismo de traducción diferente, lo arreglará.
Maltysen

1
¿Podemos convertirlos a un programa que no sea exactamente igual, pero que haga exactamente lo mismo?
jimmy23013

Respuestas:


12

Pyth, 17 + 17 = 34 bytes

BF -> Unario, 17 bytes

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

Unario -> BF, 17 bytes

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

7

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

Dado que obviamente faltaba una solución en un lenguaje relacionado, aquí está la solución en brainfuck y Golunar. No pude publicar una respuesta en unario, porque eso necesitaría unas pocas veces más de memoria que los átomos en el universo ^^

La rutina "atrás" no verificará si el código Golunar / Unary es válido. Si el conteo de bits mod 3! = 1, se ejecutará en un bucle sin fin imprimiendo muchos ">" s.

Gracias a Nitrodon por ayudarme a obtener menos de 300 caracteres para el código bf a unario

brainfuck a unary

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

Pruébalo en línea!

y de regreso

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

Pruébalo en línea!

Golunar / unarios-dígitos, 509 303 288 286 268 + 478 337 331 304 = 572 bytes

brainfuck a unary

2845581296974449674357817038179762273623136917867627972159702240227366875240878616687779429553529795902322625321040063298921498529640547483869509829184440577052825434462245755576011912505085065586076069824710351537537205287083477698633592357950165322060367940923703887

y de regreso

3775574485023133646619269732540391678811443648964274086227256847322821618228135493733703990523803451383315165001915937932498966394771849173263120467073642011339214182483748816052890450078070151307011943625602391238338941712116968736593594971620990210178757280976709140113340322124688909388916094040773207

Códigos fuente

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

y de regreso

[
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
Al convertir a Unary, puede restar los 60 directamente de la celda de entrada en lugar de ponerlos primero en su propia celda, ahorrando 16 bytes. Se pueden guardar otros 4 bytes al no crear los 45 inmediatamente (compactando así el diseño de la cinta aún más). Además, es un poco más golfista verificar los bytes de entrada en el orden 01325467.
Nitrodon

La alternativa a la que me refería era crear el 45 mientras agregaba 15 a la celda de entrada.
Nitrodon

6

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

Gracias a Sp3000 por sus numerosas sugerencias, ahorrando muchos bytes.

Brainfuck a Unary, 78 77 61 53 + 2 = 55 bytes

Se agregaron dos bytes para dar cuenta de los "s" de entrada.

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

Unario a Brainfuck, 86 64 bytes

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

Échale un vistazo a ideone aquí.



3

CJam, 35 bytes

Brainfuck a Unary, 17 bytes

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

Pruébalo en línea.

Cómo funciona

 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.

Unario a Brainfuck, 18 bytes

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

Pruébalo en línea.

Cómo funciona

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-

Prueba de salida:

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

1
tr -dc 0-9 (y en el código de golf se puede suponer que ?está bien sin
escapes

1

Japt , 13 + 13 = 26 bytes

Brainfuck a Unary

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

¡Intentalo!

Explicació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

Unario a Brainfuck

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

¡Intentalo!

Explicación:

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

Notas

No puedo encontrar la meta publicación, pero si mi memoria funciona correctamente, las respuestas pueden limitar la E / S a números que su idioma puede admitir, siempre que implementen un algoritmo que funcione si el idioma comienza a admitir números más grandes. Ese es el caso aquí, la capacidad de Japt para tratar una cadena como "base nusando estos ncaracteres para los dígitos" solo puede usar el numbertipo de datos en el otro lado de la operación y, por lo tanto, los casos de prueba no se ejecutarán con éxito; la salida del primer programa y la entrada del segundo programa obligarán al número a uno que puede representarse como a number, en lugar de usar el número real. Para números que pueden ser perfectamente representados por Japt'snumbertipo de datos, estos programas funcionarán según lo deseado, y si el numbertipo de datos cambia para admitir números más grandes, estos programas también comenzarán a admitir esos números.


0

05AB1E , 33 (17 + 16) bytes

Brainfuck a Unary-length:

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

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

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

Longitud unaria a Brainfuck

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

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

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

Dart , 77 + 142 = 219 bytes

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

Pruébalo en línea!


0

C (gcc) , 254 bytes

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

Pruébalo en línea!

Determina en qué dirección ir en función de input ( i), almacena el resultado en el búfer pasado ( o). Tenga en cuenta que algunos compiladores permiten guardar 4 bytes en función del orden definido por la implementación de o ++. En estos casos, la solución provista truncará un carácter adicional de la conversión Unary-> BF y o[1]todos pueden reemplazarse *opara recuperar el comportamiento.


El lenguaje debe ser "C (gcc) + GMP" aquí
solo ASCII del

Además, ¿es más corto como un programa que como 2? Y también recomendaría poner #include <string.h>el pie de página en lugar del encabezado para mostrar que funciona sin esa importación. Además, ¿C ++ no sería más corto debido a la sobrecarga de su operador? : P
Solo ASCII

Tampoco es importante, pero cambiaría todo sia uital vez
solo ASCII

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

también mpz_init_set_str->mpz_set_str
ASCII solo
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.