Brainf*** to tinyBF converter

6

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.

randomra

Posted 2015-04-08T17:15:14.180

Reputation: 19 909

By 'odd' and 'even', do you mean the first character of the BF code is 'odd', the next is 'even', and so on? – ASCIIThenANSI – 2015-04-08T18:14:45.870

@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. – orlp – 2015-04-08T18:20:44.643

@orip OK, but what about things like =|=| that don't change the even/odd value? Or is that part of the challenge? – ASCIIThenANSI – 2015-04-08T18:22:40.900

Is input through a file, STDIN, or our choice? – ASCIIThenANSI – 2015-04-08T19:26:19.640

@ASCIIThenANSI Your choice. – randomra – 2015-04-08T19:32:35.703

I don't understand the second example: ,[.,] into |=||==|=|=|. , transforms into |=|, then there is a odd number of =s, so why doesn't [ transform into =|? – Jakube – 2015-04-08T20:02:49.177

@Jakube You are correct. See the Edit section. – randomra – 2015-04-08T20:23:09.870

Are we allowed to assume that a dot as the very first character would be invalid because it makes no sense? – kirbyfan64sos – 2015-04-09T17:04:26.603

@kirbyfan64sos No. It does make sense though as It outputs the character with codepoint 0. – randomra – 2015-04-09T18:14:01.433

Answers

4

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 (',')      -> '|=|' ";
}/

Runer112

Posted 2015-04-08T17:15:14.180

Reputation: 3 636

12

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.

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

Sylwester

Posted 2015-04-08T17:15:14.180

Reputation: 3 678

So it's converting BF to TinyBF... in BF. That's AWESOME. – ASCIIThenANSI – 2015-04-09T19:04:59.973

1

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.

ASCIIThenANSI

Posted 2015-04-08T17:15:14.180

Reputation: 1 935

1

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.

kirbyfan64sos

Posted 2015-04-08T17:15:14.180

Reputation: 8 730

1

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.

>>>=++++=>=+++=>=+++++=>=++=>>++++|=+>=++++>=|>=|=+>=++++=>=+++=>=++++=>=+++++++
+>>>>=|>=|=>|>>=|=|=|>+++++++|=+>++++++=>=|=+=>+=|=+=|=+=|=+=|=++++++++++++++=|=
++=|>++++|=+>++++++=>=|=+=>=+|=++=||=+|=>|=+|>|=>|>|>===>>+|>=|=+=>>>===>==>=+=>
>|=>=|>|=>|>|=+=>>===>==>>+|>=|=+=>>===>>>|=>=|>|=>|>|=+=>>==>>===>>>>>+|>=|=+=>
>>>>===>>>>>>|=>=|>|=>|>|>>>>===>>>>>+|>=|=+=>+>>==>>===>>>>>>|=>=|>|=>|=+=>>>==
===>>>|>|=>|>|>>>===>>>>+|>=|=+=>+>>==>===>>>>>|=>=|>|=>|>|>>===>===>===>==>>+|>
=|=+=>+>==>===>==>>>|=>=|>|=>|>|=+=>>==>===>>>>+|>=|=+=>>>>===>>>>>|=>=|>=|=||

HyperNeutrino

Posted 2015-04-08T17:15:14.180

Reputation: 26 575

0

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.

Kirill L.

Posted 2015-04-08T17:15:14.180

Reputation: 6 693

0

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

EMBLEM

Posted 2015-04-08T17:15:14.180

Reputation: 2 179