Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

In any programming or scripting language x, write a program that takes a valid brainfuck sourcecode from stdin and output, to stdout, the sourcecode of a program, written in language x, that would output the exact same thing as the brainfuck program would do.

Your program must work for any valid brainfuck program, including the empty file.

Your score would be equal to the byte count of your sourcecode, plus the byte count of your output given the following input:

+++++ [-]
+++++ +++++ [
    > +++++ ++
    > ++ +++ ++++ +
    > +++
    <<< -
]
> ++ . H
> + . e
++ +++ ++. l
. l
+++ . o
> ++ . space
< +++++ +++ . w
----- --- . o
+++ . r
---- - - . l
----- --- . d
> + . exclamation mark
------lol; useless code :-)--------------------------[.............................................][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]<-<<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><

For example, for an input of [-], the output of *p=0; is much more favourable than while(*p) *p--;

If you happen to use non-ASCII characters, the byte count must be calculated using the UTF-8 encoding.

Lowest score wins. However, creative solutions that attempt to minimise the output shall be encouraged by upvotes.

share|improve this question
11  
You might want to add a clause that the target language not also be brainfuck ;) –  Josh Feb 3 at 1:58
    
@Josh well, if someone managed to write a short brainfuck program that removes unnecessary useless codes, why not let them do it? –  ace Feb 3 at 11:11
1  
Well quite simply because the trivial solution of outputting the source unchanged is going to have a really low score anyway for brainfuck. I will be surprised if another language can beat that. –  Tim Seguine Feb 3 at 11:19
    
@Tim Seguine I could change the question, but would that be unfair to those who have already provided an answer? And if I change the question, I'm thinking about changing the score calculation, making it byte count of source + (byte count of output)^2, would that encourage people to focus more on simplifying the output? –  ace Feb 3 at 11:25
    
Generally changing a question like that after it has already been answered is frowned upon. I was just pointing out a reason why I think Josh was right. It's good to post stuff like this in the sandbox first, so you can work out potential problems while being fair to everyone. –  Tim Seguine Feb 3 at 11:33
show 7 more comments

7 Answers

up vote 9 down vote accepted

Perl - 177 (source) + 172 (output) = 349

#!perl -p0
y/-+><.,[]
-~/p-w/d;s/(.)\K\1+|rs|wv[^v]*(?=w)/$+&&length$&/ge;$_="eval'r$_'=~".'s/.(\d*)/(qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&&v63].q($i;))x($++1)/ger'

Counting the shebang as 2 bytes, one for each option. First, each of the eight commands is translated onto the range p-w, while at the same time removing all other characters. This string is then run-length encoded and output with a minimal decoder/interpreter. A few things are optimized away: the string >< obviously does nothing, and a for loop that follows directly after another may be removed entirely, as it will never be entered.

Output for the test program:

eval'rq4vpwq9vrq6rq9rq2s2pwrq1trqtq6t1q2trq1tsq7tp7tq2tp5tp7trqtp32vt44wsps1'=~s/.(\d*)/(qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&&v63].q($i;))x($++1)/ger

A sample run:

$ perl brainfusk.pl < in.bf | perl
Hello world!

Perl - 232 (source) + 21 (output) = 253

#!perl -p0
y/-+><.,[]
-~/0-7/d;$_="eval'2$_'=~".'s/./qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&].q($i;)/ger';
/5/||fork?(wait,$?||exit):($SIG{ALRM}=sub{exit 1},alarm 9,$S=select(open 1,'>',\$o),eval,print$S "print\"\Q$o\E\"")

This one is based on FIQ's observation that if the original program doesn't contain an input statement, the output will be static, and therefore can be reduced to a single print statement. If you like this one, be sure to give his answer a +1.

So what we can do is pipe stdout to a variable, eval the code we would have output, and wrap the result in a print.

...that won't always work, though. Whenever the code to be translated would have resulted in an infinite loop, (e.g. +[.]), this cannot be reduced to a single print statement, for obvious reasons. So instead, we launch the eval in a child process with a short timeout, and if it doesn't finish executing within that time we output the translated program as before.

Structured and commented:

if(!/5/) { # no `,` in program

  if(fork) { # parent process

    # wait for child
    wait;
    # no child error, terminate without output
    $?||exit

  } else { # child process

    # alarm handler, exit with error
    $SIG{ALRM}=sub{exit 1};
    # set an alarm in 9 seconds
    alarm 9;
    # redirect STDOUT to variable $o
    $S=select open 1,'>',\$o;
    # execute translated code
    eval;
    # wrap the result in a print statement
    print$S "print\"\Q$o\E\""
  }
}

