126
\$\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
  • 7
    \$\begingroup\$ You should clarify about 1) size of memory 2) is memory circled 4) maybe any other details \$\endgroup\$
    – Nakilon
    Jan 28 '11 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\$ Feb 15 '11 at 7:52
  • 43
    \$\begingroup\$ I'd love to see someone answer this in brainfuck. \$\endgroup\$
    – Hannesh
    Mar 14 '11 at 19:15
  • 6
    \$\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\$ Apr 1 '16 at 14:07
  • 4
    \$\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\$ Apr 1 '16 at 14:09

63 Answers 63

3
\$\begingroup\$

OCaml(lex), 497 chars

OCamllex is part of the standard distribution of OCaml.

{let a=Array.create 30000 0
let(%)f g h=f(g h)
let s v i=a.(i)<-v;i
let o d i=s(a.(i)+d)i
let p i=print_char(Char.chr a.(i));flush stdout;i
let r i=s(Char.code(input_char stdin))i
let rec w g i=if 0=a.(i)then i else w g(g i)
let n x=x}
rule t f=parse
|'>'{t(succ%f)lexbuf}
|'<'{t(pred%f)lexbuf}
|'+'{t((o 1)%f)lexbuf}
|'-'{t((o(-1))%f)lexbuf}
|'.'{t(p%f)lexbuf}
|','{t(r%f)lexbuf}
|'['{t((w(t n lexbuf))%f)lexbuf}
|']'|eof{f}
|_{t f lexbuf}
{let _=t n(Lexing.from_channel(open_in Sys.argv.(1)))0}

Save as b.mll and run with

ocamllex b.mll && ocaml b.ml prime.bf

I don't like parsing by hand, so I used the provided lexer generator. From the tokens read, we compose a function for the whole brainf*ck program.

\$\endgroup\$
3
\$\begingroup\$

C# (2861 char, ~84 lines)

This is not the prettiest solution to the problem, and probably not all that 'Golf-ish', since I wasn't as concerned with length as I probably should have been. (I didn't remove the comments or extra white space.) I just wanted to try something in a new language, to see if I could. If I did it again, I'd drop the use of the stack for returning from ']' and just look back. Run without command line arguments it runs the hello world program given in the problem description. It accepts one command line argument, the filename of the program to run.

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            String ProgSource;
            if (args.Length > 0)
                ProgSource = System.IO.File.ReadAllText(args[0]);
            else //hello world
                ProgSource = "";

            Stack<int> stack = new Stack<int>();
            char[] bfProg = ProgSource.ToCharArray();
            char[] mem = new char[30000];
            int ptr = 0;

            for (int ip = 0; ip<bfProg.Length; ip++){
                switch (bfProg[ip])
                {
                    case ('>'): ptr++;  break;
                    case ('<'): ptr--;  break;
                    case ('+'): mem[ptr]++; break;
                    case ('-'): mem[ptr]--; break;
                    case ('.'): Console.Write(mem[ptr]); break;
                    case (','): 
                        char key = Console.ReadKey(false).KeyChar;
                        if (key == '\r')
                        {
                            key = (char)10;
                            Console.WriteLine();
                        }
                        mem[ptr] = key;
                        break;
                    case ('['):
                        if (mem[ptr] == 0)
                        {
                            int openBraces = 1;
                            //find the closing brace for this expression
                            for (int x = 1; x < (bfProg.Length - ip); x++)
                            {
                                if (bfProg[ip + x] == ']') openBraces--;
                                if (bfProg[ip + x] == '[') openBraces++;
                                if (openBraces == 0)
                                {
                                    if (stack.Peek() == ip) stack.Pop();
                                    ip += x;
                                    break;
                                }                                
                            }
                       }
                       else
                       {
                           stack.Push(ip);
                       }
                       break;
                    case (']'):
                        if (mem[ptr] == 0)
                            stack.Pop();
                        else
                        {
                            ip = stack.Peek();
                        }
                        break;
                }
            }

            Console.WriteLine("\n\n\nExecution Completed Sucessfully. Press any key to continue...");
            Console.ReadKey();

        }
    }

}

