6
\$\begingroup\$

You don't need to know these languages to participate. All necessary information has been provided in this question.

You should write a program or function which given a brainfuck (BF) code as input outputs its tinyBF equivalent.

BF has 8 instructions characters: +-><[],. and tinyBF has 4: =+>|. Converting works the following way: starting from the beginning of the BF code each symbol is replaced by on of its two tinyBF counterparts based on the number of = signs in the tinyBF code until that point (i.e. = behaves like a toggle switch).

The converter table (with columns: Brainfuck symbol; tinyBF symbol(s) when ther are even ='s before; tinyBF symbol(s) when ther are odd ='s before):

BF   even    odd

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

(This creates an almost unique tinyBF code. The only conflict occurs if the BF code contains a [] which is generally unused as it creates an infinite void loop.)

Input

  • An at least 1 byte long valid brainfuck program containing only the characters +-><[],.
  • Guaranteed not to contain the string []
  • Trailing newline is optional.

Output

  • A tinyBF program.
  • Trailing newline is optional.

Examples

You can convert any BF program to tinyBF with this (1440 byte long) converter (see the Edit section for a small deviation).

Format is Input into Output

++-  into  ++=+
,[.,]  into  |=||==|=|=| or |=|=|==|=|| (both is acceptable check the Edit section)
>++.--.[<]+-,  into  >++===++===|=>|=+=+=|=|
>++-+++++++[<+++++++++>-]<.  into  >++=+=+++++++|=>=+++++++++>=+|>==

Edit

As @Jakube pointed out in the official tinyBF converter in the equivalents of the , BF instruction (|=| and =|=|) the last = signs aren't counted towards the toggle state. Both the official and mine interpretations are acceptable but you have to choose one.

This is code-golf so the shortest entry wins.

\$\endgroup\$
  • \$\begingroup\$ By 'odd' and 'even', do you mean the first character of the BF code is 'odd', the next is 'even', and so on? \$\endgroup\$ – ASCIIThenANSI Apr 8 '15 at 18:14
  • \$\begingroup\$ @ASCIIThenANSI I think what's meant is the number of = characters output before the character currently being translated. Think of the = character as a toggle between two instruction sets. \$\endgroup\$ – orlp Apr 8 '15 at 18:20
  • \$\begingroup\$ @orip OK, but what about things like =|=| that don't change the even/odd value? Or is that part of the challenge? \$\endgroup\$ – ASCIIThenANSI Apr 8 '15 at 18:22
  • \$\begingroup\$ Is input through a file, STDIN, or our choice? \$\endgroup\$ – ASCIIThenANSI Apr 8 '15 at 19:26
  • \$\begingroup\$ @ASCIIThenANSI Your choice. \$\endgroup\$ – randomra Apr 8 '15 at 19:32
4
\$\begingroup\$

CJam, 50 bytes

