150
\$\begingroup\$

Write the shortest program in your favourite language to interpret a brainfuck program. The program is read from a file. Input and output are standard input and standard output.

  1. Cell size: 8bit unsigned. Overflow is undefined.
  2. Array size: 30000 bytes (not circled)
  3. Bad commands are not part of the input
  4. Comments begin with # and extend to the end of line Comments are everything not in +-.,[]<>
  5. no EOF symbol

A very good test can be found here. It reads a number and then prints the prime numbers up to that number. To prevent link rot, here is a copy of the code:

compute prime numbers
to use type the max number then push Alt 1 0
===================================================================
======================== OUTPUT STRING ============================
===================================================================
>++++++++[<++++++++>-]<++++++++++++++++.[-]
>++++++++++[<++++++++++>-]<++++++++++++++.[-]
>++++++++++[<++++++++++>-]<+++++.[-]
>++++++++++[<++++++++++>-]<+++++++++.[-]
>++++++++++[<++++++++++>-]<+.[-]
>++++++++++[<++++++++++>-]<+++++++++++++++.[-]
>+++++[<+++++>-]<+++++++.[-]
>++++++++++[<++++++++++>-]<+++++++++++++++++.[-]
>++++++++++[<++++++++++>-]<++++++++++++.[-]
>+++++[<+++++>-]<+++++++.[-]
>++++++++++[<++++++++++>-]<++++++++++++++++.[-]
>++++++++++[<++++++++++>-]<+++++++++++.[-]
>+++++++[<+++++++>-]<+++++++++.[-]
>+++++[<+++++>-]<+++++++.[-]

===================================================================
======================== INPUT NUMBER  ============================
===================================================================
+                          cont=1
[
 -                         cont=0
 >,
 ======SUB10======
 ----------

 [                         not 10
  <+>                      cont=1
  =====SUB38======
  ----------
  ----------
  ----------
  --------

  >
  =====MUL10=======
  [>+>+<<-]>>[<<+>>-]<     dup

  >>>+++++++++
  [
   <<<
   [>+>+<<-]>>[<<+>>-]<    dup
   [<<+>>-]
   >>-
  ]
  <<<[-]<
  ======RMOVE1======
  <
  [>+<-]
 ]
 <
]
>>[<<+>>-]<<

===================================================================
======================= PROCESS NUMBER  ===========================
===================================================================

==== ==== ==== ====
numd numu teid teiu
==== ==== ==== ====

>+<-
[
 >+
 ======DUP======
 [>+>+<<-]>>[<<+>>-]<

 >+<--

 >>>>>>>>+<<<<<<<<   isprime=1

 [
  >+

  <-

  =====DUP3=====
  <[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<<<

  =====DUP2=====
  >[>>+>+<<<-]>>>[<<<+>>>-]<<< <


  >>>


  ====DIVIDES=======
  [>+>+<<-]>>[<<+>>-]<   DUP i=div

  <<
  [
    >>>>>+               bool=1
    <<<
    [>+>+<<-]>>[<<+>>-]< DUP
    [>>[-]<<-]           IF i THEN bool=0
    >>
    [                    IF i=0
      <<<<
      [>+>+<<-]>>[<<+>>-]< i=div
      >>>
      -                  bool=0
    ]
    <<<
    -                    DEC i
    <<
    -
  ]

  +>>[<<[-]>>-]<<          
  >[-]<                  CLR div
  =====END DIVIDES====


  [>>>>>>[-]<<<<<<-]     if divides then isprime=0


  <<

  >>[-]>[-]<<<
 ]

 >>>>>>>>
 [
  -
  <<<<<<<[-]<<

  [>>+>+<<<-]>>>[<<<+>>>-]<<<

  >>




  ===================================================================
  ======================== OUTPUT NUMBER  ===========================
  ===================================================================
  [>+<-]>

  [
   ======DUP======
   [>+>+<<-]>>[<<+>>-]<


   ======MOD10====
   >+++++++++<
   [
    >>>+<<              bool= 1
    [>+>[-]<<-]         bool= ten==0
    >[<+>-]             ten = tmp
    >[<<++++++++++>>-]  if ten=0 ten=10
    <<-                 dec ten     
    <-                  dec num
   ]
   +++++++++            num=9
   >[<->-]<             dec num by ten

   =======RROT======
      [>+<-]
   <  [>+<-]
   <  [>+<-]
   >>>[<<<+>>>-]
   <

   =======DIV10========
   >+++++++++<
   [
    >>>+<<                bool= 1
    [>+>[-]<<-]           bool= ten==0
    >[<+>-]               ten = tmp
    >[<<++++++++++>>>+<-] if ten=0 ten=10  inc div
    <<-                   dec ten     
    <-                    dec num
   ]
   >>>>[<<<<+>>>>-]<<<<   copy div to num
   >[-]<                  clear ten

   =======INC1=========
   <+>
  ]

  <
  [
   =======MOVER=========
   [>+<-]

   =======ADD48========
   +++++++[<+++++++>-]<->

   =======PUTC=======
   <.[-]>

   ======MOVEL2========
   >[<<+>>-]<

   <-
  ]

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

  ===================================================================
  =========================== END FOR ===============================
  ===================================================================


  >>>>>>>
 ]
 <<<<<<<<



 >[-]<
  [-]
 <<-
]

======LF========

++++++++++.[-]
@

Example run:

$ python2 bf.py PRIME.BF 
Primes up to: 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 
\$\endgroup\$
27
  • 10
    \$\begingroup\$ You should clarify about 1) size of memory 2) is memory circled 4) maybe any other details \$\endgroup\$
    – Nakilon
    Commented Jan 28, 2011 at 1:37
  • 3
    \$\begingroup\$ I wonder if there should be two categories: Those programs that use eval (or shell out to compile) -- and those that don't. \$\endgroup\$ Commented Feb 15, 2011 at 7:52
  • 47
    \$\begingroup\$ I'd love to see someone answer this in brainfuck. \$\endgroup\$
    – Hannesh
    Commented Mar 14, 2011 at 19:15
  • 10
    \$\begingroup\$ What does "no EOF symbol" mean? That the cell value remains unchanged when trying , on EOF? Or that it's up to us to choose a value when trying , on EOF? Or is EOF undefined behaviour altogether? \$\endgroup\$ Commented Apr 1, 2016 at 14:07
  • 6
    \$\begingroup\$ Likewise, what should happen when someone tries to leave the 30k cells to either side? Should the tape head remain in place or is this undefined behaviour? \$\endgroup\$ Commented Apr 1, 2016 at 14:09