Edit: Removed unused references.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ @mbomb007 - Updated. Completely forgot I even did this one. (Didn't even realize anyone even read these old questions) \$\endgroup\$
    – theB
    Aug 31 '15 at 21:18
  • \$\begingroup\$ Not only do people still read them, they still answer and golf them. \$\endgroup\$
    – mbomb007
    Nov 15 '16 at 17:08
3
\$\begingroup\$

dirt, 489

'@[^@]*"# @00000000 "(#[^#]*|"#")'#|[^R]*(('<R+`<|'>R+`>|'-R+`-|'+R+`+|'.R+`.|',R+`,|'['RR+`[|']`RR+`])|`R\]'@).*|.*((`<L+'<|`>L+'>|`-L+'-|`+L+'+|`.L+'.|`,L+',|`[`LL+'[|`]'LL+'])|'@\[`L)[^L]*|[^x]*(`x('0[^#]*#`0|'1[^#]*#`1)|(`x'0)+ .*##).*|.*`I",@"[^x]*|.*`o(0'o.*'0|1'o.*'1| .*)|.*`O".@"[^o]*|.*`@(-'@.*@([^ ]*`1'0|)(`0'1)* |\+'@.*@([^ ]*`0'1|)(`1'0)* |<'@.*#( @"00000000 "|.* '@[^ ]+ `@)|>'@.*`@[^ ]+ '@("00000000 "|[^#]+)#|\['@.*@([^ ]*1)|'L\]|\['R.*@0* |`,'I.*@({0|1}'x)* |`.'O.*@'o).*

Has unbounded tape but doesn't work with comment characters.

To run, save as brainfuck.dirt and run dirt brainfuck.dirt -i "[bf_program]#[binary_input]" (# can be omitted if there's no input). It will print [bf_program]#[memory]#[unread_input]#[output].

e.g.

> dirt brainfuck.dirt -i ",[.,]#0100100001001001"
,[.,]@# @00000000 ##0100100001001001

Use the -v flag to watch it as it runs:

    > dirt brainfuck.dirt -v -i "+++++++[>+++++++<-]>.+.+."
+++++++[>+++++++<-]>.+.+.
@+++++++[>+++++++<-]>.+.+.# @00000000 ##
+@++++++[>+++++++<-]>.+.+.# @00000001 ##
++@+++++[>+++++++<-]>.+.+.# @00000010 ##
+++@++++[>+++++++<-]>.+.+.# @00000011 ##
++++@+++[>+++++++<-]>.+.+.# @00000100 ##
+++++@++[>+++++++<-]>.+.+.# @00000101 ##
++++++@+[>+++++++<-]>.+.+.# @00000110 ##
+++++++@[>+++++++<-]>.+.+.# @00000111 ##
+++++++[@>+++++++<-]>.+.+.# @00000111 ##
+++++++[>@+++++++<-]>.+.+.# 00000111 @00000000 ##
+++++++[>+@++++++<-]>.+.+.# 00000111 @00000001 ##
+++++++[>++@+++++<-]>.+.+.# 00000111 @00000010 ##
+++++++[>+++@++++<-]>.+.+.# 00000111 @00000011 ##
+++++++[>++++@+++<-]>.+.+.# 00000111 @00000100 ##
+++++++[>+++++@++<-]>.+.+.# 00000111 @00000101 ##
+++++++[>++++++@+<-]>.+.+.# 00000111 @00000110 ##
+++++++[>+++++++@<-]>.+.+.# 00000111 @00000111 ##
+++++++[>+++++++<@-]>.+.+.# @00000111 00000111 ##
+++++++[>+++++++<-@]>.+.+.# @00000110 00000111 ##
+++++++[>+++++++<-L]>.+.+.# @00000110 00000111 ##
+++++++[>+++++++<L-]>.+.+.# @00000110 00000111 ##
+++++++[>+++++++L<-]>.+.+.# @00000110 00000111 ##
+++++++[>++++++L+<-]>.+.+.# @00000110 00000111 ##
+++++++[>+++++L++<-]>.+.+.# @00000110 00000111 ##
+++++++[>++++L+++<-]>.+.+.# @00000110 00000111 ##
+++++++[>+++L++++<-]>.+.+.# @00000110 00000111 ##
+++++++[>++L+++++<-]>.+.+.# @00000110 00000111 ##
+++++++[>+L++++++<-]>.+.+.# @00000110 00000111 ##
+++++++[>L+++++++<-]>.+.+.# @00000110 00000111 ##
+++++++[L>+++++++<-]>.+.+.# @00000110 00000111 ##
+++++++@[>+++++++<-]>.+.+.# @00000110 00000111 ##
+++++++[@>+++++++<-]>.+.+.# @00000110 00000111 ##
+++++++[>@+++++++<-]>.+.+.# 00000110 @00000111 ##
+++++++[>+@++++++<-]>.+.+.# 00000110 @00001000 ##
+++++++[>++@+++++<-]>.+.+.# 00000110 @00001001 ##
+++++++[>+++@++++<-]>.+.+.# 00000110 @00001010 ##
+++++++[>++++@+++<-]>.+.+.# 00000110 @00001011 ##
+++++++[>+++++@++<-]>.+.+.# 00000110 @00001100 ##
+++++++[>++++++@+<-]>.+.+.# 00000110 @00001101 ##
+++++++[>+++++++@<-]>.+.+.# 00000110 @00001110 ##
+++++++[>+++++++<@-]>.+.+.# @00000110 00001110 ##
+++++++[>+++++++<-@]>.+.+.# @00000101 00001110 ##
+++++++[>+++++++<-L]>.+.+.# @00000101 00001110 ##
+++++++[>+++++++<L-]>.+.+.# @00000101 00001110 ##
+++++++[>+++++++L<-]>.+.+.# @00000101 00001110 ##
+++++++[>++++++L+<-]>.+.+.# @00000101 00001110 ##
+++++++[>+++++L++<-]>.+.+.# @00000101 00001110 ##
+++++++[>++++L+++<-]>.+.+.# @00000101 00001110 ##
+++++++[>+++L++++<-]>.+.+.# @00000101 00001110 ##
+++++++[>++L+++++<-]>.+.+.# @00000101 00001110 ##
+++++++[>+L++++++<-]>.+.+.# @00000101 00001110 ##
+++++++[>L+++++++<-]>.+.+.# @00000101 00001110 ##
+++++++[L>+++++++<-]>.+.+.# @00000101 00001110 ##
+++++++@[>+++++++<-]>.+.+.# @00000101 00001110 ##
+++++++[@>+++++++<-]>.+.+.# @00000101 00001110 ##
+++++++[>@+++++++<-]>.+.+.# 00000101 @00001110 ##
+++++++[>+@++++++<-]>.+.+.# 00000101 @00001111 ##
+++++++[>++@+++++<-]>.+.+.# 00000101 @00010000 ##
+++++++[>+++@++++<-]>.+.+.# 00000101 @00010001 ##
+++++++[>++++@+++<-]>.+.+.# 00000101 @00010010 ##
+++++++[>+++++@++<-]>.+.+.# 00000101 @00010011 ##
+++++++[>++++++@+<-]>.+.+.# 00000101 @00010100 ##
+++++++[>+++++++@<-]>.+.+.# 00000101 @00010101 ##
+++++++[>+++++++<@-]>.+.+.# @00000101 00010101 ##
+++++++[>+++++++<-@]>.+.+.# @00000100 00010101 ##
+++++++[>+++++++<-L]>.+.+.# @00000100 00010101 ##
+++++++[>+++++++<L-]>.+.+.# @00000100 00010101 ##
+++++++[>+++++++L<-]>.+.+.# @00000100 00010101 ##
+++++++[>++++++L+<-]>.+.+.# @00000100 00010101 ##
+++++++[>+++++L++<-]>.+.+.# @00000100 00010101 ##
+++++++[>++++L+++<-]>.+.+.# @00000100 00010101 ##
+++++++[>+++L++++<-]>.+.+.# @00000100 00010101 ##
+++++++[>++L+++++<-]>.+.+.# @00000100 00010101 ##
+++++++[>+L++++++<-]>.+.+.# @00000100 00010101 ##
+++++++[>L+++++++<-]>.+.+.# @00000100 00010101 ##
+++++++[L>+++++++<-]>.+.+.# @00000100 00010101 ##
+++++++@[>+++++++<-]>.+.+.# @00000100 00010101 ##
+++++++[@>+++++++<-]>.+.+.# @00000100 00010101 ##
+++++++[>@+++++++<-]>.+.+.# 00000100 @00010101 ##
+++++++[>+@++++++<-]>.+.+.# 00000100 @00010110 ##
+++++++[>++@+++++<-]>.+.+.# 00000100 @00010111 ##
+++++++[>+++@++++<-]>.+.+.# 00000100 @00011000 ##
+++++++[>++++@+++<-]>.+.+.# 00000100 @00011001 ##
+++++++[>+++++@++<-]>.+.+.# 00000100 @00011010 ##
+++++++[>++++++@+<-]>.+.+.# 00000100 @00011011 ##
+++++++[>+++++++@<-]>.+.+.# 00000100 @00011100 ##
+++++++[>+++++++<@-]>.+.+.# @00000100 00011100 ##
+++++++[>+++++++<-@]>.+.+.# @00000011 00011100 ##
+++++++[>+++++++<-L]>.+.+.# @00000011 00011100 ##
+++++++[>+++++++<L-]>.+.+.# @00000011 00011100 ##
+++++++[>+++++++L<-]>.+.+.# @00000011 00011100 ##
+++++++[>++++++L+<-]>.+.+.# @00000011 00011100 ##
+++++++[>+++++L++<-]>.+.+.# @00000011 00011100 ##
+++++++[>++++L+++<-]>.+.+.# @00000011 00011100 ##
+++++++[>+++L++++<-]>.+.+.# @00000011 00011100 ##
+++++++[>++L+++++<-]>.+.+.# @00000011 00011100 ##
+++++++[>+L++++++<-]>.+.+.# @00000011 00011100 ##
+++++++[>L+++++++<-]>.+.+.# @00000011 00011100 ##
+++++++[L>+++++++<-]>.+.+.# @00000011 00011100 ##
+++++++@[>+++++++<-]>.+.+.# @00000011 00011100 ##
+++++++[@>+++++++<-]>.+.+.# @00000011 00011100 ##
+++++++[>@+++++++<-]>.+.+.# 00000011 @00011100 ##
+++++++[>+@++++++<-]>.+.+.# 00000011 @00011101 ##
+++++++[>++@+++++<-]>.+.+.# 00000011 @00011110 ##
+++++++[>+++@++++<-]>.+.+.# 00000011 @00011111 ##
+++++++[>++++@+++<-]>.+.+.# 00000011 @00100000 ##
+++++++[>+++++@++<-]>.+.+.# 00000011 @00100001 ##
+++++++[>++++++@+<-]>.+.+.# 00000011 @00100010 ##
+++++++[>+++++++@<-]>.+.+.# 00000011 @00100011 ##
+++++++[>+++++++<@-]>.+.+.# @00000011 00100011 ##
+++++++[>+++++++<-@]>.+.+.# @00000010 00100011 ##
+++++++[>+++++++<-L]>.+.+.# @00000010 00100011 ##
+++++++[>+++++++<L-]>.+.+.# @00000010 00100011 ##
+++++++[>+++++++L<-]>.+.+.# @00000010 00100011 ##
+++++++[>++++++L+<-]>.+.+.# @00000010 00100011 ##
+++++++[>+++++L++<-]>.+.+.# @00000010 00100011 ##
+++++++[>++++L+++<-]>.+.+.# @00000010 00100011 ##
+++++++[>+++L++++<-]>.+.+.# @00000010 00100011 ##
+++++++[>++L+++++<-]>.+.+.# @00000010 00100011 ##
+++++++[>+L++++++<-]>.+.+.# @00000010 00100011 ##
+++++++[>L+++++++<-]>.+.+.# @00000010 00100011 ##
+++++++[L>+++++++<-]>.+.+.# @00000010 00100011 ##
+++++++@[>+++++++<-]>.+.+.# @00000010 00100011 ##
+++++++[@>+++++++<-]>.+.+.# @00000010 00100011 ##
+++++++[>@+++++++<-]>.+.+.# 00000010 @00100011 ##
+++++++[>+@++++++<-]>.+.+.# 00000010 @00100100 ##
+++++++[>++@+++++<-]>.+.+.# 00000010 @00100101 ##
+++++++[>+++@++++<-]>.+.+.# 00000010 @00100110 ##
+++++++[>++++@+++<-]>.+.+.# 00000010 @00100111 ##
+++++++[>+++++@++<-]>.+.+.# 00000010 @00101000 ##
+++++++[>++++++@+<-]>.+.+.# 00000010 @00101001 ##
+++++++[>+++++++@<-]>.+.+.# 00000010 @00101010 ##
+++++++[>+++++++<@-]>.+.+.# @00000010 00101010 ##
+++++++[>+++++++<-@]>.+.+.# @00000001 00101010 ##
+++++++[>+++++++<-L]>.+.+.# @00000001 00101010 ##
+++++++[>+++++++<L-]>.+.+.# @00000001 00101010 ##
+++++++[>+++++++L<-]>.+.+.# @00000001 00101010 ##
+++++++[>++++++L+<-]>.+.+.# @00000001 00101010 ##
+++++++[>+++++L++<-]>.+.+.# @00000001 00101010 ##
+++++++[>++++L+++<-]>.+.+.# @00000001 00101010 ##
+++++++[>+++L++++<-]>.+.+.# @00000001 00101010 ##
+++++++[>++L+++++<-]>.+.+.# @00000001 00101010 ##
+++++++[>+L++++++<-]>.+.+.# @00000001 00101010 ##
+++++++[>L+++++++<-]>.+.+.# @00000001 00101010 ##
+++++++[L>+++++++<-]>.+.+.# @00000001 00101010 ##
+++++++@[>+++++++<-]>.+.+.# @00000001 00101010 ##
+++++++[@>+++++++<-]>.+.+.# @00000001 00101010 ##
+++++++[>@+++++++<-]>.+.+.# 00000001 @00101010 ##
+++++++[>+@++++++<-]>.+.+.# 00000001 @00101011 ##
+++++++[>++@+++++<-]>.+.+.# 00000001 @00101100 ##
+++++++[>+++@++++<-]>.+.+.# 00000001 @00101101 ##
+++++++[>++++@+++<-]>.+.+.# 00000001 @00101110 ##
+++++++[>+++++@++<-]>.+.+.# 00000001 @00101111 ##
+++++++[>++++++@+<-]>.+.+.# 00000001 @00110000 ##
+++++++[>+++++++@<-]>.+.+.# 00000001 @00110001 ##
+++++++[>+++++++<@-]>.+.+.# @00000001 00110001 ##
+++++++[>+++++++<-@]>.+.+.# @00000000 00110001 ##
+++++++[>+++++++<-L]>.+.+.# @00000000 00110001 ##
+++++++[>+++++++<L-]>.+.+.# @00000000 00110001 ##
+++++++[>+++++++L<-]>.+.+.# @00000000 00110001 ##
+++++++[>++++++L+<-]>.+.+.# @00000000 00110001 ##
+++++++[>+++++L++<-]>.+.+.# @00000000 00110001 ##
+++++++[>++++L+++<-]>.+.+.# @00000000 00110001 ##
+++++++[>+++L++++<-]>.+.+.# @00000000 00110001 ##
+++++++[>++L+++++<-]>.+.+.# @00000000 00110001 ##
+++++++[>+L++++++<-]>.+.+.# @00000000 00110001 ##
+++++++[>L+++++++<-]>.+.+.# @00000000 00110001 ##
+++++++[L>+++++++<-]>.+.+.# @00000000 00110001 ##
+++++++@[>+++++++<-]>.+.+.# @00000000 00110001 ##
+++++++[R>+++++++<-]>.+.+.# @00000000 00110001 ##
+++++++[>R+++++++<-]>.+.+.# @00000000 00110001 ##
+++++++[>+R++++++<-]>.+.+.# @00000000 00110001 ##
+++++++[>++R+++++<-]>.+.+.# @00000000 00110001 ##
+++++++[>+++R++++<-]>.+.+.# @00000000 00110001 ##
+++++++[>++++R+++<-]>.+.+.# @00000000 00110001 ##
+++++++[>+++++R++<-]>.+.+.# @00000000 00110001 ##
+++++++[>++++++R+<-]>.+.+.# @00000000 00110001 ##
+++++++[>+++++++R<-]>.+.+.# @00000000 00110001 ##
+++++++[>+++++++<R-]>.+.+.# @00000000 00110001 ##
+++++++[>+++++++<-R]>.+.+.# @00000000 00110001 ##
+++++++[>+++++++<-]@>.+.+.# @00000000 00110001 ##
+++++++[>+++++++<-]>@.+.+.# 00000000 @00110001 ##
+++++++[>+++++++<-]>O+.+.# 00000000 @o00110001 ##
+++++++[>+++++++<-]>O+.+.# 00000000 @0o0110001 ##0
+++++++[>+++++++<-]>O+.+.# 00000000 @00o110001 ##00
+++++++[>+++++++<-]>O+.+.# 00000000 @001o10001 ##001
+++++++[>+++++++<-]>O+.+.# 00000000 @0011o0001 ##0011
+++++++[>+++++++<-]>O+.+.# 00000000 @00110o001 ##00110
+++++++[>+++++++<-]>O+.+.# 00000000 @001100o01 ##001100
+++++++[>+++++++<-]>O+.+.# 00000000 @0011000o1 ##0011000
+++++++[>+++++++<-]>O+.+.# 00000000 @00110001o ##00110001
+++++++[>+++++++<-]>O+.+.# 00000000 @00110001 ##00110001
+++++++[>+++++++<-]>.@+.+.# 00000000 @00110001 ##00110001
+++++++[>+++++++<-]>.+@.+.# 00000000 @00110010 ##00110001
+++++++[>+++++++<-]>.+O+.# 00000000 @o00110010 ##00110001
+++++++[>+++++++<-]>.+O+.# 00000000 @0o0110010 ##001100010
+++++++[>+++++++<-]>.+O+.# 00000000 @00o110010 ##0011000100
+++++++[>+++++++<-]>.+O+.# 00000000 @001o10010 ##00110001001
+++++++[>+++++++<-]>.+O+.# 00000000 @0011o0010 ##001100010011
+++++++[>+++++++<-]>.+O+.# 00000000 @00110o010 ##0011000100110
+++++++[>+++++++<-]>.+O+.# 00000000 @001100o10 ##00110001001100
+++++++[>+++++++<-]>.+O+.# 00000000 @0011001o0 ##001100010011001
+++++++[>+++++++<-]>.+O+.# 00000000 @00110010o ##0011000100110010
+++++++[>+++++++<-]>.+O+.# 00000000 @00110010 ##0011000100110010
+++++++[>+++++++<-]>.+.@+.# 00000000 @00110010 ##0011000100110010
+++++++[>+++++++<-]>.+.+@.# 00000000 @00110011 ##0011000100110010
+++++++[>+++++++<-]>.+.+O# 00000000 @o00110011 ##0011000100110010
+++++++[>+++++++<-]>.+.+O# 00000000 @0o0110011 ##00110001001100100
+++++++[>+++++++<-]>.+.+O# 00000000 @00o110011 ##001100010011001000
+++++++[>+++++++<-]>.+.+O# 00000000 @001o10011 ##0011000100110010001
+++++++[>+++++++<-]>.+.+O# 00000000 @0011o0011 ##00110001001100100011
+++++++[>+++++++<-]>.+.+O# 00000000 @00110o011 ##001100010011001000110
+++++++[>+++++++<-]>.+.+O# 00000000 @001100o11 ##0011000100110010001100
+++++++[>+++++++<-]>.+.+O# 00000000 @0011001o1 ##00110001001100100011001
+++++++[>+++++++<-]>.+.+O# 00000000 @00110011o ##001100010011001000110011
+++++++[>+++++++<-]>.+.+O# 00000000 @00110011 ##001100010011001000110011
+++++++[>+++++++<-]>.+.+.@# 00000000 @00110011 ##001100010011001000110011
\$\endgroup\$
3
\$\begingroup\$

Python 3.8 (single expression, no eval), 711 bytes

(g:=lambda s,a,b,p,c:None if p>=len(s)else g(s,a,b,p+1,c+1)if a==s[p]else(p if c==1 else g(s,a,b,p+1,c-1))if b==s[p]else g(s,a,b,p+1,c),x:=lambda f:None if f is None else x(f()),f:=lambda s,p,m,c:[None,(lambda:f(s,*{"+":lambda:(p,m[:p]+[m[p]+1]+m[p+1:],c+1),"-":lambda:(p,m[:p]+[m[p]-1]+m[p+1:],c+1),">":lambda:(p+1,m+[0]*(p+1>=len(m)),c+1),"<":lambda:(max(p-1,0),[0]*(p-1<0)+m,c+1),".":lambda:print(chr(m[p]),end="") or(p,m,c+1),",":lambda:(p,m[:p]+[ord(input())]+m[p+1:],c+1),"[":lambda:(p,m,(g(s,"[","]",c,0)if 0==m[p]else c)+1),"]":lambda:(p,m,len(s)-g(s[::-1],"]","[",len(s)-c-1,0)if m[p]!=0 else 1+c)}.get(s[c],lambda:(p,m,c+1))()))][c<len(s)],x(lambda:f(open(__import__("sys").argv[-1]).read(),0,[0],0)))

I've provided a hello world example here: Try it online!

single expression?

I've seen multiple fun python implementations already, but I thought that another hurdle beside just golfing would be fun. As the single expression part implies the whole solution is packed into a single python expression, through the use of things like assignment expressions (:=).

Explanation

This solution, as it stands, consists of 3 distinct functions:

  • g: facilitates find the index of a matching bracket
  • x: describes the main loop, i.e. drives the state transitions
  • f: implements the state transition of one "machine state" to another, i.e. the meat of the interpreter
g = lambda s, a, b, p, c: (
    None
    if p >= len(s)
    else g(s, a, b, p + 1, c + 1)
    if s[p] == a
    else (p if c == 1 else g(s, a, b, p + 1, c - 1))
    if s[p] == b
    else g(s, a, b, p + 1, c)
)
x = lambda f: None if f is None else x(f())
f = lambda s, p, m, c: [
    None,
    (
        lambda: f(
            s,
            *{
                "+": lambda: (p, m[:p] + [m[p] + 1] + m[p + 1 :], c + 1),
                "-": lambda: (p, m[:p] + [m[p] - 1] + m[p + 1 :], c + 1),
                ">": lambda: (p + 1, m + [0] * (p + 1 >= len(m)), c + 1),
                "<": lambda: (max(p - 1, 0), [0] * (p - 1 < 0) + m, c + 1),
                ".": lambda: print(chr(m[p]), end="") or (p, m, c + 1),
                ",": lambda: (p, m[:p] + [ord(input())] + m[p + 1 :], c + 1),
                "[": lambda: (p, m, (g(s, "[", "]", c, 0) if m[p] == 0 else c) + 1),
                "]": lambda: (
                    p,
                    m,
                    len(s) - g(s[::-1], "]", "[", len(s) - c - 1, 0)
                    if m[p] != 0
                    else 1 + c,
                ),
            }.get(s[c], lambda: (p, m, c + 1))(),
        )
    ),
][c < len(s)]

Finally all of this gets stuffed together using a "simple" call to x with a curried f, already preloaded with the initial state:

x(lambda: f(open(__import__("sys").argv[-1]).read(), 0, [0], 0))

And voilà it works and is a true python one-liner. 🎉

Sadly this interpreter is limited in the amount of characters it can read in as it is driven by recursion and python doesn't like "very" deep recursion...

Python 3.8 (single expression, no recursion, no eval), 702 bytes

(i:=__import__,k:=i("itertools"),g:=lambda s,a,b,p:p+next(i for i,d in enumerate(k.accumulate({a:1,b:-1}.get(c,0)for c in s[p:]))if 0==d),f:=lambda s,p,m,c:(s,*{"+":lambda:(p,m[:p]+[m[p]+1]+m[p+1:],c+1),"-":lambda:(p,m[:p]+[m[p]-1]+m[p+1:],c+1),">":lambda:(p+1,m+[0]*(p+1>=len(m)),c+1),"<":lambda:(max(p-1,0),[0]*(p-1<0)+m,c+1),".":lambda:print(chr(m[p]),end="") or(p,m,c+1),",":lambda:(p,m[:p]+[ord(input()[0])]+m[p+1:],c+1),"[":lambda:(p,m,(g(s,"[","]",c)if 0==m[p]else c)+1),"]":lambda:(p,m,len(s)-g(s[::-1],"]","[",len(s)-c-1)if 0!=m[p]else 1+c)}.get(s[c],lambda:(p,m,c+1))()),i("functools").reduce(lambda s,_:exit(0)if len(s[0])<=s[3]else f(*s),k.count(1),(open(i("sys").argv[1]).read(),0,[0],0)))

To get around the nasty recursion depth in python I rewrote some parts, and it even turned out shorter than before... 🤣

Here is the hello world example for this version: Try it online!

\$\endgroup\$
5
  • 3
    \$\begingroup\$ Welcome to the site! This is a very impressive first answer. Be sure to link to an external site such as Try It Online! in future answers, so that other users can run and verify your program. Hope you enjoy CGCC! \$\endgroup\$ Jun 24 '20 at 21:58
  • \$\begingroup\$ Hi @cairdcoinheringaahing, thanks for letting me know. 👍 I took a look at it and I am left worndering how one could add a default file for a code snippet to read in. My code takes the first provided argument as a filepath and then reads from said file, as such I am unsure how to set that up... \$\endgroup\$
    – timfi
    Jun 25 '20 at 6:51
  • \$\begingroup\$ It isn’t usually the easiest way to take input on TIO, but you can put something in the Header section along the lines of open(“filename”).write(“bf code”) and have filename in the Arguments section: like this, but with your code in the Code section (the link is too long for a comment) \$\endgroup\$ Jun 25 '20 at 10:04
  • \$\begingroup\$ Sounds straight forward enough. Will do. 👍 \$\endgroup\$
    – timfi
    Jun 25 '20 at 10:05
  • \$\begingroup\$ 696 bytes \$\endgroup\$
    – ceilingcat
    Sep 6 '20 at 1:05
3
\$\begingroup\$

[EDIT] C++11, 318, reads from file:

#include <bits/stdc++.h>
char b[99999]={0},g[99999]={0},*f=g,*p=b;std::function<void()>m[128]={[43]=[]{++*p;},[]{*p=getchar();},[]{--*p;},[]{putchar(*p);},[62]=[]{p++;},[60]=[]{p--;},[91]=[]{if(!(*p))while(*f-93)f++;f++;},[93]=[]{while(*f-91)f--;f--;}};int main(){
fread(g,99,999,stdin);for(;*f;f++)if(m[*f])m[*f]();}

https://godbolt.org/z/7xxbqM

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

Python 3 (no eval), 288 286 280 bytes

Based on @boothby's solution, but I replaced recursion with loop+stack and made other changes.

from sys import*
s=[];c=open(argv[1]).read();m=[0]*8**5;k=i=0
while i<len(c):
 x='+-<>[],.'.find(c[i]);u=x>3;i+=1;d=m[1]
 if m[2]<=k:
  e=m[d]and x==4;k=m[2]+e;u=1;*s,i=s+[i-1]*e+[i]*(x!=5)
  if x==6:m[d]=ord(stdin.read(1))
  print(end=chr(m[d]*(x>6)))
 m[x%8>>1or d]+=(1-x%2*2)*u

Try it online!

How it works

  • c - BF code to interpret
  • m - memory, not cyclic (32768 total cells, 3 reserved)
  • i - instruction pointer
  • d - data pointer
  • x - current command (-1 to 7)
  • s - stack of return addresses
  • k - depth at which execution is allowed
  • u - flag: is memory update required
  • e - flag: should loop be executed or skipped

Cells m[1],m[2], and m[3] are reserved for internal use:

  • m[1] - actual data pointer, d is just a shortcut.
  • m[2] - depth counter, it increases on [ and decreases on ]. If depth is more than k, instructions should be ignored: this is how interpreter reaches end of loop when condition is not met (but [ and ] still count depth).
  • m[3] - trash cell, it increases on . and decreases on , and comments, but its value is never used.

To prevent accidental rewrite, user memory is reverted: it starts at m[0], next is m[-1], then m[-2] and so on.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Welcome to Code Golf! \$\endgroup\$
    – Stephen
    Jun 20 '19 at 0:39
  • \$\begingroup\$ @Stephen thank you! I really appreciate you welcome comment, because at the moment I can communicate in my own answers only ;) \$\endgroup\$ Jun 20 '19 at 11:10
  • 1
    \$\begingroup\$ You can replace (1-x%2*2)*u with u-x%2*2*u to win 2 characters. :-) \$\endgroup\$ Feb 5 at 22:34
  • \$\begingroup\$ @PârisDouady thanks! Alas, I found that my latest changes broke it a bit. Gonna fix it first and then apply your great suggestion. \$\endgroup\$ Feb 8 at 23:52