l{"..+-><[],"#2mdT2$@T?:T=L'=?"== + > | |=|"S/@=}/

Try one example or all of them online.

Explanation

The magic is in the mapping! Looking up each operator's index in a carefully ordered yet simple string produces three useful pieces of information at once: whether the operator is directionless (index == 0), the direction the operator requires (index mod 2), and the index of the output operator (index / 2).

Using that handy mapping, it's a simple case of looping through each input operator and producing a direction swap operator if the direction needs to be changed, updating the direction, and producing the output operator.

l                   "Read a line of input.";
{                   "For each character of input:";
  "..+-><[],"#        "Map the character:
                        '.' -> 0  |
                        '+' -> 2  |  '-' -> 3
                        '>' -> 4  |  '<' -> 5
                        '[' -> 6  |  ']' -> 7
                        ',' -> 8  |            ";
  2md                 "Calculate the quotient and remainder of the mapping
                       divided by 2.";
  T2$@T?:T            "If the the mapping is nonzero (not '.'), set the
                       direction after this operator to the remainder above.
                       Otherwise ('.'), don't change the direction.";
  =L'=?               "If the direction before this operator is equal to the
                       direction after, produce an empty string. Otherwise,
                       produce the direction switch operator, '='.";
  "== + > | |=|"S/@=  "Map the previous mapping divided by 2 to an operator:
                         0 ('.')      -> '=='
                         1 ('+', '-') -> '+'
                         2 ('>', '<') -> '>'
                         3 ('[', ']') -> '|'
                         4 (',')      -> '|=|' ";
}/
\$\endgroup\$
12
\$\begingroup\$

Extended BrainFuck 276 bytes

(not counting uneccesary linefeeds)

{a<<]>&c}{b<<-]<[->}{c]<]>[>[}{d 4+[-<}3>4->3->5->-->>&d 4+>]<[-<
4+<3+<4+<8+4>]<[<]<<,[>3+&d 6->]+<-[-[-[-[14-[--[>&d 6->]+<+[--[[
-]>[-&c>.&b>>.<.<+&a->>.<.&b>.<&a->>.>>.3<&b 4>.4<&a 4>.3<&b+>>.>
>.6<]>]<]>[-3>..3<&c 3>.<<&b+>>.>.3<&a>>.<.>.<.&b+>.>.<.<&a->>.>.
<<&b 3>.5<]>]<,]

How to compile and run:

beef ebf.bf < tinybf.ebf > tinybf.bf
beef tinybf.bf < source.bf > source.tbf

It will work with any wrapping BF interpreter that uses/support 0 as EOF. Actual EBF source before golfing:

:i:f:o:p:e:a:g
$p ~"|=+>"<[<]@o
$i,( $f+++++++(-$i------)+$i-; +
     ($i-; ,
       ($i-; -
         ($i-; .
           ($i--------------; <
             ($i--; >
               ($f++++(-$i------)+$i+; [
                 ($i--; ]
                   ((-) $f(-) )
                      $f ( $o[$p.$f-]<[@f-$e.$p.$o+$i] ) ; ]
                  ) $f ( $o[-$e.$p.$f-]<[@f-$p.$i] ) ; [
                ) $f ( $o[-$e.$g.$f-]<[@f-$g.$i] ) ; >
              ) $f ( $o[$g.$f-]<[@f-$o+$e.$g.$i] ) ; <
            ) $f (- $e.. ) ; .
          ) $f ( $o[$a.$f-]<[@f-$o+$e.$a.$i] ) ; -
        ) $f ( $o[$e.$p.$e.$p.$f-]<[@f-$o+$p.$e.$p.$i] ) ; ,
     ) $f ( $o[-$e.$a.$f-]<[@f-$a.$i] ) ; +
$i,)

BrainFuck 404 bytes

This is the trimmed output of the compiled EBF.

>>>---->--->----->-->>++++[-<++++>]<[-<++++<+++<++++<++++++++>>>>]<
[<]<<,[>+++++++[-<------>]+<-[-[-[-[--------------[--[>++++[-<-----
->]+<+[--[[-]>[-]<]>[>[>.<<-]<[->>>.<.<+<<]>]<]>[>[->>.<.<<-]<[->>.
<<<]>]<]>[>[->>.>>.<<<<<-]<[->>>>>.<<<<<<]>]<]>[>[>>>>.<<<<<-]<[->+
>>.>>.<<<<<<]>]<]>[->>>..<<<]<]>[>[>>>.<<<<-]<[->+>>.>.<<<<<]>]<]>[
>[>>.<.>.<.<<-]<[->+>.>.<.<<<]>]<]>[>[->>.>.<<<<-]<[->>>>.<<<<<]>]<,]
\$\endgroup\$
  • \$\begingroup\$ So it's converting BF to TinyBF... in BF. That's AWESOME. \$\endgroup\$ – ASCIIThenANSI Apr 9 '15 at 19:04
1
\$\begingroup\$

Perl, 244 241 226 217 bytes

open(B,$ARGV[0]);%e=qw(+ + - =+ > > < => [ | ] =| . == , |=|);%o=qw(+ =+ - + > => < > [ =| ] | . == , =|=|);$q=0;while(<B>){$p='';@c=split('');foreach$c(@c){if($q%2>0){$p.=$o{$c}}else{$p.=$e{$c};}$q=$p=~/=/g;}print$p}

Works on all cases. Run with perl file.pl [filename] where file.pl is the name of the program, and [filename] is the name of the BF file.
Changes

  • Saved 3 bytes by using split('') instead of split('',$_).
  • Saved 15 bytes by:
    • Getting rid of $f= in front of open (3 bytes)
    • Replacing if($eo%2==1) with if($eo%2>0) (1 byte)
    • Replacing $p=$p. with $p.= (2 bytes * 2 times = 4 bytes)
    • Removing trailing newline, as it was optional (5 bytes)
    • Removed =() (3 bytes)
  • Saved 9 bytes by shortening variable names.
\$\endgroup\$
1
\$\begingroup\$

K, 91 bytes

o:0;{:[i:"..+-><[],"?x;t:i!2;t:0];`0::[o=t;"";"="],("==";"+";">";"|";"|=|")@i%2;o::t}',/0:`

It's more-or-less a direct port of @Runer112's CJam answer. And it's much longer. Life sucks.

\$\endgroup\$
1
\$\begingroup\$

TinyBF***, 558 bytes

Don't credit me for this, this is the TinyBF version of @Sylwester's BrainF*** answer (I used his code to convert his code into this code, :P). I just felt the need to put this answer up.

>>>=++++=>=+++=>=+++++=>=++=>>++++|=+>=++++>=|>=|=+>=++++=>=+++=>=++++=>=+++++++
+>>>>=|>=|=>|>>=|=|=|>+++++++|=+>++++++=>=|=+=>+=|=+=|=+=|=+=|=++++++++++++++=|=
++=|>++++|=+>++++++=>=|=+=>=+|=++=||=+|=>|=+|>|=>|>|>===>>+|>=|=+=>>>===>==>=+=>
>|=>=|>|=>|>|=+=>>===>==>>+|>=|=+=>>===>>>|=>=|>|=>|>|=+=>>==>>===>>>>>+|>=|=+=>
>>>>===>>>>>>|=>=|>|=>|>|>>>>===>>>>>+|>=|=+=>+>>==>>===>>>>>>|=>=|>|=>|=+=>>>==
===>>>|>|=>|>|>>>===>>>>+|>=|=+=>+>>==>===>>>>>|=>=|>|=>|>|>>===>===>===>==>>+|>
=|=+=>+>==>===>==>>>|=>=|>|=>|>|=+=>>==>===>>>>+|>=|=+=>>>>===>>>>>|=>=|>=|=||
\$\endgroup\$
0
\$\begingroup\$

Ruby, 233 217 bytes

p,m,g,l,b,s,d,a,q,f=%w(+ - > < [ ] . , | =)
z=[{p=>p,m=>f+p,g=>g,l=>f+g,b=>q,s=>f+q,d=>f+f,a=>q+f+q},{p=>f+p,m=>p,g=>f+g,l=>g,b=>f+q,s=>q,d=>f+f,a=>f+q+f+q}]
i=0
ARGV[0].each_char{|c|v=z[i%2][c];print v;i+=v.count(f)}

An 8-byte improvement on the previous non-esoteric answers!
Saved 16 bytes with the %w() syntax

\$\endgroup\$
0
\$\begingroup\$

Ruby, 101 bytes

->s{t="";s.chars{|c|t<<((t.count(?=)+i="..+-><[],".index(c))%2<1&&i>0?"":?=)+%w(= + > | |=|)[i/2]};t}

Try it online!

Uses the second interpretation of the ambiguous , translation rule.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.