Output for sample program:

print"Hello\ world\!"

Output for ,[.]:

eval'25647'=~s/./qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&].q($i;)/ger

Output for +[.] (after 9 seconds):

eval'21647'=~s/./qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&].q($i;)/ger
share|improve this answer
1  
This is amazing! Brain hurts :) –  Timwi Feb 3 at 20:25
    
I think wv.*?(?=w) is wrong. I think it will only remove code up to the next ], but you need it to find the matching ]; you need to take care of nesting... –  Timwi Feb 3 at 20:35
    
@Timwi Fixed, by ignoring the nested cases wv[^v]*(?=w), which is significantly shorter than the alternative. –  primo Feb 4 at 0:20
add comment

Brainfuck, 5 + 540 = 545 bytes

5 bytes of code, 540 from output of given test file (assuming got the count right from my paste of that code).

,[.,]

Assuming EOF is 0.

share|improve this answer
    
@primo since it doesn't reset before reading a interpreter that does not chaneg value at EOF will make this program an endless loop for all input larger than 0 bytes. –  Sylwester Feb 3 at 16:12
    
@Sylwester ahh, true. –  primo Feb 3 at 16:14
    
I cant help to wonder, what software is used to run this stuff? xD –  Teun Pronk Feb 5 at 14:31
    
@TeunPronk There's a brainfuck interpreter called bfi (github.com/susam/bfi). Just compile and install it, and run it like so: bfi input.bf where input.bf is the brainfuck file to be interpreted. –  B1KMusic Feb 10 at 1:17
add comment

PHP, 553 + 27 = 580 bytes

(553 bytes with all whitespaces, i.e. newlines and spaces, removed)

I suck badly at golfing PHP, so this approach can be heavily optimized. I mostly wanted to show my approach to the solution in something not BF.

<?php
echo "<?php ";
$x = 'if (!$b) $c = $_GET[c];
$x=$y=$n[0]=$p=0;$o[0]=1;$d="";
while($a=$c[$x++]){
    if($o[$p]){
        if($a=="-")$m[$y]--;
        if($a=="+")$m[$y]++;
        $m[$y]=$m[$y]%256;
        if($a=="<")$y--;
        if($a==">")$y++;
        if($a=="."){
            $e=chr($m[$y]);
            if ($b) echo $e;
            else $d.=addslashes($e);
        }
        if($a==",")$m[$y]=($b=$_GET[i])?ord($b):0;
    }if($a=="["){
        $p++;
        $n[$p]=$x-1;
        $o[$p]=$o[$p-1]?$m[$y]:0;
    }
    if($a=="]"){
        if($o[$p])$x=$n[$p];
        $p--;
        if($p=-1)$p=0;
    }
}
if (!$b) echo "echo \'$d\';";';
if (strstr($_GET['c'],",")) {
    $x = '$b=1;'.$x;
    echo '$c="'.addslashes($_GET[c]).'";'.$x;
    return;
}
eval($x);

Error reporting must be off, otherwise PHP will hate you. Usage: throw this up as a page, and run it with script.php?c=CODE (if the resulting script requires input, you run it as out.php?i=INPUT). Remember to url escape the input!

What this does is basically this - if the BF script contains ",", it pretty much embeds itself as the resulting script with an attached $b=1; at the top. If it does NOT contain ",", it optimizes it down to "echo '<BF output>'". Conveniently, the test script in the OP does NOT require any input. The addslashes() is just there for escaping ' and \.

share|improve this answer
add comment

C++, 695 + 510 = 1205 bytes

Code:

#include<iostream>
#include<utility>
#include<vector>
#define D "\n#define "
using namespace std;using S=string;int main(){vector<pair<S,S>>m={{"--------","(*p)-=8;"},{"<>",""},{"[]","F;"},{"+","A;"},{"-","B;"},{">","C;"},{"<","D;"},{"[","F{"},{"]","}"},{".","E;"},{",","std::cin>>*p;"}};S s;char c;while(cin>>c)if(S("+-><[].,").find(c)<8)s+=c;for(int i=0;i<s.length();i++)if(s.substr(i,4)=="[][]")s=s.replace(i--,4,"[]");cout<<"#include<iostream>" D"A ++*p" D"B --*p" D"C p++" D"D p--" D"E std::cout<<*p" D"F while(*p)\nint main(){char*p=new char[1<<19]();";while(s.size())for(auto p:m)if(s.substr(0,p.first.length())==p.first){s=s.substr(p.first.length());cout<<p.second;break;}cout<<"}";}

Output:

#include<iostream>
#define A ++*p
#define B --*p
#define C p++
#define D p--
#define E std::cout<<*p
#define F while(*p)
int main(){char*p=new char[1<<19]();A;A;A;A;A;F{B;}A;A;A;A;A;A;A;A;A;A;F{C;A;A;A;A;A;A;A;C;A;A;A;A;A;A;A;A;A;A;C;A;A;A;D;D;D;B;}C;A;A;E;C;A;E;A;A;A;A;A;A;A;E;E;A;A;A;E;C;A;A;E;D;A;A;A;A;A;A;A;A;E;(*p)-=8;E;A;A;A;E;B;B;B;B;B;B;E;(*p)-=8;E;C;A;E;(*p)-=8;(*p)-=8;(*p)-=8;(*p)-=8;B;F{E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;}F;D;B;D;D;}

Original code:

#include <iostream>
#include <utility>
#include <vector>
using namespace std;
int main() {
    vector<pair<string, string>> m={
    {"--------","(*p)-=8;"},
    {"<>",""},
    {"[]","F;"},
    {"+","A;"},
    {"-","B;"},
    {">","C;"},
    {"<","D;"},
    {"[","F{"},
    {"]","}"},
    {".","E;"},
    {",","std::cin>>*p;"}};
    string s;
    char c;
    while (cin >> c)
        if (string("+-><[].,").find(c) < 8)
            s += c;
    for(int i = 0; i < s.length(); i++)
        if(s.substr(i, 4) == "[][]")
            s = s.replace(i--, 4, "[]");
    cout << "#include<iostream>\n"
            "#define A ++*p\n"
            "#define B --*p\n"
            "#define C p++\n"
            "#define D p--\n"
            "#define E std::cout<<*p\n"
            "#define F while(*p)\n"
            "int main(){char*p=new char[1<<19]();";
    while (s.size())
        for (auto p : m)
            if (s.substr(0, p.first.length()) == p.first) {
                s = s.substr(p.first.length());
                cout << p.second;
                break;
            }
    cout << "}";
}
share|improve this answer
add comment

Python - 514 + 352 = 866

Code:

import sys,zlib,base64
s,i="import sys\na,i=[0]*300000,0\n",0
for c in sys.stdin.read():
 if c in"+-><,.[]":
  s+=" "*i+{'+':"a[i]+=1\n",'-':"a[i]-=1\n",'>':"i+=1\n",'<':"i-=1\n",',':"a[i]=(lambda x:0if x==''else ord(x))(sys.stdin.read(1))\n",".":"sys.stdout.write(chr(a[i]))\n","[":"while a[i]!=0:\n","]":"pass\n"}[c]
  i+={'[':1,']':-1}.get(c,0)
print('import zlib,base64\nexec(zlib.decompress(base64.b64decode("'+base64.b64encode(zlib.compress(bytes(s,"utf8"),9)).decode("utf8")+'")).decode("utf8"))')

Output:

import zlib,base64
exec(zlib.decompress(base64.b64decode("eNrLzC3ILypRKK4s5krUybSNNojVMjYAAR0DrsTozFhtW0OCdHlGZk6qAoinaGtgxQVm6QLFFQoSi4uJNoVc2zJBggowWTIZVDGEEvMzddFJ1FDMxBYUwFjTKy5JyS8t0SsvyixJ1UjOKNIASWpqomrAp5DceMBnJjn2Ee0ZojToUiGlEfIFzA5yaGqHELXtp5XfMukVwMOFRi/u8IXZqOSo5KjkqOSIlAQ3k9BLy1HBUcFRwVFBOgpmIrfeMhGE9ihrpLEAudg3NA==")).decode("utf8"))
share|improve this answer
add comment

Lua - 328 + 2256 = 2584

(Oh I just realized you need to add the length of the result too, poor score, it looks like)

print((("l,m,p=loadstring,{0},1 z,y,x,w,v,u=l'io.write(string.char(@))',l'@=io.read(1):byte()',l'p=p-1',l'p=p+1 @=@or 0',l'@=(@+1)%256',l'@=(@-1)%256'"..io.read"*a":gsub("[^.,<>[%]+-]",""):gsub(".",{["."]="z()",[","]="y()",["<"]="x()",[">"]="w()",["["]="while @~=0 do ",["]"]="end ",["+"]="v()",["-"]="u()"})):gsub("@","m[p]")))

Taken from this answer of mine.

share|improve this answer
add comment

Sorry everyone.

In 2013 i wrote a class in php to convert and run brainfuck code.

I could get it running and i could convert the code into php and c.

Here is a link: http://sandbox.onlinephpfunctions.com/code/c487e0024ad62dde3272a10c3c4e9f30685db1f3

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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