Skip to content

Instantly share code, notes, and snippets.

@hillerstorm
Forked from 140bytes/LICENSE.txt
Last active December 23, 2015 10:39
Show Gist options
  • Save hillerstorm/6622750 to your computer and use it in GitHub Desktop.
Save hillerstorm/6622750 to your computer and use it in GitHub Desktop.
Brainfuck interpreter

Brainfuck interpreter

Fully featured with loops, input, output and comments.

139bytes!

Chrome and Firefox only

(
a, // brainfuck input and later used as brainfuck "register"
b, // function to use for user input and output
// if any data is passed, it is printed out,
// otherwise b returns user input
c // placeholder index argument
) => eval(
// replace every char
a.replace(
// use regex as register
a = /./g,
// mapping table from identifiers to javascript
d => '1=-~101=~-10while1{0}0c++0c--0b101=b()'
// saving some space
.replace(/1/g, '(a[c])')
.split(0)['+-[]><.,'.indexOf(d)]
// add semicolon to separate statements
+ ';',
// reset index
c = 0)
)
(a,b,c)=>eval(a.replace(a=/./g,d=>'1=-~101=~-10while1{0}0c++0c--0b101=b()'.replace(/1/g,'(a[c])').split(0)['+-[]><.,'.indexOf(d)]+';',c=0))
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2013 Johan Hillerström <https://github.com/hillerstorm>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "brainfuck",
"description": "Executes a brainfuck program.",
"keywords": [
"brainfuck",
"interpreter",
"compiler"
]
}
<!DOCTYPE html>
<title>Brainfuck interpreter</title>
<div>Expected Value: <b>Hello World!
</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
var brainfuck = (a,b,c)=>eval(a.replace(a=/./g,d=>'1=-~101=~-10while1{0}0c++0c--0b101=b()'.replace(/1/g,'(a[c])').split(0)['+-[]><.,'.indexOf(d)]+';',c=0));
brainfuck(
'++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.',
function (output) {
// if no output is given, read user input instead
if (typeof output === 'undefined') {
return prompt().charCodeAt();
}
// else buffer the char
document.getElementById('ret').innerHTML += String.fromCharCode(output);
});
</script>
@atk
Copy link

atk commented Sep 24, 2013

Only if one of those chars were in our command array, but it's a valid point anyway.

@atk
Copy link

atk commented Sep 24, 2013

The only other way I can imagine to save space would be to use clever mathematics with the charcode (my current approach to do so is woefully as long as the previous implementation):

';'+'1=-~101=~-10while1{0}0b++0b--0i101=i()'.replace(/1/g,'(a[b])').split(0)['+-[]><.,'.indexOf(a[b])]
';'+'while1{00}001=-~101=~-100b++0b--00i101=i()'.replace(/1/g,'(a[b])').split(0)[a[b].charCodeAt()%13]

Maybe we'll find a way to reduce this approach further.

@hillerstorm
Copy link
Author

Interesting...

I tried (and failed) with this crazy attempt (163b):

function(a,i,b){eval(eval(a.replace(/./g,"'1=-~101=~-10while1{0}0b++0b--0i101=i()'.replace(/1/g,'(a[b])').split(0)['+-[]><.,'.indexOf('$&')]+';'+")+"''"),a=[b=0])}

every char gets replaced with the whole lookup table and evaled twice :)

@hillerstorm
Copy link
Author

I guess I can give up my dream to be able to parse commented code and instead go for 140b by restricting the input to valid BF identifiers :)

@atk
Copy link

atk commented Sep 24, 2013

We could reluctantly externalize the main command string to go below 140bytes (114, to be precise). It's a bit of a gray area that I have used for my JS syntax highlighter and base64 decoder, too.

function(a,i,s,b,c){for(b in a)c+=';'+s.replace(/1/g,'(a[b])').split(0)['+-[]><.,'.indexOf(a[b])];a=[b=0];eval(c)}
// i=function(b,u){return b==u?prompt().charCodeAt():document.getElementById('output').innerHTML+=String.fromCharCode(b)}, 
// s='1=-~101=~-10while1{0}0b++0b--0i101=i()'

Let's keep the version with 151bytes as a great learning example, anyway.

@hillerstorm
Copy link
Author

It could even be 82b if the command string is the complete array, with the 1's already replaced with a[b]:

function(a,i,s,b,c){for(b in a)c+=';'+s['+-[]><.,'.indexOf(a[b])];a=[b=0];eval(c)}
// s=['a[b]=-~a[b]','a[b]=~-a[b]','while(a[b]){','}','b++','b--','i(a[b])','a[b]=i()']

but that actually feels like too much of a gray area for my taste :D
not at all plug-and-play! as much code outside as there is inside the function

@atk
Copy link

atk commented Sep 25, 2013

I wholeheartedly agree. Maybe we'll find a solution after all. Until then, we do have a gray area solution and another one that's too big.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment