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> |
We could save quite some chars if we could use the key characters to split the command string (but alas, then the command string could not use + and - at least for the first two commands :-( )
'+inc a[b]+-dec a[b]-[start loop[]stop loop]>inc b><dec b<.output.,input'.split(a[b])[1]
That could (or more likely will absolutely) result in errors parsing bf code with "comments" :) aka any char other than the valid identifiers.
Only if one of those chars were in our command array, but it's a valid point anyway.
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.
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 :)
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 :)
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.
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
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.
Great :) now if only replace, split and indexOf was shorter!