3
\$\begingroup\$

C - 306 243 237 235 bytes

This was actually my second ever code golf, and is from a while ago

char m[30000],*p=m,o[30000];i,c;k(v){return v==o[i];}main(x,y)int**y;{for(read(open(y[1],0),o,30000);o[i];i++)if(*(p+=k(62)-k(60))+=k(43)-k(45),x=k(91)-k(93),read(write(1,p,k(46)),p,k(44)),x&&!!*p^!~-x)for(i+=c=x;c+=k(91)-k(93);)i+=x;}

235 by ceilingcat

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Shouldn't #define a 3000 be #define a 30000 since the array size is specified to be 30000 bytes in the challenge? \$\endgroup\$ Nov 17 '20 at 1:54
  • \$\begingroup\$ @ceilingcat sorry I would have added yours if I had seen it sooner, thanks for the solution tho! \$\endgroup\$
    – Shipof123
    Dec 16 '20 at 15:51
  • \$\begingroup\$ Suggest 'u0' instead of 30000 \$\endgroup\$
    – ceilingcat
    Apr 16 at 4:17
2
\$\begingroup\$

golfscript, partial solution only, 150 chars

:i;[0]30000*[]0 "#{File.open('f').read}"{{\(@=\''if}+['>+\\(@\\' '<@+\\)' '+1+256%' '-1- 256%' ".[0$]''+print " ',;i(\:i;' '[{.}{' ']}while']\%}%~;;;;

i am greatly indebted to the pattern of generating your own source and then eating it, as others have already posted.

misfeatures:

  • only parses brainfuck code from the file 'f'.
  • all input you want to read with ',' must be piped in at the beginning.
  • runs hello world, yet dies somewhere during prime.bf. i'm not sure why. i did read somewhere that golfscript is broken for nested while loops, so that might be it.
  • stores a char=>string map in a way that is entertainingly horrible, at least to me.

I've tried loading arbitrary files with constructions like "#{File.open(" "some_file.bf" ").read}" + + but Ruby seems to helpfully escape the "#" for me so i dont accidentally load the file im trying to load. On the other hand, embedding "#{getc}" works okay for reading from stdin, but there's still the restriction that input is non-interactive - only stuff piped in at the start is read. Anyone know a way around one or more of these input issues?

\$\endgroup\$
1
  • \$\begingroup\$ The way round the first problem is to build a string consisting of a string literal and then ~ it. See my blog post on using this for debugging. \$\endgroup\$ Sep 10 '12 at 12:34
2
\$\begingroup\$

PHP, 208 bytes

<?$a=array_fill(0,3e4,$b=0);$A='$a[$b]';$c=explode('|',"|while($A){|}|echo chr($A);|$A=ord(fgetc(STDIN));|++$A;|--$A;".'|++$b;|--$b;');eval(preg_replace('~.~e','$c[strpos(" [].,+-><","\0")]',`cat $argv[1]`));

Tested with PRIME.BF

php ./bf.php 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\$
2
\$\begingroup\$

Julia, 427 422 bytes

I know the challenge is old, but who cares... My solution feels huge, and I bet it could be a lot shorter.

function g(n::AbstractString) p=open(n);c=readchomp(p);close(p);b="a[k]";e=30000;j="a=zeros(UInt8,$e);k=1;";for i=1:length(c) c[i]=='<'?(j=j*"k-=1;"):c[i]=='>'?(j=j*"k+=1;"):c[i]=='+'?(j=j*"$b+=1;"):c[i]=='-'?(j=j*"$b-=1;"):c[i]=='['?(j=j*"while $b>0 "):c[i]==']'?(j=j*"end;"):c[i]=='.'?(j=j*"print(Char($b));"):c[i]==','?(j=j*"s=chomp(readline(STDIN));s==\"\"?$b=10:$b=s[1];"):nothing;end;println(j);@eval $(parse(j));end

Characters are entered one by one, no buffered input. Just hitting the enter key sends newline (ASCII 10).

Execution of the test case for primes up to 255, on my i5 2410 M laptop takes about 9.5 minutes:

julia> @time bf("primes.bf")
Primes up to: 2
5
5

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 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251
567.207327 seconds (301.29 k allocations: 19.484 MB)

Ungolfed:

function bf(n::AbstractString)
    p=open(n)
    c=readchomp(p)
    close(p)
    b="a[k]"
    U="UInt8(1)"
    e=30000
    j="a=zeros(UInt8,$e);k=1;"
    for i=1:length(c)
        c[i]=='<' ? (j=j*"k-=1;") :
        c[i]=='>' ? (j=j*"k+=1;") :
        c[i]=='+' ? (j=j*"$b+=$U;") :
        c[i]=='-' ? (j=j*"$b-=$U;") :
        c[i]=='[' ? (j=j*"while $b>0 ") :
        c[i]==']' ? (j=j*"end;") :
        c[i]=='.' ? (j=j*"print(Char($b));") :
        c[i]==',' ? (j=j*"s=chomp(readline(STDIN));s==\"\" ? $b=10 :  $b=s[1];") : nothing
    end
    j=parse(j)
    @eval $j
end

The interpreter generates julia code from the bf source and evaluates the code. For the test case, the result would look like this:

a=zeros(UInt8,30000);k=1;k+=1;a[k]+=1;a[k]+=1;a[k]+=1;a[k]+=1;a[k]+=1;a[k]+=1;...........

In a more readable version with newlines instead of semicolons, this results in 1368 SLOC:

a=zeros(UInt8,30000)
k=1
k+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
while a[k]>0
k-=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
k+=1
a[k]-=1
end
...
...
...
while a[k]>0
a[k]-=1
end
k-=1
while a[k]>0
a[k]-=1
end
k-=1
k-=1
a[k]-=1
end
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
a[k]+=1
print(Char(a[k]))
while a[k]>0
a[k]-=1
end
\$\endgroup\$
2
\$\begingroup\$

VB.net, 730 bytes

If P.Aggregate(Of Int32)(0,Function(s,i)If(s<0,s,If(i="["c,s+1,If(i="]"c,s-1,s))))=0 Then Dim C=0,O=0,M(30000)As Int32:Dim J As Func(Of Int32,Int32,Int32,Char,Char,Int32)=Function(x,n,l,g,t)If(P(x)=g,J(x+n,n,l+1,g,t),If(P(x)=t,If(l=1,x,J(x+n,n,l-1,g,t)),J(x+n,n,l,g,t))):Dim Q As New Dictionary(Of Char,Action)From{{"+"c,Sub()M(O)=If(M(O)=255,255,M(O)+ 1)},{"-"c,Sub()M(O)=If(M(O)=0,0,M(O)-1)},{"<"c,Sub()O=If(O=0,M.Length,O-1)},{">"c,Sub()O=If(O=M.Length-1,0,O+1)},{"["c,Sub()C=If(M(O)=0,J(C,+1,0,"["c,"]"c),C)},{"]"c,Sub()C=If(M(O)=0,C,J(C,-1,0,"]"c,"["c))},{","c,Sub()M(O)=Console.Read()},{"."c,Sub()Console.Write(Convert.ToChar(M(O)))}}:For C=0To P.Length-1:Dim a=If(Q.ContainsKey(P(C)),Sub()Q(P(C))(),Sub()Exit Sub):a():Next
\$\endgroup\$
1
  • \$\begingroup\$ The C# version has the potential to be smaller I think. \$\endgroup\$ Dec 11 '13 at 3:31
2
\$\begingroup\$

Cy, 272 270 253 233 232 bytes

This is mind-numbingly slow, but I guess that's what I get for interpreting an inefficent language in an interpreted interpreted language.

Thanks to this answer, Cy is my first language to be proven Turing-complete!

[0 &=d] =C
{$C $d ::} =c
("+" "$C $d ::++" :
"-" "$C $d ::--" :
"<" ".d --" :
">" ".d ++ $C 0 <~" :
"[" "{c 0 >} {" :
"]" "} while" :
"." "c chr :<<" :
"," "$C $d :>c ord ::=" :
"",)=f
"" =m
:>R {=x .m $f $x :: "% " +=} each
$m exec

I have created a monster.

Ungolfed/"readable":

[0] =cells
0 =dp

{ $cells $dp :: } =cell
(
    "+" " $cells $dp ::++ " :
    "-" " $cells $dp ::-- " :
    "<" "
        .dp --
    " :
    ">" "
        .dp ++
        $dp $cells len >< {
            $cells 0 <~
        } if
    " :
    "[" "
        { cell 0 > } {
    " :
    "]" "
        } while
    " :
    "." " cell chr :<< " :
    "," " $cells $dp :>c ord  ::= " :
    "" ,
) =funcs


:>R =code
"" =cmds
$code { =x
    .cmds $funcs $x :: +=
} each
$cmds exec
\$\endgroup\$
2
\$\begingroup\$

C, 194 bytes

s[99999],*p;char*c;k(h){h=*c-h;return h*h<2?h:0;}main(d,i){c=1[p=i];for(p=s;*c;++c){(*p)-=k(44);p+=k(61);*c^46?*c^44?0:(*p=getchar()):putchar(*p);d=k(92);if(*p?~d:d-1)for(i=d;i;i+=k(92))c-=d;}}

Expects the brainfuck program as the first command line argument.

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

PynTree, 123 bytes

Æp+"Dw[0]Dy0"Ƭ+"æ#wy%+1#wy256"-"æ#wy%_#wy1 256"."ƤȮ#wy","æ#wy%OĊ256">";ß+y1æSwy"<"¿yß_y1æIw0 0"["¡#wy¤"]'}}JfxSėx"+-.,[]<>"

Try it online!

Transpiles Brainfuck to PynTree and then calls pyntree_eval on it. PynTree transpiles directly to Python.

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

Powershell, 175 195 183 175 173 bytes, Transpiler

,'$p=0
$c=@{}'+(gc $args|% t*y|%{(-split'$p++
$p--
$c.$p++
$c.$p--
$c.$p=[console]::Read()
write-host([char]$c.$p)-n
for(;$c.$p){
}
#')[('><+-,.[]'|% i*f $_)]
})-join'
'|iex