83 Answers 83

1 2
3
2
\$\begingroup\$

C# - 373 349 339 335 chars

using C=System.Console;class P{static void Main(string[] z){try{for(dynamic c,p=z[0],a=new int[30000],s=new int[9],f=1>0,i=0,d=0,t=0;;i=c==51&&f&(f|=s[--t]<0)?s[t]:++i){c=p[i]-42;a[d+=(c-19)*(f&c>17&c<21?1:0)]+=(2-c)*(f&c>0&c<4?1:0);if(f&c==4)C.Write((char)a[d]);if(f&c==2)a[d]=C.Read();if(c==49)s[t++]=f?(f=a[d]!=0)?i:-1:i;}}catch{}}}

And more readable:

using C=System.Console;
class P
{
    static void Main(string[] z)
    {
        try
        {
            for(dynamic c,p=z[0],a=new int[30000],s=new int[9],f=1>0,i=0,d=0,t=0;;i=c==51&&f&(f|=s[--t]<0)?s[t]:++i)
            {
                c=p[i]-42;
                a[d+=(c-19)*(f&c>17&c<21?1:0)]+=(2-c)*(f&c>0&c<4?1:0);
                if(f&c==4)C.Write((char)a[d]);
                if(f&c==2)a[d]=C.Read();
                if(c==49)s[t++]=f?(f=a[d]!=0)?i:-1:i;
            }
        }
        catch{}
    }
}

Limitation is it only handles nested [ up to 9 deep. Can make the s array bigger to handle more.

Edit 373 -> 349: Removed outer loop (was for a different site), character comparisons to integers, moved c declaration into the for loop

Edit 349 -> 339:

  • Combined +/- and >/< into single lines.
  • Reduced integer literal lengths by subtracting 42 from c to allow for some of the integer literals to be a single character (credit @ceilingcat).
  • Moved i=... into the for loop iterator section (credit @ceilingcat).

Edit 339 -> 335:

  • Combined +/- and >/< into a single line (credit @ceilingcat)
  • Removed unnecessary parenthesis in the i=... (credit @ceilingcat)
\$\endgroup\$
3
  • \$\begingroup\$ oooo, very nice with the subtracting from the c to make the number literals smaller. Can't believe I didn't think of putting the i=... in the loop iterator section. \$\endgroup\$
    – tdashroy
    Commented Aug 10, 2020 at 4:23
  • \$\begingroup\$ awesome again! slowly getting closer to the folks at code.golf/brainfuck#c-sharp. Still in disbelief that so many more bytes can be shaved off. So curious how they do it \$\endgroup\$
    – tdashroy
    Commented Aug 10, 2020 at 8:41
  • \$\begingroup\$ Don't need the space between string[] and z \$\endgroup\$
    – ceilingcat
    Commented Aug 10, 2020 at 19:38
2
\$\begingroup\$

Rust, 312 bytes

use std::io::*;macro_rules! b{(@+)=>{A[I]+=1;};(@-)=>{A[I]-=1;};(@>)=>{I+=1;};(@<)=>{I-=1;};(@[$($t:tt)*])=>{while A[I]>0{$(b!(@$t);)*}};(@.)=>{print!("{}",A[I]as char);};(@,)=>{stdin().read(&mut A[I..=I]);};(@$t:tt)=>{};($($t:tt)*)=>{static mut A:[u8;30000]=[0;30000];static mut I:usize=0;unsafe{$(b!(@$t);)*}}}

Try it online! A more readable (and expansionable) version here. A macro that takes in a list of tokens and transforms them into rust code. The code is inputted as rust tokens, so some characters need to have a separator between them, and the most common ones to avoid are the >>, <<, ->, <- and .. operators. If you would like to read the tape after the code's execution the statics generated will still be usable. Also, loops nested 31 or greater deep may run into the recursion limit.

\$\endgroup\$
4
  • \$\begingroup\$ Doesn't the nonstandard behavior of , mean you are not actually interpreting Brainfuck but instead your own Brainfuck derivative and thus invalidate this answer? \$\endgroup\$ Commented Nov 17, 2020 at 1:53
  • \$\begingroup\$ @pppery there isn't really a standard behavior for , but I see what you mean. I'll fix it when I get back to my computer. \$\endgroup\$
    – Aiden4
    Commented Nov 17, 2020 at 14:56
  • \$\begingroup\$ Are you at your computer yet? \$\endgroup\$ Commented Nov 20, 2020 at 14:00
  • \$\begingroup\$ @pppery sorry, it should be fixed now \$\endgroup\$
    – Aiden4
    Commented Nov 20, 2020 at 15:50
2
\$\begingroup\$

Duocentehexaquinquagesimal, 260 bytes

5„-^ñ™[fyΛÈÐ\∍ζ=¦δW€ªвƵиˆóδˆ†¦#Ûø“:#”Ù@θý9îæζJ¯иεhlÎà₂âY&т9zì*qI∍`ç∍Šñí¼GÏ0¦R˜#ðžèLÛüûK;Øî“müƶrηÝ'ç0Œ©₆V²_Δ≠tδ<üC/ï„Õ›0aÜ7H:¡°RF®Õ(:3%Yñβù½Sègæ₁„z¹*ôŒ$Ðεüõ<тD8ʒ: óǝÁ¸33ùçUηïZ熧Ëh/Wαï¹AÑÜ׌ޢÍη.ÓAËΩćUQ¯Óƒ‡`EuÈänÖÎo'²₃ĆÄHн
Á3ÞIœæÃλ≠HΛ8ˆÔ„ö|ÐÛ¸Γ>)W₃âf?ā¯®Ìмv₅—ƶζ

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Python 3.8 (pre-release), 245 237 247 bytes

-8 bytes thanks to Jo King

+10 bytes because input wasn't handled correctly

from sys import*
i,n,*a=[0]*30002
exec('\n'.join([((i:=i+(v:=s=='[')-(s==']'))-v)*' '+'while(a[n]): 0 n-=1 n+=1 a[n]+=1 a[n]-=1 a[n]=ord(stdin.read(1)) print(end=chr(a[n]))'.split()[u.index(s)]for s in open(argv[1]).read()if s in(u:='[]<>+-,.')]))

Try it online!

Compiles bf source code to python and execs.

\$\endgroup\$
2
  • \$\begingroup\$ You can just do end=chr(a[n]). The initialisation can also be i,n,*a=[0]*30002 \$\endgroup\$
    – Jo King
    Commented Oct 7, 2021 at 21:58
  • \$\begingroup\$ Ahh, meant to do the last one. Thanks for the end=, wouldn't have thought of that. \$\endgroup\$ Commented Oct 8, 2021 at 0:33
2
\$\begingroup\$

JavaScript (ES6), 222 200 197 196 bytes

-19 bytes by stealing the idea of indexOfing from @GezaKerecsenyi's answer.

Takes BF code (b) and input (i) via currying, and returns the output.

b=>i=>eval(`m=Array(3e4).fill(k=p=0);o='';${[...b].map(c=>'m[p]++@m[p]--@p++@p--@while(m[p]){@}@m[p]=i.charCodeAt(k++)|0@o+=String.fromCharCode(m[p])'.split`@`['+-><[],.'.indexOf(c)]).join`;`};o`)

Try it online!

It works by generating a piece of valid JS code from the BF, then evals it. (If you strip away eval, you can see the generated code.)

Technical details

  • Tape length: 30000 cells
  • Tape left-hand-side: unusable
  • Tape wrap-around: no
  • Max value: 253-1 (JS MAX_SAFE_INTEGER)
  • Negative numbers: allowed
  • EOF: 0 (solution with -2 bytes possible by letting EOF corrupt the tape with a NaN)
\$\endgroup\$
2
\$\begingroup\$

Rattle, 234 bytes

\&[0]*199&99&\|!I[g0P4I~n[62P2g+s][60P2g-s][43f6+f5][45f6-f5][46f6,][91f6[0f0]]
[93f6[^0f1]][44g3P5I~nP2f5P5g+s]P4g+sg0I^[~q]g]0;P6g=+s[P4g+f2[91f3]g8[93f4[0f]]]0
;P6g=+s[P4g-f2[93f3]g8[91f4[0f]]]0;sg0I~ns8;P6g+s;P6g-s;r`g1l(~,\);g1P2I~

(without the line breaks)

Try it Online!

This is by far Rattle's most complicated program yet.

This takes Brainf*** code as the first line of input and input for the Brainf*** code as the second line of input. Note that Rattle expects the second line to exist even if there is no input for Brainf***.

Here's a similar example except instead of the classic Hello World!, I've modified it to take ! as input but otherwise still output the same thing.

Explanation

This program is a little lengthy to do a full explanation for but here's a much more human-readable version of the program:

\&[0]*199&99&\|!I

[
  g0 P4 I~n

  [62 g2 + s2]
  [60 g2 - s2]
  [43 g1 P2 I~ + r` g1 l(~,\)]
  [45 g1 P2 I~ - r` g1 l(~,\)]
  [46 g1 P2 I~ ,]
  [91 g1 P2 I~ [0 f0]]
  [93 g1 P2 I~ [^0 f1]]
  [44 g3 P5 I~ n r` g1 P2 l(~,\) g5 + s5]

  g4 + s4
  g0 I^ P4 [~q]
  P4g
]0

;g6 =+ s6 [g4 + s4 g0 P4 I~ n s8 [91 g6 + s6] g8 [93 g6 - s6 [0 f]]]0
;g7 =+ s7 [g4 - s4 g0 P4 I~ n s8 [93 g7 + s7] g8 [91 g7 - s7 [0 f]]]0

:(this line and below is just a comment)
data tape values:
0 - code
1 - code data tape
2 - code pointer
3 - input
4 - code command index
5 - input character index
6 - open loop counter
7 - close loop counter
8 - temp
\$\endgroup\$
2
\$\begingroup\$

nice-expr, 660 bytes

var f is func(str)none func(var C is str)none{var T is list[int]repeat(0,30001);var p is int;var B is map[int]int;var b is list[int];for var i is int0{var c is str C_i;if c="["then{set b+[i];}else if c="]"then{set B@b_-1is i;set B@i is b_-1;set b is b_0..-1;};set i+1;if i>=len(C)then{break;};};for var i is int0{var c is str C_i;if c=">"then{set p+1;}else if c="<"then{set p-1;}else if c="+"then{set T@p is(T_p)+1;}else if c="-"then{set T@p is(T_p)-1;}else if c="."then{print(char(T_p));}else if c=","then{set T@p is ord(inputchar());}else if c="["and(T_p)=0then{set i is B_i;}else if c="]"and(T_p)!=0then{set i is B_i;};set i+1;if i>=len(C)then{break;};};};

This is a function that takes takes in the brainfuck code as a string.

This certainly can be golfed down; half the code in the solution is only dedicated to pairing up brackets to each other.

Ungolfed Explanation

var interpret is func(str)none func(var code is str)none {
    // there are neither 8-bit, nor unsigned, types in nice-expr.
    // a list of ints will have to do.
    var tape is list[int] repeat(0,30000);
    var ptr is int 0; // start on the start of the tape.

    var brackets is map[int]int <||>; // keys and values are indexes of brackets.

    var bracketStack is list[int] []; // stack that holds left bracket indexes
    for var i is int 0 { // first pass: match up brackets
        var c is str code_i;
        if c = "[" then {
            set bracketStack + [i]; // push a left bracket
        } else if c = "]" then {
            // pop a left bracket
            var left is int bracketStack_-1;
            set bracketStack is bracketStack_0..-1;
            var right is int i;
            set brackets@left is right;
            set brackets@right is left;
        };
        set i + 1;
        if i >= len(code) then { break; };
    };

    for var i is int 0 {
        var c is str code_i;
        if c = ">" then {
            set ptr + 1;
        } else if c = "<" then {
            set ptr - 1;
        } else if c = "+" then {
            set tape@ptr is (tape_ptr) + 1;
        } else if c = "-" then {
            set tape@ptr is (tape_ptr) - 1;
        } else if c = "." then {
            print(char(tape_ptr));
        } else if c = "," then {
            set tape@ptr is ord(inputchar());
        } else if c = "[" and (tape_ptr) = 0 then {
            set i is brackets_i; // jump to the matching right bracket
        } else if c = "]" and (tape_ptr) != 0 then {
            set i is brackets_i; // jump to matching left bracket
        };

        set i + 1;
        if i >= len(code) then { break; };
    };
};
\$\endgroup\$
2
\$\begingroup\$