Explanation:

The script is transpiler from a brainfuck source code to a powershell source code. Finally, the script evaulates the result powershell code by command iex.

  • init commands $p=0 and $c=@{}
  • gc $args|% t*y|%{ - for each character from file
  • ('><+-,.[]'|% i*f $_)+1 - treats a current char as index in the array of code snippets. If character match no code snippet, the script uses the comment char #.
  • and iex evaulates the result powershell code

Compared to Joey's answer, this script fixes a bug "Index operation failed; the array index evaluated to null" ($p=0 in the init block)

Known issues:

  • [console]::Read() eats first char in VSCode. This expression work correct in a powershell window.

Less golfed test script:

$f = {

'$p=0',
'$c=@{}'+
(gc $args|% t*y|%{
    $bfcmd_Idx='><+-,.[]'.IndexOf($_)     # IndexOf returns -1 if char $_ does not found.
    @(  '$p++',
        '$p--',
        '$c.$p++',
        '$c.$p--',
        '$c.$p=[console]::Read()',
        'write-host([char]$c.$p)-n',
        'for(;$c.$p){',
        '}',
        '#'
    )[$bfcmd_Idx]      # push to pipe an element. -1 means last element
})-join"`n"|Invoke-Expression

}

&$f interpret-brainf-hello.bf
&$f interpret-brainf-prime.bf

Output:

Hello World!
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

File interpret-brainf-prime.bf contains a test script from the question.

File interpret-brainf-hello.bf (from wiki):

[ This program prints "Hello World!" and a newline to the screen, its
  length is 106 active command characters. [It is not the shortest.]

  This loop is an "initial comment loop", a simple way of adding a comment
  to a BF program such that you don't have to worry about any command
  characters. Any ".", ",", "+", "-", "<" and ">" characters are simply
  ignored, the "[" and "]" characters just have to be balanced. This
  loop and the commands it contains are ignored because the current cell
  defaults to a value of 0; the 0 value causes this loop to be skipped.
]

++++++++               Set Cell #0 to 8
[
    >++++               Add 4 to Cell #1; this will always set Cell #1 to 4
    [                   as the cell will be cleared by the loop
        >++             Add 2 to Cell #2
        >+++            Add 3 to Cell #3
        >+++            Add 3 to Cell #4
        >+              Add 1 to Cell #5
        <<<<-           Decrement the loop counter in Cell #1
    ]                   Loop till Cell #1 is zero; number of iterations is 4
    >+                  Add 1 to Cell #2
    >+                  Add 1 to Cell #3
    >-                  Subtract 1 from Cell #4
    >>+                 Add 1 to Cell #6
    [<]                 Move back to the first zero cell you find; this will
                        be Cell #1 which was cleared by the previous loop
    <-                  Decrement the loop Counter in Cell #0
]                       Loop till Cell #0 is zero; number of iterations is 8

The result of this is:
Cell No :   0   1   2   3   4   5   6
Contents:   0   0  72 104  88  32   8
Pointer :   ^

>>.                     Cell #2 has value 72 which is 'H'
>---.                   Subtract 3 from Cell #3 to get 101 which is 'e'
+++++++..+++.           Likewise for 'llo' from Cell #3
>>.                     Cell #5 is 32 for the space
<-.                     Subtract 1 from Cell #4 for 87 to give a 'W'
<.                      Cell #3 was set to 'o' from the end of 'Hello'
+++.------.--------.    Cell #3 for 'rl' and 'd'
>>+.                    Add 1 to Cell #5 gives us an exclamation point
>++.                    And finally a newline from Cell #6

Powershell, 257 bytes, Interpreter

$c=@{}
$p=$i=0
$m={for(;($b+=($s[$i]-92)|?{$_-in-1,1})){$i+=$args[0]}}
for($s=gc $args -ra;$i-lt$s.Length){switch($s[$i]-40){22{$p++}20{$p--}3{$c.$p++}5{$c.$p--}4{$c.$p=[console]::Read()}6{write-host([char]$c.$p)-n}51{if(!$c.$p){.$m 1}}53{.$m -1;$i--}}$i++}

Less golfed test script:

$f = {

$c=@{}                                      # $c - hashtable
$p=$i=0                                     # $p - ptr (a key in the hashtable), $i - IC (Instruction Counter)
$m={
    for(;($b+=($s[$i]-92)|?{$_-in-1,1})){   # $b - balance of the brackets
        $i+=$args[0]                        # move IC forward or backward
    }                                       # while balance of the brackets is not 0
}
for($s=gc $args -ra;$i-lt$s.Length){        # -ra is shortcut for -raw parameter = get-content as char array
    switch($s[$i]-40){                      # '-40' needs to convert into [int] and to reduce cases 43 44 45 46 into 3 4 5 6 (-2 bytes)
        22{$p++}
        20{$p--}
        3{$c.$p++}
        5{$c.$p--}
        4{$c.$p=[console]::Read()}          # it eats a first char in a VSCode, it works correct in a Powershell terminal
        6{write-host([char]$c.$p)-n}
        51{if(!$c.$p){.$m 1}}               # dot source the script block m
        53{.$m -1;$i--}                     # dot sourcing does not create a new scope https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scripts
    }
    $i++
}

}

&$f interpret-brainf-hello.bf
&$f interpret-brainf-prime.bf

Output:

Hello World!
Primes up to: 20
2 3 5 7 11 13 17 19
\$\endgroup\$
2
\$\begingroup\$

Javascript - 342 bytes

This is pretty much a complete ripoff of https://codegolf.stackexchange.com/a/220/85546, but I've translated it to Javascript, which was mostly simple except for the converting of character codes, which required some extra lines of code.

d=l=>{i=0,b=new Array(300).fill(0),t="",q=[];r=new Response(l).text().then(q=>(q.split("").forEach(e=>{t+=["i++;","i--;","b[i]++;","b[i]--;","n=new Buffer(1);n[0]=b[i];q.push(n.toString());","b[i]=prompt().charCodeAt(0);","while (b[i]){","}"]["><+-.,[]".indexOf(e)]||"\n",i+=(92-e.charCodeAt(0))*(e.indexOf("][")>-1)});eval(t);return q))}

It reads input from a Blob (l), and returns the output as an array of numbers/strings/whatever. All other input is taken as a prompt, of which only the first character is stripped. As with @Alexandru's submission, it evals the translated code, which is simply mapped one character at a time to corresponding JS.

\$\endgroup\$
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
    Aug 10 '20 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
    Aug 10 '20 at 8:41
  • \$\begingroup\$ Don't need the space between string[] and z \$\endgroup\$
    – ceilingcat
    Aug 10 '20 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\$ Nov 17 '20 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
    Nov 17 '20 at 14:56
  • \$\begingroup\$ Are you at your computer yet? \$\endgroup\$ Nov 20 '20 at 14:00
  • \$\begingroup\$ @pppery sorry, it should be fixed now \$\endgroup\$
    – Aiden4
    Nov 20 '20 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\$

Scala, 459 bytes

I'd love to see other scala solutions!

The golfed version:

@main def a(n:String)={val t=io.Source.fromFile(n).mkString;var r=t;var p=0;var q=0;val b=Array.fill(30000){0};def f(c:Int)={var l=1;p=r.indexWhere(x=>{l+=Map('['->c,']'-> -c).getOrElse(x,0);l==0},p+1);1<0};def a=p=t.size-1-p;while(t.size!=p){t(p)match{case'+'=>b(q)+=1case'-'=>b(q)-=1case'>'=>q+=1case'<'=>q-=1case'['=>r=t;b(q)==0&&f(1)case']'=>r=t.reverse;a;b(q)!= 0&&f(-1);a case'.'=>print((b(q)&255).toChar)case','=>b(q)=Console.in.read()case _=>0};p+=1}}

The ungolfed version:

@main def evalFromFile(fileName: String) =
  val code = io.Source.fromFile(fileName).mkString
  val size = code.size
  var tempCode = code
  var codePtr = 0
  var cellPtr = 0
  val cells = Array.fill(30_000){0}

  def moveLoopPtr(direction: Int) =
    var count = 1;
    codePtr = tempCode.indexWhere(x => {
      count += Map('[' -> direction, ']' -> -direction).getOrElse(x, 0)
      count == 0
    }, codePtr + 1)
    1 > 1

  while (code.size != codePtr) {
    code(codePtr) match
      case '+' => cells(cellPtr) += 1
      case '-' => cells(cellPtr) -= 1
      case '>' => cellPtr += 1
      case '<' => cellPtr -= 1
      case '[' =>
        tempCode = code;
        cells(cellPtr) == 0 && moveLoopPtr(1)
      case ']' =>
        tempCode = code.reverse
        codePtr = code.size - 1 - codePtr
        cells(cellPtr) != 0 && moveLoopPtr(-1)
        codePtr = code.size - 1 - codePtr
      case '.' => print((cells(cellPtr) & 255).toChar)
      case ',' => cells(cellPtr) = Console.in.read()
      case _ => 0
    codePtr += 1
  }
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to Code Golf, nice answer! user uses Scala a lot, you two would probably get along :p \$\endgroup\$ Oct 6 at 17:11
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\$
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\$

From sepp2k solution - 148

eval"a=[i=0]*3e4;"+$<.bytes.map{|b|{?.,"putc a[i]",?,,"a[i]=getc",?[,"while a[i]>0",?],"end",?<,"i-=1",?>,"i+=1",?+,"a[i]+=1",?-,"a[i]-=1"}[b]}*";"

eval"a=[i=0]*3e4;"+$<.bytes.map{ can be replaced with a=[i=0]*3e4;eval$<.bytes.map{ -3 bytes

*";" => *$/ -1 bytes

"while a[i]>0" and"end" => "(" and ")while(a[i]>0)" -1 bytes

And we get 143 (5 bytes less)

a=[i=0]*3e4;eval$<.bytes.map{|b|{?.,"putc a[i]",?,,"a[i]=getc",?[,"(",?],")while a[i]>0",?<,"i-=1",?>,"i+=1",?+,"a[i]+=1",?-,"a[i]-=1"}[b]}*$/

And what if there aren't any comments in input (only +-<>[],.) http://codepad.org/EihHsoJO

we can write like this:

a=[i=0]*3e4;eval$<.bytes.map{|b|%w{putc(a[i]) a[i]=getc ( )while(a[i]>0) i-=1 i+=1 a[i]+=1 a[i]-=1}[".,[]<>+-\n".index b]}*$/

And this is 126 bytes, if there wouldn't be "\n" at the end, we can skip it in this part ".,[]<>+-\n" => ".,[]<>+-" saving 2 bytes

And this can be shorten to:

a=[i=0]*3e4;eval$<.bytes.map{|b|%w{i-=1 ( i+=1 )while(0<a[i]) a[i]+=1 a[i]=getc a[i]-=1 putc(a[i])}[b%30%9]}*$/

which is 112 bytes

where b%30%9 is a mapping from ascii code to array index

How to find this formula?

Very easy:

c="<[>]+,-."
(1..99).each do |i|
    (1..99).each do |j|
        r = c.each_byte.map {|a| a%i%j}.select {|x| x < c.size}.uniq
        puts "#{r} #{i} #{j} " if r.size==c.size
    end
end

>>> 
[0, 1, 2, 3, 4, 5, 6, 7] 30 9  
[4, 5, 6, 7, 0, 1, 2, 3] 43 13  
[4, 3, 6, 5, 7, 0, 1, 2] 44 12  
[0, 7, 2, 1, 3, 4, 5, 6] 52 8  
[0, 7, 2, 1, 3, 4, 5, 6] 60 8

So if only we can assume, that there would be only <>+-[],. whe can shorten the solution to 112 bytes

\$\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\$ Nov 29 '15 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\$

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
    Oct 7 at 21:58
  • \$\begingroup\$ Ahh, meant to do the last one. Thanks for the end=, wouldn't have thought of that. \$\endgroup\$ Oct 8 at 0:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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