ASCII FALSE, 365 bytes

Takes Brainfuck program and input separated by $ ("end of Brainfuck"); very slow (replacing a cell is a linear time operation with bad constant factors; loops search for the matching bracket each time they are executed). Could be optimized by (1) doing peephole optimizations on most commands, most notably stripping loops, memorizing loop targets and compressing sequences of +/- into single instructions (2) using binary trees as the array representation, giving better O(log n) modification time (much more complex; requires managing binary trees, and basic GC if no memory is to be leaked).

EOF is all ones (255; it's unclear what "no EOF symbol" is supposed to mean). Overflow being undefined behavior is taken advantage of. The pointer not over/underflowing is taken advantage of as well.

Runs "hello world" correctly as well as the prime finder, though it is very inefficient (as expected). I recommend first stripping the prime finder of comments, then appending $<small number>:

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

This runs in about 1s for me, producing

Primes up to: 2 3 5 7 11 13 17 19

(Since input is given after the program in stdin, the number "up to" which primes are printed is of course missing from the output; this could be addressed by outputting all read characters (insert $, after ^), if desired.)

Note: This is ASCII FALSE, using O instead of ø (if ø were to be used instead, it would be a couple bytes longer) and B instead of ß (buffering is not relevant here however). Interpreters for ASCII FALSE can be found here.

Golfed

[n;0=$[%%x;0~]?~[$0=$[% % n;1-n:q;!0 0~]?~[$1&\2/\ $[% q;!2*1|0~]?~[q;!2*]?]?]?]q:0c:[^$'$=~][c;1+c:]#%30000$t:[1-$][0\]#0i:0p:[t;c;+i;-1-O]o:[x:p;n:q;!]s:[o;!$'[=[b;1+b:]?']=[b;1-b:]?]j:[c;i;>][o;!k:k;'.=[p;O,]?k;',=[^255&s;!]?k;'>=[p;1+p:]?k;'<=[p;1-p:]?k;'+=[p;O1+s;!]?k;'-=[p;O1-s;!]?k;'[=[p;O0=[1b:[b;][i;1+i:j;!]#]?]?k;']=[p;O[1_b:[b;][i;1-i:j;!]#]?]?i;1+i:]#

There are most probably quite a few more easy golfs possible.

Ungolfed

The core function is q ("shove/splice"), which allows fully using the stack like an array by remembering items on the call stack, then mutating the stack by replacing an element, and then restoring the elements remembered on the call stack. Once we can use the stack as an array, the rest is straightforward.

{
    shove/splice (q):
    pop n elements, remembering them on the call stack,
    then mutate the stack, dropping an item and replacing it with x,
    then restore the popped elements

    invocation: 101x: 42n: q;!
}
[
    n;0=
    $[% %x; 0~]?
    ~[
        $0=
        $[
            % {kill cond}
            % {kill dup'd zero on stack}
            n; 1- n:
            q;!
            0 {this is to be left on the stack}
            0~
        ]?
        ~[
            $ 1& {extract lowest bit}
            \ 2/ \ {>> 1 thing on stack}
            $[
                % q;! 2* 1| 0~
            ]?
            ~[
                q;! 2*
            ]?
        ]?
    ]?
]q:

0c: {# commands}
[^$ '$=~][c;1+c:]# {loop until `$` is encountered, leaves chars on stack}
% {drop '$}

30000$t:[1-$][0\]# {leave 30k 0's on the stack (note: final iteration will leave zeroed counter itself on stack)}

0i: {instruction pointer}
0p: {data pointer (0-based)}
[t;c;+ {depth of stack} i;- 1- O]o: {get (o)p}

[x: p;n: q;!]s: {set item}

[
    o;!
    $'[=[b;1+b:]?
    ']=[b;1-b:]?
]j: {count bracket balance}

[c;i;>][
    o;! k:
    k;'.=[p;O ,]?
    k;',=[^ 255& s;!]?
    k;'>=[
        p;1+p:
    ]?
    k;'<=[
        p;1-p:
    ]?
    k;'+=[p;O 1+ s;!]?
    k;'-=[p;O 1- s;!]?
    k;'[=[
        p;O 0=[
            1b: {balance}
            [b;][
                i;1+i:
                j;!
            ]#
        ]?
    ]?
    k;']=[
        p;O [
            {analogeous with two small changes}
            1_ b: {balance}
            [b;][
                i;1-i:
                j;!
            ]#
        ]?
    ]?
    i;1+i:
]#
```
\$\endgroup\$
2
\$\begingroup\$

Atto-8*, 0 bytes

*with brainfuck frontend

Unfortunately couldn't manage to golf off additional bytes. Open to suggestions if anyone has pointers.

Explanation

The Atto-8 microprocessor, when built with its brainfuck frontend, begins executing ASCII-encoded brainfuck directly from RAM, on bare metal. The microprocessor's machine code is brainfuck source code, and so no interpreter is required.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to Code Golf! Atto-8 looks very cool, thanks for sharing it on this site. I think you would have to change the header of this post to "Atto-8 + BF Frontend, 0 bytes". I'd be interested in seeing some golf submissions written for the Atto-8, maybe in some sort of assembly. \$\endgroup\$ Commented Nov 7, 2023 at 20:58
2
\$\begingroup\$

TI-Basic (TI-84 Plus), 519 bytes

*fixed an error

"................................ !.....'()*+,-./0123456789:.<=>?.ABCDEFGHIJKLMNOPQRSTUVWXYZ[.]^..abcdefghijklmnopqrstuvwxyz{.}.→Str2
Prompt Str1
50→dim(L₁
Fill(0,L₁
50→Dim(L₂
Fill(0,L₂
5→P
0→L
0→D
0→X
1→Y
0→S
ClrHome
For(I,1,length(Str1
sub(Str1,I,1→Str3
If not(D
Then
If Str3=",
Then
Input Str4
inString(Str2,Str4→L₁(P
End
If Str3=".
Then
If L₁(P
Output(int(X/16)+1,remainder(X,16)+1,sub(Str2,L₁(P),1
X+1+X
End
L₁(P)+(Str3="+")-(Str3="-→L₁(P
remainder(abs(254(L₁(P)<0)-L₁(P)),256→L₁(P
P+(Str3=">")-(Str3="<→P
End
If Str3="[
Then
If L₁(P
Then
L+1→L
I→L₂(L
Else
S+1→S
1→D
End
End
If Str3="]
Then
S(S>1→S
If D(S=1
Then
0→D
0→S
Else
If L₁(P
Then
L₂(L→I
Else
L-1→L
End
End
End
End

I had to re-create the ASCII code page myself, since the TI-84 plus doesn't have a command that gets a character from its char code. The periods are characters that are not on the TI-84 Plus.

Keep in mind this is extremely slow at just printing Hello World (around 70 seconds to do it) so I couldn't imagine it trying to calculate primes.

It prompts you for code when the program starts, you MUST put a quotation mark (") before your code because of how the TI-84 works.

When prompting you for an input, you also have to put a quotation mark before your input.

There might be an error in the code due to me manually copying it from my calculator to my computer. If there is, please tell me.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ you don't need to initialize variables to zero and fill the lists with zeros, since you can assume a fresh environment \$\endgroup\$
    – MarcMush
    Commented May 17 at 17:32
  • \$\begingroup\$ @MarcMush ah! I didn't know I could do that. I'll try to fix it once my calculator starts working again since its been having temper tantrums as of late and not turning on =c \$\endgroup\$ Commented May 20 at 13:32
2
\$\begingroup\$

Acc!!, 678 652 bytes

-26 bytes thanks to @Mukundan314

Count i while _/256^(8+i)-33 {
_+N*256^(9+i)+2^32
}
Count i while (_-_/2^32)%2^16 {
_-(_/2^48%256-_/256^(9+_%2^16)%256)*2^48-(_/2^64%256-_/256^(9+(_/2^16+_/2^32)%2^16)%256)*2^64
Count j while 0^(_/2^48%256-91-j)^2*0^(_/2^64%256)^2+_/2^64%256*0^(_/2^48%256-93-j)^2+_/2^56%256 {
_+(92-_/2^48%256)*0^0^j
_+2^56*(0^(_/256^(9+_%2^16)%256-91)^2-0^(_/256^(9+_%2^16)%256-93)^2)*(92-_/2^48%256)
}
Count j while 0^(_/2^48%256-44)^2-j {
_-(_/2^64%256-N)*256^(9+(_/2^16+_/2^32)%2^16)
}
Count j while 0^(_/2^48%256-46)^2-j {
Write _/2^64%256
}
_+256^(9+(_/2^16+_/2^32)%2^16)*(0^(_/2^48%256-43)^2-0^(_/2^48%256-45)^2)+2^16*(0^(_/2^48%256-62)^2-0^(_/2^48%256-60)^2)+1

Try it online!

Explanation

# Accumulator is split up into indivually-addressable chunks of bytes
# MSB [memory][code][memcache][depth][codecache][c][p][r] LSB, where:
#   Field       Size    LSb/LSB     Explanation
#   r           u16     2^0         Program counter / instruction pointer
#   p           u16     2^16        Memory pointer
#   c           u16     2^32        Size of code in bytes
#   codecache   u8      2^48        Saved copy of code[r] to save space
#   depth       u8      2^56        Current bracket depth when handling [ and ]
#   memcache    u8      2^64        Saved copy of memory[p] to save space
#   code        u8[c]   256^9       Code as read directly from input
#   memory      u8[]    256^(9+c)   Brainfuck memory tape

# Bit k of _    (_/2^k%2)
# Byte k of _   (_/256^k%256)
# code[c]       (_/256^(9+_/2^32%2^16)%256)
# code[r]       (_/256^(9+_%2^16)%256)
# memory[p]     (_/256^(9+(_/2^16+_/2^32)%2^16)%256)
# a == b        0^(a-b)^2
# a != b        a-b (or 0^0^(a-b)^2 for only 0/1 output)
# if(cnd) _+=i  _+i*0^(cnd)^2
# if(cnd) {..}  Count z while 0^(cnd)^2-z {..}

# Read source code while code[c-1] != 33 ('!')
# i = c in this loop
Count i while _/256^(8+i)-33 {
    _ + N*256^(9+i) + 2^32 # Read N to code[c] and c++
}

# Interpret loop
# Loop while r != c (while r-c nonzero)
Count i while (_-_/2^32)%2^16 {
    # Cache code[r] in 2^48 to reduce duplication
    # Cache memory[p] in 2^64 to reduce duplication
    # Clear old values and set new values
    _ - (_/2^48%256 - _/256^(9+_%2^16)%256) * 2^48
      - (_/2^64%256 - _/256^(9+(_/2^16+_/2^32)%2^16)%256) * 2^64

    # Handle [ and ] instructions - code[r] == 91/93
    # Skip / backtrack to matched ] / [ while depth nonzero
    Count j while
        0^(_/2^48%256-91-j)^2 * 0^(_/2^64%256)^2 # (code[r]==91 & memory[p]==0)
        + _/2^64%256 * 0^(_/2^48%256-93-j)^2  # or (code[r]==93 & memory[p]!=0)
        + _/2^56%256                          # or (depth!=0)
    {
        # r++/-- if past first iteration
        # Since code[r] is 91 or 93, 92-code[r] is 1/-1 for [/] respectively.
        _ + (92-_/2^48%256) * 0^0^j

        # depth++/-- if code[r] == 91 / [
        # depth--/++ if code[r] == 93 / ]
        _ + 2^56
            * (0^(_/256^(9+_%2^16)%256-91)^2 - 0^(_/256^(9+_%2^16)%256-93)^2)
            * (92-_/2^48%256)
    }
    
    # Handle , instruction - code[r] == 44
    Count j while 0^(_/2^48%256-44)^2-j {
        # Clear memory[p] / Read N into memory[p]
        _ - (_/2^64%256 - N)*256^(9+(_/2^16+_/2^32)%2^16)
    }

    # Handle . instruction - code[r] == 46
    Count j while 0^(_/2^48%256-46)^2-j {
        Write _/2^64%256 # Print memory[p]
    }

    # Handle + instruction / memory[p]++ if code[r] == 43
    # Handle - instruction / memory[p]-- if code[r] == 45
    # Handle < instruction / p-- if code[r] == 60
    # Handle > instruction / p++ if code[r] == 62
    # Next instruction / r++
    _ + 256^(9+(_/2^16+_/2^32)%2^16)
        * (0^(_/2^48%256-43)^2 - 0^(_/2^48%256-45)^2)
      + 2^16
        * (0^(_/2^48%256-62)^2 - 0^(_/2^48%256-60)^2)
      + 1

# } for this count block can be omitted as i is never used (interpreter bug)
\$\endgroup\$
2
1
\$\begingroup\$

Lua (to long)

I made some Lua implementation, but I can't get the bracket stuff right. Here it is anyway:

-- >    increment the data pointer (to point to the next cell to the right).
-- <    decrement the data pointer (to point to the next cell to the left).
-- +    increment (increase by one) the byte at the data pointer.
-- -    decrement (decrease by one) the byte at the data pointer.
-- .    output a character, the ASCII value of which being the byte at the data pointer.
-- ,    accept one byte of input, storing its value in the byte at the data pointer.
-- [    if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the
--      command after the matching ] command*.
-- ]    if the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the
--      command after the matching [ command*.
s=setmetatable({0},{__index=function() return 0 end})

i=1 -- index array
j=1 -- index input
l=loadstring
t="><+-.,[]"
o=0
fh=arg[1] and io.open(arg[1]) or io.stdin
I=fh:read"*a":gsub("[^><%+%-%.,%[%]]","")
fh:close()
print(I)
for k=1,#I do io.write(k%5==1 and"+"or"-") end
io.write"\n"
for k=1,math.ceil(#I/5) do local n=5*(k-1)+1 local s=(" "):rep(4-math.floor(math.log10(n))) io.write(n,s) end
io.write"\n"
dbg=true
f={
"i=i+1 ",   -- array index ++
"i=i-1 ",   -- array index --
"s[i]=(s[i]+1)%256 ",   -- byte + 1
"s[i]=(s[i]-1)%256 ",   -- byte - 1
"io.write(string.char(s[i])) ", -- put byte
"local c=io.read(1):byte()s[i]=c==10 and s[i] or c",        -- read byte "Newline required!"
[=[if s[i]==0 then
    o=0
    repeat
        if dbg then print(j,"Forward!",o,b) end
        b=I:sub(j,j):match'[%[%]]'
        o= b=='['and o+1 or b==']' and o-1 or o;
        j=j+1
    until b==']' and o == 0
end
]=],    -- jump to matching ]
[=[
if s[i]~=0 then
    o=0
    count=0
    repeat 
        if dbg then print(j,"Backwards",o,b) end
        b=I:sub(j,j):match"[%[%]]"
        o= b=='['and o-1 or b==']' and o+1 or o;
        j=j-1
    until b=='[' and o == 0
end
]=],    -- jump to matching ]
}
for k,v in ipairs(f) do f[t:sub(k,k)],e=l(v) if e then error(e)end end
function run()
j=1
while j<=#I do
    f[I:sub(j,j)]()
    j=j+1
end
end
res,err = pcall(run)
if not res then
    print('error=',err)
    print('Dumping state')
    print('','stack')
    for k,v in pairs(s) do print("",k,v) end
end
if debug then
    print("stack")
    for k,v in pairs(s) do print(k,v) end
end

It doesn't pass the prime test, but acts nicely with Hello World and all echo and reverse examples I tried. So if anyone sees the bug, feel free to catch it.

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

Smalltalk, Squeak 4.x flavour 414 chars

Here is an interpreter which works exclusively with streams and block closures:

b:=[:c :i :o :n |
| v |
v := 1 to: n.
v := (v collect: [:x| | t |
    t := 0.
    Dictionary newFrom: {
        $+ -> [t:=t+1\\256].
        $- -> [t:=t-1\\256].
        $. -> [o nextPut:t].
        $, -> [t:=i next].
        $< -> [v back].
        $> -> [v next].
        $[ -> [t=0 and: [
            [c next=$[
                ifTrue: [(v peek at: $[) value].
             c peek=$]] whileFalse.
            c next]].
        $] -> [t=0 or: [c back.
            [c back=$]
                ifTrue: [(v peek at: c next) value. c back;back].
             c peek=$[] whileFalse.
            c next]].
        }]) readStream.
[c atEnd] whileFalse: [(v peek at: c next ifAbsent: [[]]) value]]
  • c is a readStream on code
  • i is a readStream on input (a ByteArray)
  • o is a writeStream on output (a ByteArray)
  • v is a readStream on interpreters (an Array)
  • n is number of cells

For each cell, we create an interpreter - that is a Dictionary which associate a Block to each BF command (a Character).
Those blocks close over a value t, initialized at zero.
The jump instructions are implemented recursively.
The pointers (code and data) are hidden in streams state.

To use the interpreter, we just have to feed this block with proper streams:

c := 'http://esoteric.sange.fi/brainfuck/bf-source/prog/PRIME.BF' asUrl retrieveContents contents readStream.
i := '15\' withCRs withUnixLineEndings asByteArray readStream.
o := #[] writeStream.
n := 30000.
b valueWithArguments: {c.i.o.n}.
^'',o contents

The interpreter can be golfed to 414 chars, using as:Dictionary which is shorter and by removing overflow and underflow protections (the cell value is then unbound).

b:=[:c :i :o :n||v|v:=1to:n.v:=(v collect:[:x||t|t:=0.{$+->[t:=t+1].$-->[t:=t-1].$.->[o nextPut:t].$,->[t:=i next].$<->[v back].$>->[v next].$[->[t=0and:[[c next=$[ifTrue:[(v peek at:$[)value].c peek=$]]whileFalse.c next]].$]->[t=0or:[c back.[c back=$]ifTrue:[(v peek at:c next)value.c back;back].c peek=$[]whileFalse.c next]]}as:Dictionary])readStream.[c atEnd]whileFalse:[(v peek at:c next ifAbsent:[[]])value]].
\$\endgroup\$
1
\$\begingroup\$

C: 317 characters (reads from a file)

#include <stdio.h>
char t[30000],*p=t,b[30000],c;void r(char*a){while((c=*a++)&&c-93){p+=c==62;p-=c==60;*p+=c==43;*p-=c==45;c^46||putchar(*p);c^44||(*p=getchar());if(c==91){while(*p)r(a);c=1;while(c+=(*a==91)-(*a++==93));}}}int main(int n,char**a){FILE*f;f=fopen(a[1],"r");fread(b,1,30000,f);fclose(f);r(b);return 0;}

This is my brainfuck interpreter that I wrote for a couple of months ago, it's quite a bit longer than it needs to be, but that is because I didn't focus on size when I wrote it, I focused on readability (just the fact that it compiles without error and even includes a library suggest that it is heavily shrinkable).

And expanded:

#include <stdio.h>
char t[30000],*p=t,b[30000],c;
void r(char*a){
    while((c=*a++)&&c-93){
        p+=c==62;
        p-=c==60;
        *p+=c==43;
        *p-=c==45;
        c^46||putchar(*p);
        c^44||(*p=getchar());
        if(c==91){
            while(*p)r(a);
            c=1;
            while(c+=(*a==91)-(*a++==93));
        }
    }
}
int main(int n,char**a){
    FILE*f;
    f=fopen(a[1],"r");
    fread(b,1,30000,f);
    fclose(f);
    r(b);
    return 0;
}

I might return with an actually golfed version.

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

LiveScript evaling JavaScript: 263

Note that this is currently untested.

p='process.std';g=p+'in.read';f='function(x){return';eval "eval('var i=0,m=[#{[0]*3e4*\,}];'+#g().map(#f'[]+-<>,.'.indexOf(x)).filter(#f~-x).map(#f['#{"while(8){,},i++,i--,8++,8--,#{p}out.write(String.fromCharCode(8)),#g(1)"/','*"','"/'8'*'m[i]'}'][x]).join(''))"

Ungolfed:

p='process.std'
g=p+'in.read'
f='function(x){return'
eval """
  eval('
      var i = 0,
          m=[#{[0]*3e4*\,}];' +
    #{g}()
      .map(#{f} '[]+-<>,.'.indexOf(x))
      .filter(#{f} ~-x)
      .map(#{f} ['#{
        "while( 8 ){ 0
         } 0
         i++ 0
         i-- 0
         8++ 0
         8-- 0
         #{p}out.write(String.fromCharCode( 8 )) 0
         #{g}(1)" / '0' * "','" / '8' * 'm[i]'
       }'][x])
       .join(''))
"""
\$\endgroup\$
1
\$\begingroup\$

Binary Lambda Calculus 104 bytes (829 bits)

I didn't come up with this solution. Go credit whoever put it on wikipedia. However it is amazing.

( λ 11 ) ( λ ( λ λ λ 1 ( λ ( λ 2111 ( λ λ 133 ( λ λ 1 ( λ λ ( λ 7 ( 1 ( 3 ( λ λ λ λ λ 10 ̲ ( 1 ( λ 6143 ) ) ( λ 15 ( 65432 ) ) ) ( λ λ 2 ( ( λ 11 ) ( λ λ λ 2 ( λ λ λ 662 ( λ λ 6 ( λ 1 ( 26 ) 3 ) ( 15 ̲ ( 51 ( λ 1 ) ) ( 5 ( λ 1 ) 1 ) ) ) ) ( 12 ( λ λ λ 312 ) ) ) 1 ( λ λ 2 ) ) ) ) ) ( 3 ( 1 ( λ λ λ λ 9 ( 1 ( λ 51 ( λ 154 ) ) ) ( 24 ( λ 142 ) ) ) ) ( 5 ( 11 ̲ ( λ 1 ) ) ( 12 ̲ ( λ 2 ( ( λ 11 ) ( λ λ λ 1 ( ( λ 11 ) ( λ λ λ 2 ( 1 ( 33 ) ) ( λ 8 ( 771 ) ) ) ) 21 ) ) ) ) ) ) ) ( λ 12 ̲ ( λ 12 ̲ ( λ 3 ( 21 ) ) ) ) ) ) ) ) ( λ λ 1 ) ) ) ( 11 ) ) ( λ ( λ 11 ) ( λ λ 1 ( ( λ 1 ( 1 ( 1 ( λ λ 1 ( λ λ 2 ) 2 ) ) ) ) ( λ λ 2 ( 21 ) ) ( λ λ 1 ) ) ( 22 ) ) ( 1 ( λ λ λ λ λ λ 1 ) ) 1)

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I'm not sure that this actually fulfills the criteria – it doesn't handle non-brainfuck-syntax as comments, and it has an unbounded tape instead of the bounded one required by the question. \$\endgroup\$ Commented Nov 29, 2015 at 10:15
1
\$\begingroup\$

SmileBASIC, 258 bytes

C=0DEF B S,K
DIM M[3E4]FOR I=0TO LEN(S)-1C=ASC(S[I])N=M[P]ON!F GOTO@C?CHR$(N)*(C==46);
O=C==91F=!N*O
K=K+CHR$(I)*O*!F
IF C==93THEN I=ASC(POP(K))-1
M[P]=N-N(42)P=P+N(59)IF C==44THEN M[P]=ASC(SHIFT(K))@C:F=F-N(90)
NEXT
END
DEF N(L)RETURN(C-L-2)*(C<L&&C<L+4)END

Call the function as B code,input

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

Python 3, 306 bytes (no eval)

from sys import*
s=open(argv[1]).read()
d=[0]*30000
i=p=a=0
k=[]
j=k+d
for o in s:
 if o==']':j[a]=k.pop();j[j[a]]=a
 k+=[a]*(o=='[');a+=1
while i<a:x,r='[]<>,.+-'.find(s[i]),d[p];d[p],p=(r+(x==6)-(x>6))%256if 4!=x else ord(stdin.read(1)),p+(x==3)-(x==2);i=j[i] if x==(r>0)else 1+i;print(end=chr(r)*(5==x))

Outputs null (0x00) characters though, and times out on prime example but should theoretically finish.
Can still be improved a bit.

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

Go, 377 bytes

I just had to Golf this. Straightforward implementation; leverages constraints (no overflows, no bad instructions), prime finder works as expected. Takes path to Brainfuck program as first argument and input over stdin.

package main
import."os"
func main(){
var t[30000]uint8
d,i,s:=0,0,[]byte{0}
c,_:=ReadFile(Args[1])
for;i<len(c);i++{m:=func(j int){b:=j
for b!=0{i+=j
switch c[i]{case'[':b++
case']':b--}}}
switch c[i]{case',':Stdin.Read(s);t[d]=s[0]
case'.':s[0]=t[d];Stdout.Write(s)
case'<':d--
case'>':d++
case'+':t[d]++
case'-':t[d]--
case '[':if t[d]==0{m(1)}
case ']':if t[d]!=0{m(-1)}}}}
\$\endgroup\$
1
\$\begingroup\$

Lua, 353 bytes

Doesn't beat the other working Lua solution which transpiles the entire source to Lua, then runs that rather than doing the mish-mash this one does; very inefficient due to the use of heavy pattern matching for finding matching brackets concisely.

s=io.open(...):read"*a"f="if(d[p]or 0)%s0 then i=%s end"d={}p=1 i=1 while#s>i do load(({[43]="d[p]=(d[p]or 0)+1",[45]="d[p]=(d[p]or 0)-1",[60]="p=p-1",[62]="p=p+1",[46]="io.write(string.char(d[p]or 0))",[44]="d[p]=io.read(1):byte()",[91]=f:format("==","s:find('^%b[]()',i)-1"),[93]=f:format(">","s:sub(1,i):find('()%b[]$')")})[s:byte(i)]or"")()i=i+1 end

Or with some formatting:

s=io.open(...):read"*a"
f="if(d[p]or 0)%s0 then i=%s end"
g=""d={}p=1
i=1
while#s>i do
    load(({
        [43]="d[p]=(d[p]or 0)+1",
        [45]="d[p]=(d[p]or 0)-1",
        [60]="p=p-1",
        [62]="p=p+1",
        [46]="io.write(string.char(d[p]or 0))",
        [44]="d[p]=io.read(1):byte()",
        [91]=f:format("==","s:find('^%b[]()',i)-1"),
        [93]=f:format(">","s:sub(1,i):find('()%b[]$')")
    })[s:byte(i)]or"")()i=i+1
end
\$\endgroup\$
1
\$\begingroup\$

Julia 1.7, 193 bytes

!x="let a=fill(0,8^5),i=1
"*replace(x*"]",(["><+-.,[]"...].=>[["i" "a[i]"].*["+=1";"-=1"]...
"print('\0'+a[i])"
"a[i:i]=read(stdin,1)"
"while a[i]>0"
"end"].*";")...,r"."s=>"")|>Meta.parse|>eval

Attempt This Online!

Julia 1.7 is needed for replace with multiple patterns

ungolfed code:

!x="let a=fill(0,8^5),i=1
"*replace(x*"]",	# add `end` to close the `let` block
'>' => "i+=1;",
'<' => "i-=1;",
'+' => "a[i]+=1;",
'-' => "a[i]-=1;",
'.' => "print('\0'+a[i]);",
',' => "a[i:i]=read(stdin,1);",
'[' => "while a[i]>0;",
']' => "end;",
r"."s => ""		# remove all other characters
)|>Meta.parse|>eval

Attempt This Online!

This function takes the program as parameter.
Program with the stricter IO (as a file given as argument): 206 bytes

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

JavaScript - Partial Solution (241 235)

Does not read from file - does not manage PRIMES.BF, but works for Hello World!

// not included in 235 count, the hello world code from wikipedia
var p="++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.",

// partial solution - dies on primes
a=[0,0,0,0,0],b=0
eval(p.replace(/[^\][.,+><-]/g,'').replace(/(.)/g,function(e){return "0while(a[b]){0}0console.log(String.fromCharCode(a[b]))0a[b]=prompt()0++a[b]0--a[b]0++b0--b".split(0)[" [].,+-><".search(new RegExp("\\"+e))]+";"}))

Just copy and paste it into javascript console to see it in action. Works in node.js, or broswer.

I was hoping to get PRIMES.BF to work in node.js, but not been able to emulate STDIN in a synchronous way yet.


With comments

// should read from file - easy with node.js
// this is the `Hello World! ` program from wikipedia
var p="++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.",

// declare a and b. If a needs to be longer, can use:
//     a=[];for(0;a.length<30000;a.push(0))b=0
a=[0,0,0,0,0],b=0

// evaluate
eval(
  // the brainfuck code
  p
  // replacing all the non brainfuck commands with nothing 
  .replace(/[^\][.,+><-]/g,'')
  // replacing all commands (captured in parenthesis) with callback
  .replace(/(.)/g,function(e){
     // return swapped commands
     return "0while(a[b]){0}0console.log(String.fromCharCode(a[b]))0a[b]=prompt()0++a[b]0--a[b]0++b0--b"
     // split into array on the 0 (used as seperator - shorter than "|" when
     // called in .split(0) function)
     .split(0)[
       // matching brainfuck commands
       " [].,+-><"
       // searched with escaped, captured command
       .search(new RegExp("\\"+e))
       // add a semicolon to all statements - extra semicolons do not interfere
       // with execution of javascript
     ]+";"
  })
)
\$\endgroup\$
0
\$\begingroup\$

Simplex v.0.5, 103 bytes

br{j'>=?[v'R;Ru]'<=?[v'L;Ru]'+=?[v'I;Ru]'-=?[v'M;Ru]'.=?[v's;Ru]',=?[v'G;Ru]'[=?[v'{;Ru]']=?[v'};Ru]LL}
b                     ~~ Takes a string input (BF prgm)
 r                    ~~ Reverses the string (pointer is at end)
  {               LL} ~~ Loop until empty cell is found
   j                  ~~ Inserts an empty cell at pointer
    '>                ~~ Sets empty cell to character (>) 
      =               ~~ Sets cell to 1 if > is the current character
       ?[      ]      ~~ Evaluate inside if cell is 1
         v    u       ~~ Goes down, then up
          'R          ~~ Puts the character (R) to the byte
            ;         ~~ Adds the current cell to the outer program
             R        ~~ Goes right (frees up next cell)
    '< =? [v'L;Ru]    ~~ …etc
    '+ =? [v'I;Ru]
    '- =? [v'M;Ru]
    '. =? [v's;Ru]
    ', =? [v'G;Ru]
    '[ =? [v'{;Ru]
    '] =? [v'};Ru]

I used this program to prove that Simplex is Turing-complete, it being reducible to a Turing-complete language. It's simple enough; after evaluation of this program, a second program is evaluated, which contains the BF "transcript". Yeah, it really just compiled BF to Simplex. But hey! I think this is the shortest answer thus posted.

(Note that I implemented a theoretically infinite (unbound) version, as Simplex is thus.)

\$\endgroup\$
3
  • \$\begingroup\$ Is this still accurate? \$\endgroup\$ Commented Feb 28, 2016 at 1:29
  • \$\begingroup\$ @VoteToClose No, I have not yet implemented some of the commands found in this program. \$\endgroup\$ Commented Feb 28, 2016 at 1:31
  • 1
    \$\begingroup\$ ‪:c crosses fingers for Simplex implementation \$\endgroup\$ Commented Feb 28, 2016 at 1:43
1 2
3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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