Interpret brainf***

114

29

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 

Alexandru

Posted 2011-01-28T01:32:54.707

Reputation: 5 485

1

@Hannesh http://codegolf.stackexchange.com/a/37887/38891 Someone actually did it.

– ASCIIThenANSI – 2015-04-12T03:47:48.087

Is the file anyone we choose or do we get it from the command line or stdin? – Juan – 2011-01-28T03:25:32.913

@Juan: You have to take input to the program you're interpreting on stdin. – Anon. – 2011-01-28T03:53:01.163

162 byte C version: http://j.mearie.org/post/1181041789/brainfuck-interpreter-in-2-lines-of-c

– luser droog – 2015-07-04T05:05:32.973

I'd post the one I made a while ago, but it's over 1000 characters. – The_Basset_Hound – 2015-08-31T22:32:26.550

@Hannesh, https://code.google.com/p/awib/

– SeanC – 2012-09-12T19:14:15.147

3I wonder if there should be two categories: Those programs that use eval (or shell out to compile) -- and those that don't. – MtnViewMark – 2011-02-15T07:52:27.457

Are cells signed or unsigned? – JPvdMerwe – 2011-01-28T11:38:30.323

@JPvdMerwe: I think that depends on the language. For example Python has unsigned bytes, Java signed bytes. – Alexandru – 2011-01-28T12:11:00.647

@Hannesh: http://esolangs.org/wiki/brainfuck#Self-interpreters

– M L – 2016-03-23T23:34:12.300

3What 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? – Martin Ender – 2016-04-01T14:07:31.220

3Likewise, 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? – Martin Ender – 2016-04-01T14:09:45.220

How do you end the primes up to: prompt? What does alt 1 0 do? – Cyoce – 2016-05-03T22:37:00.307

1I'm VTC as unclear because of the issues that Martin brought up. – Mego – 2016-06-30T05:09:00.580

1When you say bad commands are not part of the input, you mean that all programs will behave in the given guidelines? Or is validation on where the memory pointer is and what values are in memory needed? Also, is there a limit to the input file size? – Juan – 2011-01-29T02:54:43.097

34I'd love to see someone answer this in brainfuck. – Hannesh – 2011-03-14T19:15:06.693

@Juan: 1. Yes, all programs behave in the given guidelines. 2. No limit on input file size, but it will fit in ram with plenty of extra space for your internal data structures. – Alexandru – 2011-01-29T16:44:27.003

@SeanCheshire But that is a compiler, not an interpreter. – Justin – 2014-01-15T22:38:41.027

Is integer overflow an error or is it defined to wrap around? I mean if we don't have access to 8-bit integers do we have to use modulo on it, or is anything ok as long as it works as expected for integers that never exceed the 8-bit range? – sepp2k – 2011-01-30T15:14:03.480

My suggestion is not to bother with error checking. In my implementation cells are unsigned 8-bit and wrap around (b[i]=(b[i]+1)&255). – Alexandru – 2011-01-30T15:26:40.600

2Another question: Why the unusual comment syntax? Usually everything that isn't ,.-+[]<> is a comment in brainfuck. (I'm asking because it makes my implementation quite a bit longer than it needs to be) – sepp2k – 2011-01-30T15:33:14.703

1@Alexandru: My point about the behaviour being defined was that if you say "overflow is undefined", then just using normal integers (i.e. removing the &255 part in your solution) would still leave the solution valid (which I kinda prefer, since it's another way to lose a couple of chars). – sepp2k – 2011-01-30T15:36:17.710

How the array must be initialized ? with which value ? – BenjaminB – 2011-06-15T17:16:53.827

5

You should clarify about 1) size of memory 2) is memory circled 4) maybe any other details

– Nakilon – 2011-01-28T01:37:22.180

@sepp2k: good one. – Alexandru – 2011-01-28T01:44:19.960

Answers

46

Perl, 120 138

%c=qw(> $p++ < $p-- + D++ - D-- [ while(D){ ] } . print+chrD , D=ord(getc));
$/=$,;$_=<>;s/./$c{$&};/g;s[D]'$b[$p]'g;eval

This runs hello.bf and primes.bf flawlessly:

$ perl bf.pl hello.bf
Hello World!
$ perl bf.pl 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

Initialization: The opcode to Perl translation table is stored in %c. The readable form looks like this:

%c=(
  '>' => '$p++',
  '<' => '$p--',
  '+' => '$b[$p]++',
  '-' => '$b[$p]--',
  '[' => 'while($b[$p]){',
  ']' => '}',
  '.' => 'print chr$b[$p]',
  ',' => '$b[$p]=ord(getc)',
);

Step 1: Slurp program input to $_ and transform it to Perl code using the translation table. Comments are automatically stripped (replaced with undef) in this step.

Step 2: Uncompress all $b[$p] occurrences

Step 3: Launch the program using eval.

J B

Posted 2011-01-28T01:32:54.707

Reputation: 9 638

@JB hey, I accidentally pressed down vote on your answer and it is locked in, can you edit this so I can reverse the down Vote? – Teoc – 2015-09-09T00:38:13.640

Just use Perl's qw syntax to define %c directly -- good for 7 fewer chars (you'll have to say print+chr$b[$p] and ord(getc), though) – mob – 2012-09-11T23:36:49.693

I count 18 saved… thanks! (updating in a minute) – J B – 2012-09-12T08:19:48.110

1@olivecoder What on earth are you talking about? – J B – 2012-09-19T07:12:56.157

The %c table is declared and defined in the first line; its characters are perfectly accounted for. – J B – 2012-09-19T13:46:32.543

69

Python (no eval), 317 bytes

from sys import*
def f(u,c,k):
 while(c[1]>=k)*u:
  j,u='[]<>+-,.'.find(u[0]),u[1:];b=(j>=0)*(1-j%2*2);c[1]+=b*(j<2)
  while b*c[c[0]]and j<1:f(u,c,k+1);c[1]+=1
  b*=c[1]==k;c[[0,c[0],2][j/2-1]]+=b
  if(j==6)*b:c[c[0]]=ord(stdin.read(1))
  if(j>6)*b:stdout.write(chr(c[c[0]]))
f(open(argv[1]).read(),[-1]+[0]*30003,0)

boothby

Posted 2011-01-28T01:32:54.707

Reputation: 9 038

71+1 for the f(u,c,k) – Joel Cornett – 2012-08-04T21:48:15.227

-1 byte if you replace while b*c[c[0]]and j<1 with while b*c[c[0]]*(j<1) – Daniil Tutubalin – 2019-06-24T07:58:52.283

10That is one beautiful piece of noise, sir – globby – 2014-12-06T01:44:52.417

50

16 bit 8086 machine code: 168 bytes

Here's the base64 encoded version, convert and save as 'bf.com' and run from Windows command prompt: 'bf progname'

gMYQUoDGEFKzgI1XAgIfiEcBtD3NIR8HcmOL2LQ/i88z0s0hcleL2DPA86sz/zP2/sU783NHrL0I
AGgyAU14DTqGmAF194qOoAH/4UfDJv4Fwyb+DcO0AiaKFc0hw7QBzSGqT8MmODV1+jPtO/NzDaw8
W3UBRTxddfJNee/DJjg1dPoz7U509YpE/zxddQFFPFt18U157sM+PCstLixbXUxjTlJWXmV+

EDIT

Here's some assembler (A86 style) to create the executable (I had to reverse engineer this as I'd misplaced the original source!)

    add dh,10h                              
    push dx                                 
    add dh,10h                              
    push dx                                 
    mov bl,80h                              
    lea dx,[bx+2]                         
    add bl,[bx]                            
    mov [bx+1],al                         
    mov ah,3dh                              
    int 21h                                 
    pop ds                                 
    pop es                                 
    jb ret                               
    mov bx,ax                              
    mov ah,3fh                              
    mov cx,di                              
    xor dx,dx                              
    int 21h                                 
    jb ret                               
    mov bx,ax                              
    xor ax,ax                              
    repz stosw                                     
    xor di,di                              
    xor si,si                              
    inc ch                                 
program_loop:
    cmp si,bx                              
    jnb ret                               
    lodsb                                    
    mov bp,8                            
    push program_loop
symbol_search:                       
    dec bp                                 
    js ret
    cmp al,[bp+symbols]
    jnz symbol_search
    mov cl,[bp+instructions]
    jmp cx                                 
forward:
    inc di                                 
    ret                                    
increment:
    inc b es:[di]                      
    ret                                    
decrement:
    dec b es:[di]                      
    ret                                    
output:
    mov ah,2                              
    mov dl,es:[di]                            
    int 21h                                 
    ret                                    
input:
    mov ah,1                              
    int 21h                                 
    stosb                                    
backward:
    dec di                                 
    ret                                    
jumpforwardifzero:
    cmp es:[di],dh                            
    jnz ret                               
    xor bp,bp
l1: cmp si,bx                              
    jnb ret
    lodsb                                    
    cmp al,'['                              
    jnz l2
    inc bp
l2: cmp al,']'                              
    jnz l1
    dec bp                                 
    jns l1
    ret                                    
jumpbackwardifnotzero:
    cmp es:[di],dh                            
    jz  ret
    xor bp,bp
l3: dec si                                 
    jz  ret
    mov al,[si-1]                         
    cmp al,']'
    jnz l4
    inc bp  
l4: cmp al,'['                              
    jnz l3
    dec bp                                 
    jns l3
    ret                                    
symbols:
    db '><+-.,[]'
instructions:
    db forward and 255
    db backward and 255
    db increment and 255
    db decrement and 255
    db output and 255
    db input and 255
    db jumpforwardifzero and 255
    db jumpbackwardifnotzero and 255

Skizz

Posted 2011-01-28T01:32:54.707

Reputation: 2 225

I've added a source code version of the program. I've just noticed that non-bf characters cause the program to exit rather than be ignored. Easy to fix that and I'll leave it as an exercise for people to do that themselves. – Skizz – 2012-08-14T13:18:15.960

I remember I got the Linux ELF version 166 bytes, 10 years ago, here http://www.muppetlabs.com/~breadbox/software/tiny/

– Emmanuel – 2014-07-28T17:34:54.110

44

brainfuck, 843 691 bytes

Edit: decided to revisit this and found a surprising number of ways to golf off bytes

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

This takes input in the form code!input where the !input is optional. It also simulates negative cells without using negative cells itself and can store up to (30000-(length of code+6))/2 cells.

Try it online!

Jo King

Posted 2011-01-28T01:32:54.707

Reputation: 38 234

Just to make sure I got this right, if I ran this program with this program I could nest it 5 levels deep and still handling code-inputs of length 262. – Draco18s no longer trusts SE – 2019-10-01T21:46:07.457

@Draco18s I suspect you'd run out the 30000 cells before that, since the size of each nested interpreter increases exponentially. I think you'd get 2, maybe 3 levels deep – Jo King – 2019-10-01T23:03:02.613

Even 3 deep would be hilariously silly. – Draco18s no longer trusts SE – 2019-10-02T02:34:01.277

27

Ruby 1.8.7, 188 185 149 147 characters

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]}*";"

Somewhat readable version:

code = "a = [0] * 3e4; i = 0;"
more_code ARGF.bytes.map {|b|
  replacements = {
    ?. => "putc a[i]",
    ?, => "a[i] = getc",
    ?[ => "while a[i] > 0 do",
    ?] => "end",
    ?< => "i -= 1",
    ?> => "i += 1",
    ?+ =>"a[i]+=1",
    ?- =>"a[i]-=1"
  }
  replacements[b]
}.join(";")
eval code+more_code

As you see I shamelessly stole your idea of translating to the host language and then using eval to run it.

sepp2k

Posted 2011-01-28T01:32:54.707

Reputation: 1 679

You can shave off a byte byte comparing to zero >0 rather than testing equality: !=0. The specs say unsigned, and overflow is undefined. – anonymous coward – 2011-02-06T05:32:50.353

3e4 will also work as opposed to 30000 – anonymous coward – 2011-02-06T05:36:59.913

@Charlie: Thanks. Though to be fair it didn't say "unsigned" when I wrote the code. I honestly didn't know that you could write 3e4 though. That's a very good point and good to know. – sepp2k – 2011-02-06T05:40:36.103

If you use an array instead of a hash, you can get it down to 134 bytes: eval"a=[i=0]*3e4;"+$>.bytes.map{|b|%w[i-=1 end i+=1 a[i]+=1 a[i]=getc a[i]-=1 putc(a[i]) while(a[i]>0)][7&b%60]if',.+-[]<>'[b.chr]}*?;. If you take the bytes of <]>+,-.[ and compute 7&b%60, miraculously you get 01234567. Without comments (other characters), this could be 115 bytes... – blutorange – 2015-05-13T12:26:53.633

File.read($*.pop).bytes -> $<.bytes should work too – Arnaud Le Blanc – 2011-02-12T22:31:43.273

@user: After you read from $<, gets won't work anymore (as gets reads from $< too). – sepp2k – 2011-02-12T22:36:23.763

@Ventero: Have you tested it with brainfuck code that reads input? – sepp2k – 2011-02-14T15:56:31.480

1Ruby 1.8.7 has an even shorter syntax to build a literal hash: {?a,"foo"}, which is equivalent to {?a=>"foo"}. And testing here shows that you actually can replace File.read($*.pop).bytes with $< without any problems. Also inlining everything to something like eval"a[0]..."+$<.bytes.map{?.,"putc a[i]",...}*";" shortens the solution by another few characters. – Ventero – 2011-02-14T15:58:59.730

@sepp2k: I tested it with the example file supplied in the question. echo "10" | ruby1.8 bf.rb prime.bf works without any problems. – Ventero – 2011-02-14T16:02:13.613

@Ventero: Ok, now it works for me too. Could have sworn it didn't before. Thanks. – sepp2k – 2011-02-14T16:07:55.870

I get a "bf.rb:1: unterminated string meets end of file" error when I try it :( – J B – 2011-02-14T20:30:32.520

@JB: Sorry, I somehow missed the last " when copy and pasting from the file. Fixed now. – sepp2k – 2011-02-15T03:04:01.560

a=[0]3e4;i=0; can be converted to a=[i=0]3e4; to save another 2 chars – user163365 – 2011-03-24T22:49:57.577

@ChaosR: Good catch, thanks. – sepp2k – 2011-03-24T23:03:03.403

26

Binary Lambda Calculus 112

The program shown in the hex dump below

00000000  44 51 a1 01 84 55 d5 02  b7 70 30 22 ff 32 f0 00  |DQ...U...p0".2..|
00000010  bf f9 85 7f 5e e1 6f 95  7f 7d ee c0 e5 54 68 00  |....^.o..}...Th.|
00000020  58 55 fd fb e0 45 57 fd  eb fb f0 b6 f0 2f d6 07  |XU...EW....../..|
00000030  e1 6f 73 d7 f1 14 bc c0  0b ff 2e 1f a1 6f 66 17  |.os..........of.|
00000040  e8 5b ef 2f cf ff 13 ff  e1 ca 34 20 0a c8 d0 0b  |.[./......4 ....|
00000050  99 ee 1f e5 ff 7f 5a 6a  1f ff 0f ff 87 9d 04 d0  |......Zj........|
00000060  ab 00 05 db 23 40 b7 3b  28 cc c0 b0 6c 0e 74 10  |....#@.;(...l.t.|
00000070

expects its input to consist of a Brainfuck program (looking only at bits 0,1,4 to distinguish among ,-.+<>][ ) followed by a ], followed by the input for the Brainfuck program.

Save the above hex dump with xxd -r > bf.Blc

Grab a blc interpreter from https://tromp.github.io/cl/cl.html

cc -O2 -DM=0x100000 -m32 -std=c99 uni.c -o uni
echo -n "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.]" > hw.bf
cat bf.Blc hw.bf | ./uni

Hello World!

John Tromp

Posted 2011-01-28T01:32:54.707

Reputation: 957

So this wouldn't work with commented brainfuck programs? – kamoroso94 – 2018-02-15T20:05:59.140

No, not without stripping out the comments first. – John Tromp – 2018-02-16T22:27:46.497

1

Why does this even exist? Apparently, it even exists in the realm of research. O.o

– Isiah Meadows – 2014-12-04T04:11:49.003

18

Retina 0.8.2, 386 391 386 bytes

Code contains unprintable NUL (0x00) characters. It's also not super golfed yet, because it's already really slow, and if I golf it more, I don't know how long it'd take to finish. Appears to time out on the prime-finding sample.

There may be bugs in the online interpreter or in my program (leading new lines don't show in the output?).

Takes input like <code>│<input>. No, that is not a pipe (|). It's the Unicode character U+2502. The code also uses the Unicode characters ÿ▶◀├║. Unicode characters are used in order to support input of all ASCII characters. Therefore, these characters need to be separated from the code by a non-ASCII character.

Try it online

s`^.*
▶$0├║▶
s{`(▶>.*║.*)▶(.)(.?)
$1$2▶$3
▶$
▶
║▶
║▶
(▶<.*║.*)(.)▶
$1▶$2
T`ÿ-`o`(?<=▶\+.*║.*▶).
^\+

T`-ÿ`ÿo`(?<=▶-.*║.*▶).
^-

(▶\..*├.*)(║.*▶)(.)
$1$3$2$3
(▶,.*│)(.?)(.*├.*▶).
$1$3$2
▶\[(.*║.*▶)
[▶▶${1}
{`(▶▶+)([^[\]]*)\[
$2[$1▶
}`▶(▶+)([^[\]]*)\]
$2]$1
r`([[\]]*)▶\](.*║.*▶[^])
$1◀◀]$2
r{`\[([^[\]]*)(◀+)◀
$2[$1
}`\]([^[\]]*)(◀◀+)
$2◀]$1
◀
▶
}`▶([^│])(.*║)
$1▶$2
s\`.*├|║.*

Note there is a trailing newline there.

Brief Explanation:

Zeros 0x00 are used for the tape, which is infinite. The first replacement sets up the interpreter in the form ▶<code>│<input>├<output>║▶<tape>, where the first is the pointer for the code, and the second one is the pointer for the tape.

ÿ is 0xFF (255), which is used for Transliteration (used to implement + and -) to wrap the cells back around to zero.

is only used for readability (in case the program is stopped in the middle or you want to see the program mid-execution). Otherwise, you couldn't tell which way the pointer was moving.

Commented Code:

s`^.*                       # Initialize
▶$0├║▶
s{`(▶>.*║.*)▶(.)(.?)        # >
$1$2▶$3
▶$
▶
║▶                          # <
║▶
(▶<.*║.*)(.)▶
$1▶$2
T`ÿ-`o`(?<=▶\+.*║.*▶).      # +
^\+

T`-ÿ`ÿo`(?<=▶-.*║.*▶).      # -
^-

(▶\..*├.*)(║.*▶)(.)         # .
$1$3$2$3
(▶,.*│)(.?)(.*├.*▶).        # ,
$1$3$2
▶\[(.*║.*▶)                 # [
[▶▶${1}
{`(▶▶+)([^[\]]*)\[
$2[$1▶
}`▶(▶+)([^[\]]*)\]
$2]$1
r`([[\]]*)▶\](.*║.*▶[^])    # ]
$1◀◀]$2
r{`\[([^[\]]*)(◀+)◀
$2[$1
}`\]([^[\]]*)(◀◀+)
$2◀]$1
◀
▶
}`▶([^│])(.*║)              # next instruction
$1▶$2
s\`.*├|║.*                  # print output

Click here for the code with zeros in place of null bytes. Any occurrences of $0 should not be replaced with nulls.

Edit: Now supports empty input and suppresses trailing newline.

Infinite output is now supported. (403 bytes)

mbomb007

Posted 2011-01-28T01:32:54.707

Reputation: 21 944

I kind of wish that I'd placed the <code> and the <tape> next to each other (though it'd be more characters) so that transitioning to an SMBF interpreter would be easier, if I ever decide to do that. – mbomb007 – 2016-07-20T16:43:48.733

14

TI-BASIC, 264 bytes

Because of limitations in TI-BASIC, this actually doesn't qualify for this challenge since it breaks rule 2; the calculators' RAM is very limited, and doing something like 30000->dim(L1 (I use L1 for the stack/array) will force it to throw an ERR:MEMORY. As such, the stack/array starts at a size of 1 and grows if the pointer is pointing to an element past the end of it. It also breaks rule 3, because it's already breaking rule 2 so I may as well not bother with a cell-size limit.

Could probably still be golfed, by the way... I've made one or two edits to that end since first submitting, but if the version below doesn't work then head back to the edit from May 6 '15 and use that code instead. Also, as there's really no ASCII in TI-BASIC, this takes numbers of any size (and anything that returns a number, like a variable or expression) as input, and outputs numbers in turn.

Use SourceCoder to build it into a .8xp file then send it to your calculator with TI-Connect or TILP or something, and run it by including your brainfuck program in double quotes followed by a colon and whatever you named the TI-BASIC program. For instance, if you named it BRAINF, you'd run a program like this: "brainfuck goes here":prgmBRAINF. If you have a shell on your calc that intercepts other commands when it detects the prgm token, though, do this: "brainfuck goes here" -> press ENTER -> prgmBRAINF.

seq(inString("<>-+.,[]",sub(Ans,S,1)),S,1,length(Ans->L2
cumSum((Ans=7)-(Ans=8->L3
seq(Ans(X),X,dim(Ans),1,~1->L4
1->P:DelVar L11->dim(L1 //this is the same as DelVar L1:1->dim(L1 as DelVar does not require a colon or newline after its argument
For(S,1,dim(L2
L2(S->T
P-(T=1)+(T=2->P
dim(L1
Ans+(P-Ans)(P>Ans->dim(L1
L1(P)-(T=3)+(T=4->L1(P
If T=5
Disp Ans
If T=6:Then
Input V
V->L1(P
End
If T=7 and not(L1(P
S+2+sum(not(cumSum(L3(S)-1=seq(L3(X),X,S+1,dim(L3->S
1-S+dim(L3
If T=8 and L1(P
S-sum(not(cumSum(L4(Ans)=seq(L4(X),X,Ans+1,dim(L4->S
End

If you don't have a way of connecting your calculator to your computer and want to type this out on-calc instead (I can't imagine why you'd want to, but I digress) note that -> is the STO> button above the ON key, ~ is the negative symbol next to ENTER, and to replace all instances of L<number> with the corresponding list token found on 2ND -> <number on keypad>

Thanks to thomas-kwa (at least, I think that's his Stack username) for helping me optimize this, especially with the [ and ] instructions.

M. I. Wright

Posted 2011-01-28T01:32:54.707

Reputation: 849

1Do you need the parens around Ans+S? – Zacharý – 2017-07-07T13:16:07.880

@Zacharý Good catch, no. I must have been unsure about how PEMDAS works or something... I'll refrain from editing, however, because it's been so long that it definitely isn't worth it to bump this post up to the front and because a two-byte reduction isn't going to give the answer any sort of advantage over the others lol. – M. I. Wright – 2017-08-06T23:23:19.453

1I remember like 2-3 years ago when I used this program to interpret Brainf*** on my calculator. And, it's an interpret brainf*** question, I think it should be at the top to be honest. – Zacharý – 2017-08-06T23:42:01.360

1Actually, I think that whole line could be S-sum(not(cumSum(L4(Ans)=seq(L4(X),X,Ans+1,dim(L4->S. (a-a=0). And hey, don't worry about forgetting ONE order of operation thing here, I've seen a whole host of people forget order of operations for % (mod) on a challenge. – Zacharý – 2017-08-06T23:46:52.853

1Oh dang, yeah. Okay, that gives at least 10 bytes off since the if can be made a one-liner as well, plus some other things... may as well edit, then. You've made me whip my calculator out for the first time in like a year to check this stuff, haha – M. I. Wright – 2017-08-07T00:12:04.243

13

Python 275 248 255

I decided to give it a try.

import sys
i=0
b=[0]*30000
t=''
for e in open(sys.argv[1]).read():
 t+=' '*i+['i+=1','i-=1','b[i]+=1','b[i]-=1','sys.stdout.write(chr(b[i]))','b[i]=ord(sys.stdin.read(1))','while b[i]:','pass','']['><+-.,['.find(e)]+'\n'
 i+=(92-ord(e))*(e in'][')
exec t 

Alexandru

Posted 2011-01-28T01:32:54.707

Reputation: 5 485

1You may strip 1 char, "import sys as s" and replace "sys" to "s" in the rest – YOU – 2011-02-06T06:52:25.737

I wrote a 227 character version of this in python myself, and there are a few tricks you could use to shorten your code. Rather than storing the number of indents in i, and incrementing/decrementing i, you can store the indent itself, which takes exactly as many characters to update (i=i[e==']':]+' '[e!='[':]), and saves you from doing i*' ', and lets you do i=t=''. Rather than storing '' as the last item in the array, you can keep pass as the last one, which translates any non-operation into pass, which works fine. Everything else I did has been suggested already. – Strigoides – 2012-10-20T05:42:52.673

7I'd +1, but many improvements have been suggested and not implemented. – mbomb007 – 2016-11-15T17:01:46.213

Note that this is actually 247 chars. (See the nasty space after exec t?).
If you use S.Mark's tip and also make the whole for cycle into one line, you can shrink this to 243 chars.

– Oleh Prypin – 2011-04-04T15:18:35.860

12Neat, you are generating python source code using brainfuck. – None – 2011-01-30T02:00:23.757

This fails on any input containing [], a valid though trivial bf program. I've suggested an edit which fixes this, but increases the character count. To further reduce the character count, you can from sys import *, and use 'i+=1,...'.split(',') instead of ['i+=1',...]. – boothby – 2011-07-05T20:19:34.877

13

Haskell, 457 413 characters

import IO
import System
z=return
'>'#(c,(l,d:r))=z(d,(c:l,r))
'<'#(d,(c:l,r))=z(c,(l,d:r))
'+'#(c,m)=z(succ c,m)
'-'#(c,m)=z(pred c,m)
'.'#t@(c,_)=putChar c>>hFlush stdout>>z t
','#(_,m)=getChar>>=(\c->z(c,m))
_#t=z t
_%t@('\0',_)=z t
i%t=i t>>=(i%)
b('[':r)=k$b r
b(']':r)=(z,r)
b(c:r)=f(c#)$b r
b[]=(z,[])
f j(i,r)=(\t->j t>>=i,r)
k(i,r)=f(i%)$b r
main=getArgs>>=readFile.head>>=($('\0',("",repeat '\0'))).fst.b

This code "compiles" the BF program into an IO action of the form State -> IO State the state is a zipper on an infinite string.

Sad that I had to expend 29 characters to turn buffering off. Without those, it works, but you don't see the prompts before you have to type input. The compiler itself (b, f, and k) is just 99 characters, the runtime (# and %) is 216. The driver w/initial state another 32.

>ghc -O3 --make BF.hs 
[1 of 1] Compiling Main             ( BF.hs, BF.o )
Linking BF ...

>./BF HELLO.BF 
Hello World!

>./BF 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 

update 2011-02-15: Incorporated J B's suggestions, did a little renaming, and tightened up main

MtnViewMark

Posted 2011-01-28T01:32:54.707

Reputation: 4 779

1You should be able to get the buffering from just IO, and the arguments from just System (-19). The buffering issue bothers me as well, as the spec doesn't really mention it and the top-voted answer doesn't even do I/O. If you must keep it, it's probably shorter to hFlush after each write than change the global buffering mode (-34+15). – J B – 2011-02-15T10:49:57.290

11

Conveyor, 953

This might be the most beautiful code you will ever see:

0

:I\1\@p
>#====)
^#====<
PP0
P<=======================<
00t:)01t1  a:P:P:P:P:P:P:^
>===========">">2>">2>">"^
^           +^-^5^ ^5^]^.^
^           "^"^*^"^*^"^"^
^           -^-^6^-^6^-^-^
^           #^#^*^#^*^#^#^
^           P P -^P )^P P
^           P P #^P )^P P
^t1\)t0:))t01   P   -^  1
^===========<   P   #^  0
^  t1\(t0:))t01     P   t
^=============<     P   )
^         t11(t01   0 0 )
^===============<. t P 10
^                 FT#T#=<
^=================< P 
^             t11)t01 
^===================< 10t))0tP00t:(01t(1a:P:
^                     >=====#=>==========">"
^                             ^          ]^[
^                           P ^          "^"
^===========================<=^#=====<   -^-
                            ^==<     ^ PP#^#=
                                     ^===PTPT<
                                     ^  )P P
                                     ^=<=< (
                                       ^===<

Loovjo

Posted 2011-01-28T01:32:54.707

Reputation: 7 357

8Could you add an explanation and a link to an implementation? I want to understand the beauty. ;) – DLosc – 2015-05-12T22:47:20.667

1

Well, I'm currently developing it, there is a compiler and a very bad explanation at https://github.com/loovjo/Conveyor. The source is pretty readable if you want to understand it.

– Loovjo – 2015-05-13T08:30:07.823

9

C 284 362 (From a file)

#include <stdio.h>
char b[30000],z[9999],*p=b,c,*a,i;f(char*r,int s){while(c=*a++){if(!s){(c-62)?(c-60)?(c-43)?(c-45)?(c-46)?(c-44)?0:(*p=getchar()):putchar(*p):--*p:++*p:--p:++p;if(c==91)f(a,!*p);else if(c==93){if(!*p)return;else a=r;}}else{if(c==93){--s;if(!*p&&!s)return;}else if(c==91){s++;}}}}main(int c,char**v){fread(z,1,9999,fopen(*++v,"r"));a=z;f(0,0);}

Primes:

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
Press any key to continue . . .

Compiled and ran successfully VS2008

Original solution failed to recognize loops that were initially set to zero. Still some room to golf. But finally solves the Prime Number program.

Ungolfed:

#include <stdio.h>
char b[30000],z[9999],*p=b,c,*a,i;
f(char*r,int s)
{
    while(c=*a++)
    {   
        if(!s)
        {
            (c-62)?(c-60)?(c-43)?(c-45)?(c-46)?(c-44)?0:(*p=getchar()):putchar(*p):--*p:++*p:--p:++p;
            if(c==91)f(a,!*p);
            else if(c==93){if(!*p)return;else a=r;}
        }
        else
        {
            if(c==93)
            {
                --s;
                if(!*p&&!s)return;
            }
            else if(c==91)
            {
                s++;
            }
        }
    }
}

main(int c,char**v){
    fread(z,1,9999,fopen(*++v,"r"));
    a=z;
    f(0,0);
}

Tests:

Hello World

Rot13

snmcdonald

Posted 2011-01-28T01:32:54.707

Reputation: 641

I fail to see how the program code is read from a file, as well as how input is performed. – J B – 2011-02-14T20:07:35.917

@JB The initial question did not specify from a file. This reads from stdin. Also note that the current PHP and Python are read from argv. – snmcdonald – 2011-02-14T23:36:11.503

@dark_charlie: nice improvement!!! reducing all the ifs with a single define! – snmcdonald – 2011-02-14T23:38:48.907

@snmcdonald Indeed I didn't get here in time to see the initial question. But the current PHP and Python do read from a file. – J B – 2011-02-14T23:43:43.290

Hate to be a kill-joy, but did any of the up-voters notice that this code doesn't work? Even ignoring that it doesn't read the BF program from a file -- it doesn't implement the , operation correctly at all. – MtnViewMark – 2011-02-16T03:03:40.910

@MtnViewMark: As noted the original solution was geared to the original post which did not specify that it was read from a file. I am not certain why it did not compile for you. My solutions all compiled and ran successfully. Perhaps I am using undefined behavior (http://meta.codegolf.stackexchange.com/questions/21/c-c-golfing-should-undefined-behaviour-be-allowed).

– snmcdonald – 2011-02-17T02:34:11.070

@snmcdonald: It did compile, and run, but try executing PRIME.BF: You'll notice that your code doesn't implement the comma (,) operation (which reads from standard input). BF programs are interactive and process input. -- As for reading the program, 999 is way too short: PRIME.BF is >4k, and many BF programs are even larger. Finally, the original post was corrected within 10min of posting. – MtnViewMark – 2011-02-17T03:53:12.000

@MtnViewMark: I have updated the comma operator. I made this a community wiki due to the feedback I was receiving. Please feel free to improve upon this question. – snmcdonald – 2011-02-17T05:26:30.280

@snmcdonald - comma needs to read from stdin, probably via getchar(). – MtnViewMark – 2011-02-18T01:45:43.327

Are you checking the same pointer (l) every time you loop? I think you are supposed to check the current location of the head (p). – Alexandru – 2011-01-30T19:51:11.510

I pass the pointer to the buffer and the pointer to the stream. It checks at the end of the loop to see if the pointer l in the buffer has reached zero and breaks else it resets the stream back to the original loop [. This is necessary for nested [ loops. – snmcdonald – 2011-01-30T20:00:41.527

1Yeah. I thought so. You should not check the value at pointer at first enter in the loop, but the value at the current pointer. Check the test in the question. Your program hangs. – Alexandru – 2011-01-30T20:10:50.263

@Alexandru +1: Good point. I have corrected my solution. – snmcdonald – 2011-01-30T20:19:46.580

1You can replace break;else by return;. – Alexandru – 2011-01-30T20:56:36.930

3I think you can replace (c==62)?a:b with (c-62)?b:a. – Alexandru – 2011-01-30T22:01:59.587

9

PHP 5.4, 296 294 273 263 261 209 191 183 178 166 characters:

I gave it a shot without using eval, but I eventually had to use it

<?$b=0;eval(strtr(`cat $argv[1]`,["]"=>'}',"["=>'while($$b){',"."=>'echo chr($$b);',","=>'$$b=fgetc(STDIN);',"+"=>'$$b++;',"-"=>'$$b--;',">"=>'$b++;',"<"=>'$b--;']));

All commands are working. This heavily abuses variable variables, and spews warnings. However, if one changes their php.ini to squelch warnings (or pipes stderr to /dev/null), this works great.

Verification (It's the "Hello World!" example from Wikipedia): http://codepad.viper-7.com/O9lYjl

Ungolfed, 367 365 335 296 267 characters:

<?php
$a[] = $b = 0;
$p = implode("",file($argv[1])); // Shorter than file_get_contents by one char
$m = array("]" => '}', "[" => 'while($a[$b]){',"." => 'echo chr($a[$b]);', "," => '$a[$b]=fgetc(STDIN);', "+" => '$a[$b]++;', "-" => '$a[$b]--;', ">" => '$b++;', "<" => '$b--;');
$p = strtr($p,$m);
@eval($p);

This should be run via the command line: php bf.php hello.bf

Kevin Brown

Posted 2011-01-28T01:32:54.707

Reputation: 5 756

8

C, 333 characters

This is my first BF interpreter and the first golf I actually had to debug.

This runs the prime number generator on Mac OS X/GCC, but an additional #include<string.h> may be necessary at a cost of 19 more characters if the implicit definition of strchr doesn't happen to work on another platform. Also, it assumes O_RDONLY == 0. Aside from that, leaving int out of the declaration of M saves 3 characters but that doesn't seem to be C99 compliant. Same with the third * in b().

This depends on the particulars of ASCII encoding. The Brainfuck operators are all complementary pairs separated by a distance of 2 in the ASCII code space. Each function in this program implements a pair of operators.

#include<unistd.h>
char C[30000],*c=C,o,P[9000],*p=P,*S[9999],**s=S,*O="=,-\\",*t;
m(){c+=o;}
i(){*c-=o;}
w(){o<0?*c=getchar():putchar(*c);}
b(){if(o>0)*c?p=*s:*--s;else if(*c)*++s=p;else while(*p++!=93)*p==91&&b();}
int(*M[])()={m,i,w,b};
main(int N,char**V){
read(open(V[1],0),P,9e3);
while(o=*p++)
if(t=strchr(O,++o&~2))
o-=*t+1,
M[t-O]();
}

Potatoswatter

Posted 2011-01-28T01:32:54.707

Reputation: 181

I think you can shrink it more by using the 'e' notation for all the big numbers. – luser droog – 2011-08-16T04:34:38.810

@luser: I was initially surprised too, but the language and compiler won't allow that. I did manage to shrink another 4 chars with tweaks, and using a #define instead of the function table would also probably be terser. I just like the number 333 and the table :v) . – Potatoswatter – 2011-08-16T05:56:33.653

Oh, right. I really should've known that. E-notation is in the production for a floating-point constant, whereas a declaration requires an integer. BTW, this may be cheating, but check out http://nieko.net/projects/brainfuck for Urban Müller's version. The biggest gain appears to be heavy use of ||.

– luser droog – 2011-08-16T06:10:09.293

8

CJam, 75 bytes

lq3e4Vc*@{"-<[],.+>"#"T1$T=(t T(:T; { _T=}g \0+(@T@t _T=o "_'(')er+S/=}%s~@

Try it online: string reverser, Hello World.

Explanation

Takes code on the first line of STDIN and input on all lines below it.

l            Read a line from STDIN (the program) and push it.
 q           Read the rest of STDIN (the input) and push it.
  3e4Vc*     Push a list of 30000 '\0' characters.
        @    Rotate the stack so the program is on top.

{               }%   Apply this to each character in prog:
 "-<[],.+>"#         Map '-' to 0, '<' to 1, ... and everything else to -1.
            ...=     Push a magical list and index from it.

s~       Concatenate the results and evaluate the resulting string as CJam code.
  @      Rotate the top three elements again -- but there are only two, so the
         program terminates.

What about that magical list?

"T1$T=(t T(:T; { _T=}g \0+(@T@t _T=o "  Space-separated CJam snippets.
                                        (Note the final space! We want an empty
                                        string at the end of the list.)
_'(')er+                                Duplicate, change (s to )s, append.
        S/                              Split over spaces.

The resulting list is as follows:

T1$T=(t    (-)
T(:T;      (<)
{          ([)
_T=}g      (])
\0+(@T@t   (,)
_T=o       (.)
T1$T=)t    (+)
T):T;      (>)
{          (unused)
_T=}g      (unused)
\0+(@T@t   (unused)
_T=o       (unused)
           (all other characters)

We generate the snippets for + and > from those for - and <, simply by changing left parens (CJam’s “decrement”) into right parens (CJam’s “increment”).

Lynn

Posted 2011-01-28T01:32:54.707

Reputation: 55 648

Shortest answer & biggest winner – Jack Giffin – 2018-05-15T00:32:19.487

8

Windows PowerShell, 204

'$c=,0*3e4;'+@{62='$i++
';60='$i--
';43='$c[$i]++
';45='$c[$i]--
';44='$c[$i]=+[console]::ReadKey().keychar
';46='write-host -n([char]$c[$i])
';91='for(;$c[$i]){';93='}'}[[int[]][char[]]"$(gc $args)"]|iex

Fairly straightforward conversion of the instructions and then Invoke-Expression.

History:

  • 2011-02-13 22:24 (220) First attempt.
  • 2011-02-13 22:25 (218) 3e4 is shorter than 30000.
  • 2011-02-13 22:28 (216) Unnecessary line breaks. Matching on integers instead of characters is shorter.
  • 2011-02-13 22:34 (207) Used indexes into a hash table instead of the switch.
  • 2011-02-13 22:40 (205) Better cast to string removes two parentheses.
  • 2011-02-13 22:42 (204) No need for a space after the argument to Write-Host.

Joey

Posted 2011-01-28T01:32:54.707

Reputation: 12 260

7

Delphi, 397 382 378 371 366 364 328 characters

Eat this Delphi!

328 var p,d:PByte;f:File;z:Word=30000;x:Int8;begin p:=AllocMem(z+z);d:=p+z;Assign(F,ParamStr(1));Reset(F,1);BlockRead(F,p^,z);repeat z:=1;x:=p^;case x-43of 1:Read(PChar(d)^);3:Write(Char(d^));0,2:d^:=d^+44-x;17,19:d:=d+x-61;48,50:if(d^=0)=(x=91)then repeat p:=p+92-x;z:=z+Ord(p^=x)-Ord(p^=x xor 6);until z=0;end;Inc(p)until x=0;end.

Here the same code, indented and commented :

var
  d,p:PByte;
  x:Int8;
  f:File;
  z:Word=30000;
begin
  // Allocate 30000 bytes for the program and the same amount for the data :
  p:=AllocMem(z+z);
  d:=p+z;
  // Read the file (which path must be specified on the command line) :
  Assign(F,ParamStr(1));
  Reset(F,1);
  BlockRead(F,p^,z);
  // Handle all input, terminating at #0 (better than the spec requires) :
  repeat
    // Prevent a begin+end block by preparing beforehand (values are only usable in '[' and ']' cases) :
    z:=1;                       // Start stack at 1
    x:=p^;                      // Starting at '[' or ']'
    // Choose a handler for this token (the offset saves 1 character in later use) :
    case x-43of
      1:Read(PChar(d)^);        // ','     : Read 1 character from input into data-pointer
      3:Write(Char(d^));        // '.'     : Write 1 character from data-pointer to output
      0,2:d^:=d^+44-x;          // '+','-' : Increase or decrease data
      17,19:d:=d+x-61;          // '<','>' : Increase or decrease data pointer
      48,50:                    // '[',']' : Start or end program block, the most complex part :
        if(d^=0)=(x=91)then     // When (data = 0 and forward), or when (data <> 0 and backward)
        repeat                  //
          p:=p+92-x;            // Step program 1 byte back or forward
          z:=z+Ord(p^=x)        // Increase stack counter when at another bracket
              -Ord(p^=x xor 6); // Decrease stack counter when at the mirror char
        until z=0;              // Stop when stack reaches 0
    end;
    Inc(p)
  until x=0;
end.

This one took me a few hours, as it's not the kind of code I normally write, but enjoy!

Note : The prime test works, but doesn't stop at 100, because it reads #13 (CR) before #10 (LF)... do other submissions suffer this problem too when running on CRLF OSes?

PatrickvL

Posted 2011-01-28T01:32:54.707

Reputation: 641

Wow! I never would have expected to trump C in terseness with Delphi! Not until you apply my ideas to C I guess ;-) – PatrickvL – 2011-03-12T16:30:56.423

7

C, 260 + 23 = 283 bytes

I created a C program which can be found here.

main(int a,char*s[]){int b[atoi(s[2])],*z=b,p;char*c=s[1],v,w;while(p=1,
*c){q('>',++z)q('<',--z)q('+',++*z)q('-',--*z)q('.',putchar(*z))q(',',*z
=getchar())if(*c=='['||*c==']'){v=*c,w=184-v;if(v<w?*z==0:*z!=0)while(p)
v<w?c++:c--,p+=*c==v?1:*c==w?-1:0;}c++;}}

Has to be compiled via gcc -D"q(a,b)"="*c-a||(b);" -o pmmbf pmmbf.c and can be called as follows: pmmbf ",[.-]" 30000 whereby the first argument (quoted) contains the bf-program to run, the second determines how large the tape should be.

phimuemue

Posted 2011-01-28T01:32:54.707

Reputation: 71

1I think that you need to add 23 characters to your count for the -D"q(a,b)"="*c-a||(b);" option, since that seems (to my limited understanding, at least) to be helping you shrink your code. – Gareth – 2011-08-05T09:23:17.927

The option is included in the posted text. The reason for it is to avoid the lengthy word define and newline, but I don't think that's really kosher. Anyway with the quotes, comment, and gcc -D I don't see the advantage at all. – Potatoswatter – 2011-08-06T03:30:35.033

7

F#: 489 chars

The following program doesn't jump at '[' / ']' instructions, but scans the source code for the next matching token. This of course makes it kind of slow, but it can still find the primes under 100. F# integer types don't overflow but wrap.

Here's the short version:

[<EntryPoint>]
let M a=
 let A,B,i,p,w=Array.create 30000 0uy,[|yield!System.IO.File.ReadAllText a.[0]|],ref 0,ref 0,char>>printf"%c"
 let rec g n c f a b=if c then f i;if B.[!i]=a then g(n+1)c f a b elif B.[!i]=b then(if n>0 then g(n-1)c f a b)else g n c f a b
 while !i<B.Length do(let x=A.[!p]in match B.[!i]with|'>'->incr p|'<'->decr p|'+'->A.[!p]<-x+1uy|'-'->A.[!p]<-x-1uy|'.'->w x|','->A.[!p]<-byte<|stdin.Read()|'['->g 0(x=0uy)incr '['']'|']'->g 0(x>0uy)decr ']''['|_->());incr i
 0

A nasty gotcha was that the primes.bf program chokes on windows newlines. In order to run it I had to save the input number to a UNIX formatted text document and feed it to the program with a pipe:

interpret.exe prime.bf < number.txt

Edit: entering Alt+010 followed by Enter also works in Windows cmd.exe

Here's the longer version:

[<EntryPoint>]
let Main args =
    let memory = Array.create 30000 0uy
    let source = [| yield! System.IO.File.ReadAllText args.[0] |]
    let memoryPointer = ref 0
    let sourcePointer = ref 0
    let outputByte b = printf "%c" (char b)
    let rec scan numBraces mustScan adjustFunc pushToken popToken =
        if mustScan then
            adjustFunc sourcePointer
            if source.[!sourcePointer] = pushToken then
                scan (numBraces + 1) mustScan adjustFunc pushToken popToken
            elif source.[!sourcePointer] = popToken then
                if numBraces > 0 then scan (numBraces - 1) mustScan adjustFunc pushToken popToken
            else
                scan numBraces mustScan adjustFunc pushToken popToken 

    while !sourcePointer < source.Length do
        let currentValue = memory.[!memoryPointer]
        match source.[!sourcePointer] with
            | '>' -> incr memoryPointer
            | '<' -> decr memoryPointer
            | '+' -> memory.[!memoryPointer] <- currentValue + 1uy
            | '-' -> memory.[!memoryPointer] <- currentValue - 1uy
            | '.' -> outputByte currentValue
            | ',' -> memory.[!memoryPointer] <- byte <| stdin.Read()
            | '[' -> scan 0 (currentValue = 0uy) incr '[' ']'
            | ']' -> scan 0 (currentValue > 0uy) decr ']' '['
            |  _  -> ()
        incr sourcePointer
    0 

cfern

Posted 2011-01-28T01:32:54.707

Reputation: 311

I solved the Enter issue by not pressing it but Ctrl+J :-) – Joey – 2011-02-14T08:11:09.617

Ctrl+J didn't work for me, but entering Alt+010 followed by Enter did. – cfern – 2011-02-14T09:28:14.063

5

Python 2, 223

I admit that I recycled an old program of mine (but had to change it quite a bit, because the old version didn't have input, but error checking...).

P="";i,a=0,[0]*30000
import os,sys
for c in open(sys.argv[1]).read():x="><+-.[,]".find(c);P+=" "*i+"i+=1 i-=1 a[i]+=1 a[i]-=1 os.write(1,chr(a[i])) while+a[i]: a[i]=ord(os.read(0,1)) 0".split()[x]+"\n";i+=(x>4)*(6-x)
exec P

Runs the primes calculator fine.

I see now that Alexandru has an answer that has some similarities. I'll post mny answer anyways, because I think there are some new ideas in it.

Reinstate Monica

Posted 2011-01-28T01:32:54.707

Reputation: 929

5

C (gcc) Linux x86_64, 884 621 525 487 439 383 358 352 bytes

*z,*mmap();d[7500];(*p)();*j(a,g)char*a;{char*t=a,*n,c,q=0;for(;read(g,&c,!q);t=c==47?n=j(t+9,g),z=mempcpy(t,L"\xf003e80Ƅ",5),*z=n-t-9,n:c==49?q=*t++=233,z=t,*z=a-13-t,z+1:stpcpy(t,c-18?c-16?~c?c-1?c-2?c?"":"1\xc0P_\xF\5":"RXR_\xF\5":L"໾":L"۾":L"컿":L"웿"))c-=44;return t;}main(P,g)int**g;{p=mmap(0,1<<20,6,34,0,0);p(*j(p,open(g[1],0))=195,d,1);}

Try it online!

This is a JIT that compiles BF code into x86_64 machine language at runtime. This performs a straight translation so commonly occurring sequences such as >>>, <<<, +++ and --- aren't coalesced into faster instructions.

Less golfed version:

// size of data area
*z,c,*mmap();d[7500];(*p)();
// recursive function translates BF commands to x86_64 instructions
*j(a,g)char*a;{
  char*t=a,*n,q=0;
  for(;read(g,&c,!q);)
    c-=44,
    t=c==47? // [
        // cmpb $0x0,(%rsi)
        // je n-t-9
        n=j(t+9,g),
        z=mempcpy(t,L"\xf003e80Ƅ",5)
        *z=n-t-9,
        n
      :
        c==49? // ]
          // jmp a-13-t
          q=*t++=233,
          z=t,
          *z=a-13-t,
          z+1
        :
          stpcpy(t,c-18? // >
                     c-16? // <
                       ~c? // +
                         c-1? // -
                           c-2? // .
                             c? // ,
                               ""
                             :
                               // xor %eax,%eax
                               // push %rax
                               // pop %rdi
                               // syscall
                               "1\xc0P_\xF\5"
                           :
                             // push %rdx
                             // pop %rax
                             // push %rdx
                             // pop %rdi
                             // syscall
                             "RXR_\xF\5"
                         :
                           // decb (%rsi)
                           L"໾"
                       :
                         // incb (%rsi)
                         L"۾"
                     :
                       // dec %esi
                       L"컿"
                   :
                     // inc %esi
                     L"웿");
  return t;
}
main(P,g)int**g;{
  // allocate text (executable) memory and mark as executable
  p=mmap(0,1<<20,6,34,0,0);
  // run JIT, set %rdx=1 and call code like a function
  p(*j(p,open(g[1],0))=195,d,1);
}

ceilingcat

Posted 2011-01-28T01:32:54.707

Reputation: 5 503

5

C, 267

#define J break;case
char*p,a[40000],*q=a;w(n){for(;*q-93;q++){if(n)switch(*q){J'>':++p;J'<':--p;J'+':++*p;J'-':--*p;J'.':putchar(*p);J',':*p=getchar();}if(*q==91){char*r=*p&&n?q-1:0;q++;w(r);q=r?r:q;}}}main(int n,char**v){p=a+read(open(v[1],0),a,9999);*p++=93;w(1);}

Run as ./a.out primes.bf

Ungolfed Version:

#define J break;case

char*p,a[40000],*q=a; // packed so program immediately followed by data

w(n){
    for(;*q-93;q++){ // until ']'
        if(n)switch(*q){ // n = flagged whether loop evaluate or skip(0)
                J'>':++p;
                J'<':--p;
                J'+':++*p;
                J'-':--*p;
                J'.':putchar(*p);
                J',':*p=getchar();
        }
        if(*q==91){char*r=*p&&n?q-1:0;q++;w(r);q=r?r:q;} // recurse on '[', record loop start
    }
}

main(int n,char**v){
    p=a+read(open(v[1],0),a,9999);
    *p++=93; // mark EOF with extra ']' and set data pointer to next
    w(1); // begin as a loop evaluate
}

baby-rabbit

Posted 2011-01-28T01:32:54.707

Reputation: 1 623

4

Lua, 285

loadstring("m,p={0},1 "..io.open(arg[1]):read"*a":gsub("[^.,<>[%]+-]",""):gsub(".",{["."]="io.write(string.char(@)) ",[","]="@=io.read(1):byte() ",["<"]="p=p-1 ",[">"]="p=p+1 @=@or 0 ",["["]="while @~=0 do ",["]"]="end ",["+"]="@=(@+1)%256 ",["-"]="@=(@-1)%256 "}):gsub("@","m[p]"))()

Somewhat readable version:

loadstring( --execute
    "m,p={0},1 ".. --initialize memory and pointer
    io.open(arg[1]) --open file
        :read"*a" --read all
            :gsub("[^.,<>[%]+-]","") --strip non-brainfuck
                :gsub(".", --for each character left
                    {["."]="io.write(string.char(@)) ", -- '@' is shortcut for 'm[p]', see below
                    [","]="@=io.read(1):byte() ",
                    ["<"]="p=p-1 ",
                    [">"]="p=p+1 @=@or 0 ", --if a before unexplored memory cell, set to 0
                    ["["]="while @~=0 do ",
                    ["]"]="end ",
                    ["+"]="@=(@+1)%256 ", --i like it overflowing
                    ["-"]="@=(@-1)%256 "
                    }
                )
                    :gsub("@","m[p]") --replace the '@' shortcut
    ) --loadstring returns a function
() --call it

Works perfectly

Lua, 478, w/o loadstring

local m,p,i,r,c={0},1,1,{},io.open(arg[1]):read"*a"while i<=#c do(({[43]=function()m[p]=(m[p]+1)%256 end,[45]=function()m[p]=(m[p]-1)%256 end,[62]=function()p=p+1 m[p]=m[p]or 0 end,[60]=function()p=p-1 end,[46]=function()io.write(string.char(m[p]))end,[44]=function()m[p]=io.read(1):byte()end,[91]=function()if m[p]==0 then i=select(2,c:find("%b[]",i))else r[#r+1]=i end end,[93]=function()if m[p]==0 then r[#r]=nil else i=r[#r] end end})[c:byte(i)]or function()end)()i=i+1 end

Readable version:

local m,   p, i, r,  c= --memory, pointer, brackets stack, code
      {0}, 1, 1, {}, io.open(arg[1]) --open file
              :read"*a" --read it
while i<=#c do --while there's code
    (
        (
            {
                [43]=function() -- +
                    m[p]=(m[p]+1)%256
                end,
                [45]=function() -- -
                    m[p]=(m[p]-1)%256
                end,
                [62]=function() -- >
                    p=p+1 m[p]=m[p]or 0 --if new memory cell, set it to 0
                end,
                [60]=function() -- <
                    p=p-1
                end,
                [46]=function() -- .
                    io.write(string.char(m[p]))
                end,
                [44]=function() -- ,
                    m[p]=io.read(1):byte()
                end,
                [91]=function() -- [
                    if m[p]==0 then
                        i=select(2,c:find("%b[]",i)) --find matching ]
                    else
                        r[#r+1]=i --push position to the stack
                    end
                end,
                [93]=function() -- ]
                    if m[p]==0 then
                        r[#r]=nil --pop from stack
                    else
                        i=r[#r] --go to position on the top of stack
                    end
                end
            }
        )[c:byte(i)] --transform character into code
        or function()end --do nothing on non-brainfuck
    )() --run the resulting function
    i=i+1 --go to the next opcode
end

mniip

Posted 2011-01-28T01:32:54.707

Reputation: 9 396

4

Brainfuck, 948 bytes

Well, that took a while. I golfed a Brainfuck self-interpreter by ... not me.

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

MD XF

Posted 2011-01-28T01:32:54.707

Reputation: 11 605

4

C, 374 368

Reads from a file. Passes PRIME.BF test.

Usage: ./a.out PRIME.BF

#include <stdio.h>
main(int c,char**v){int m[30000],s[99],p=0,i=0,n=0;char l[9999],d;FILE*f=fopen(v[1],"r");for(l[i]=0;i<9999&&l[i]!=EOF;l[i]=getc(f))i++;for(i=1;d=l[i];i++){if(!n){p+=d-62?0:1;p-=d-60?0:1;m[p]+=d-43?0:1;m[p]-=d-45?0:1;if(d==46)putchar(m[p]);if(d==44){m[p]=getchar();}if(d==93){i=s[c]-1;c--;n++;}}if(d==91){if(m[p]){c++;s[c]=i;}else{n++;}}n-=d-93?0:1;}}


Reformatted:

#include <stdio.h>
main(int c,char**v){
    int m[3000],s[99],p=0,i=0,n=0;
    char l[9999],d;
    FILE*f=fopen(v[1],"r");
    for(l[i]=0;i<9999&&l[i]!=EOF;l[i]=getc(f))i++;
    for(i=1;d=l[i];i++){
        if(!n){ // > < + - . , ] \n [ ]
            p+=d-62?0:1;
            p-=d-60?0:1;
            m[p]+=d-43?0:1;
            m[p]-=d-45?0:1;
            if(d==46)putchar(m[p]);
            if(d==44){m[p]=getchar();}
            if(d==93){i=s[c]-1;c--;n++;}
        }
        if(d==91){if(m[p]){c++;s[c]=i;}else{n++;}}
        n-=d-93?0:1;
    }
}

jtjacques

Posted 2011-01-28T01:32:54.707

Reputation: 1 055

3000 vs 30000. Your buffer is too small. The program size is too small also. – Alexandru – 2011-01-31T12:54:26.503

I made a typo, fixed. What do you mean by program size? If you mean max file size, you didn't specify a minimum it should handle. – jtjacques – 2011-01-31T15:27:42.653

4

Recall, 594 bytes

In short: Recall has no arithmetic operators in a classic sense, it only has bitwise operations. You can not just "add one" etc. Recall is also strictly stack-based.

DC505M22022M32032M606M42042M707M92092M4405022o032o06o042o07o092o044o1305022o06o042o092o52052q.q2305022o06o07o93093q.q5403206o07o14014q.q6403206o042o07o24024q.q74Yx34034z03MMMMMMMM034o3yY030401r3.4.101zyY040301r4.3.101zY01052gZ02Z040301052023s4.3.10zyY01023gZ02z030401023052s3.4.10zyY01093gZ02q20zyY01054gZ02u20zyY01014gZx20zyY01064gZ02X0zyY01024gZ03304302r33.43.20zyY01074gZ04303302r43.33.20zyyQ6205.8Y06208g6206208iZ08M808013izy062U7205.9Y07209g7207209iz09M909013izy072R53.63.82063MMMMMMMM053o63082013i53082KKKKKKKK82053063082S84.94.12.73.83t012073083TY083073012r83.73.12012084gzY012094gZt0zyy

Example 1: Print something

Input:

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

Output:

PPCG rocks!

Example 2: Output square numbers up to 100

Input:

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

Output:

0
1
4
9
16
25
36
49
64
81
100

This example might take a few minuted to execute and might cause a "this tab is frozen" message. Ignore that and wait.

mınxomaτ

Posted 2011-01-28T01:32:54.707

Reputation: 7 398

4Your website domain has expired. Also, this answer is non-competing, because the language is newer than the challenge. – mbomb007 – 2016-03-23T20:27:51.887

3

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.

theB

Posted 2011-01-28T01:32:54.707

Reputation: 171

1@mbomb007 - Updated. Completely forgot I even did this one. (Didn't even realize anyone even read these old questions) – theB – 2015-08-31T21:18:10.237

Not only do people still read them, they still answer and golf them. – mbomb007 – 2016-11-15T17:08:27.543

3

C (gcc), 273 268 bytes

main(_,a){_=fopen("w.c","w");fputs("main(){char a[30000],*p=a;",_);x:a=getchar();fputs(a-62?a-60?a-43?a-45?a-46?a-44?a-91?a-93?~a?"":"}":"}":"while(*p){":"*p=getchar();":"putchar(*p);":"--*p;":"++*p;":"--p;":"++p;",_);if(~a)goto x;fclose(_);system("cc w.c;./a.out");};

Try it online!

-5 thanks to ceilingcat

Takes input from stdin.

This relies a little bit on the environment, but is pretty consistent. This is effectively the eval solution for c. It writes an appropriate C program to the file w.c, compiles it, and runs it as the desired executable. Thus as a bonus effect this actually compiles the bf code and leaves a.out as a binary for it. Note that depending on the system you may need to modify the last string. In particular most windows c compilers call the default executable "a.exe". Luckily as far as I can tell, they all have the same length so the bytecount is the same. (though if you don't have a cc defined you may need to add a letter such as gcc to the compile command, adding 1 byte).

I am aware that this thread is a bit old, but I didn't see this style of C solution yet, so I thought I'd add it.

LambdaBeta

Posted 2011-01-28T01:32:54.707

Reputation: 2 499

259 bytes – ceilingcat – 2019-08-04T16:37:42.847

3

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.

bltxd

Posted 2011-01-28T01:32:54.707

Reputation: 191

3

Python 3 (no eval), 288 bytes

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

from sys import*
f=[];u=open(argv[1]).read();c=[0]*8**5;k=i=0
while i<len(u):
 j='+-><[],.'.find(u[i]);g=j>3;i+=1;d=c[1]+9
 if c[2]<=k:
  z=c[d]and j==4;f+=z*[i-1];k=c[2]+z;g=1
  if j==5:*f,i=f
  if j==6:c[d]=ord(stdin.read(1))
  if j>6:stdout.write(chr(c[d]))
 c[j%8>>1or d]+=(1-j%2*2)*g

Try it online!

How it works

  • u - Brainf*** code to interpret
  • i - instruction pointer
  • c - memory (32768 cells)
  • f - stack to store return addresses
  • k - depth at which execution is allowed
  • j - current command (-1 to 7)
  • g - flag: is memory update required
  • d - shortcut for data pointer
  • z - flag: should loop be executed or skipped

User memory is c[9:].

c[0:9] range is reserved for internal use:

  • c[1] - data pointer.
  • c[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).
  • c[3] - trash cell, it increases on . and decreses on , and comments, but its value is never used.

Daniil Tutubalin

Posted 2011-01-28T01:32:54.707

Reputation: 547

Welcome to Code Golf! – Stephen – 2019-06-20T00:39:52.123

@Stephen thank you! I really appreciate you welcome comment, because at the moment I can communicate in my own answers only ;) – Daniil Tutubalin – 2019-06-20T11:10:22.047

2

16-bit x86 assembler code, 104 bytes

Assembles with YASM. It wants the file piped from stdin, though.

;compliant version, non-commands are ignored, but 104 bytes long

[bits 16]  
[org 0x100]  
; assume bp=091e used  
; assume di=fffe  
; assume si=0100  
; assume dx=cs (see here)  
; assume cx=00ff  
; assume bx=0000  
; assume ax=0000 used (ah)  
; assume sp=fffe  
start:
        mov al, code_nothing - start  
code_start:
        mov ch, 0x7f ; allow bigger programs  
        mov bx, cx  
        mov di, cx  
        rep stosb  
        mov bp, find_right + start - code_start ;cache loop head for smaller compiled programs  
        jmp code_start_end  
find_right:
        pop si  
        dec si  
        dec si ;point to loop head  
        cmp [bx], cl  
        jne loop_right_end  
loop_right:
        lodsb  
        cmp al, 0xD5 ; the "bp" part of "call bp" (because 0xFF is not unique, watch for additional '[')  
        jne loop_left  
        inc cx  
loop_left:
        cmp al, 0xC3 ; ret (watch for ']')  
        jne loop_right  
        loop loop_right ;all brackets matched when cx==0  
        db 0x3c ;cmp al, xx (mask push)  
loop_right_end:
        push si  
        lodsw ; skip "call" or dummy "dec" instruction, depending on context  
        push si  
code_sqright:
        ret  
code_dec:
        dec byte [bx]  
code_start_end:
        db '$' ;end DOS string, also "and al, xx"  
code_inc:
        inc byte [bx]  
        db '$'  
code_right:
        inc bx ;al -> 2  
code_nothing:
        db '$'  
code_left:
        dec bx  
        db '$'  
code_sqleft:
        call bp  
        db '$'  
; create lookup table  
real_start:
        inc byte [bx+''] ;point to code_right  
        mov byte [bx+'['], code_sqleft - start  
        mov byte [bx+']'], code_sqright - start  
        lea sp, [bx+45+2] ;'+' + 4 (2b='+', 2c=',', 2d='-', 2e='.')  
        push (code_dec - start) + (code_dot - start) * 256  
        push (code_inc - start) + (code_comma - start) * 256  
pre_write:
        mov ah, code_start >> 8  
        xchg dx, ax  
; write  
        mov ah, 9  
        int 0x21  
; read  
code_comma:
        mov dl, 0xff  
        db 0x3d ; cmp ax, xxxx (mask mov)  
code_dot:
        mov dl, [bx]  
        mov ah, 6  
        int 0x21  
        mov [bx], al  
        db '$'  
        db 0xff ; parameter for '$', doubles as test for zero  
; switch  
        xlatb  
        jne pre_write  
  ; next two lines can also be removed  
  ; if the program ends with extra ']'  
  ; and then we are at 100 bytes... :-)  
the_end:
        mov dl, 0xC3  
        int 0x21  
        int 0x20 

peter ferrie

Posted 2011-01-28T01:32:54.707

Reputation: 804

What is 104 bytes? Compiled machine code? I don't think so, boilerplate in programs are huge. – user202729 – 2017-11-26T02:05:33.850

Or the compiled function size? – user202729 – 2017-11-26T02:06:53.043

the assembled code is 104 bytes long. It will compile and run any supplied bf code. – peter ferrie – 2017-11-26T02:34:09.117

2

Gol><>, 111 bytes

/2ds2e111`!a0im*aF+:ZB|0L.
^9R~`;r"0RXf2"WL0p|m0.
^8R~`P
^7R~"~iE0"
^6R~`M
^5R~":o"
^4R~`{
^3R~`}
^~~`W
^~`|
^~

Try Hello World online! or Try String Reverser online!

How it works

The first row is the main loop.

/2ds2e111`!a0im*aF+:ZB|0L.

 2ds2e111`!a0               Push [2,29,2,14,1,1,1,33,10,0]
                            (the differences of all valid chars)
             im*            Take input and negate it
                aF... |     Repeat 10 times...
                  +:ZB      Add, and break if the sum is 0
                       0L.  Jump to another row based on loop count

Other rows share the structure:

^xR~...

 xR~     Discard unneeded numbers x times
    ...  Push relevant code
^        Return to the main loop

Newline is the delimiter between code and input.

^9R~`;r"0RXf2"WL0p|m0.

    `;r"0RXf2"          Add "2fXR0" to the start and ";" to the end
                        "2fXR0" pushes 2**15 zeros to the stack
                        ";" finishes the program
              W...|     While there is some code on the stack...
               L0p      Write the code on the row 0
                   m0.  Jump to row 0

Other lines are for command translation.

^8R~`P      "+" => "P"    Increment
^7R~"~iE0"  "," => "~iE0" Erase current cell, take input and
                          change to 0 if EOF
^6R~`M      "-" => "M"    Decrement
^5R~":o"    "." => ":o"   Duplicate current cell and print
^4R~`{      "<" => "{"    Rotate to the left
^3R~`}      ">" => "}"    Rotate to the right
^~~`W       "[" => "W"    While (non-popping)
^~`|        "]" => "|"    End while
^~       Others => ""     Ignore

Inlining the switch-case turned out to be a nightmare (simply because there is no explicit if...else structure in Gol><>), so I used an index-jump method instead.

Bubbler

Posted 2011-01-28T01:32:54.707

Reputation: 16 616

2

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 

Arnaud Le Blanc

Posted 2011-01-28T01:32:54.707

Reputation: 2 286

2

[EDIT]

C++11, 355, reads from file:

#include<functional>
#include<stdio.h>
main(){
char b[30000],g[9999],*f=g,*p=b,n[]="+-,.><[]",j;
std::function<void()>m[]={
[&p]{(*p)++;},
[&p]{(*p)--;},
[&p]{*p=getchar();},
[&p]{putchar(*p);},
[&p]{p++;},
[&p]{p--;},
[&p,&f]{if(!(*p))while(*f-93)f++;},
[&f,&m]{while(*f-91)f--;m[6]();}
};
fread(g,1,9999,fopen(a[1],0));
for(;*f;f++)for(j=0;n[j];j++)if(n[j]==*f)m[j]();
}

Test

http://ideone.com/b7vO4

[OLD VERSION]

C++11, 391, to see running: http://ideone.com/yZHVv

#include<functional>
#include<stdio.h>
main(int c,char **a) {
  char b[30000],g[9999],*f=g,*r=f,*p=b;
  std::function<void()>m[256];
  m['>']=[&p]{p++;};  
  m['<']=[&p]{p--;};
  m['+']=[&p]{(*p)++;};
  m['-']=[&p]{(*p)--;};
  m['.']=[p]{putchar(*p);};
  m[',']=[&p]{*p=getchar();};
  m['[']=[p,&r,&f]{*p?r=f-1:r=0;};
  m[']']=[&r,&f]{r?f=r:r=f;};
  fread(g,1,9999,fopen(a[1],"r"));
  while (c=*(f++))if(m[c]&&(r||c==']'))m[c]();
}

olivecoder

Posted 2011-01-28T01:32:54.707

Reputation: 307

2

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

M L

Posted 2011-01-28T01:32:54.707

Reputation: 2 865

1

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]].

aka.nice

Posted 2011-01-28T01:32:54.707

Reputation: 411

1

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.

Fors

Posted 2011-01-28T01:32:54.707

Reputation: 3 020

1

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

12Me21

Posted 2011-01-28T01:32:54.707

Reputation: 6 110

1

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

Adam Speight

Posted 2011-01-28T01:32:54.707

Reputation: 1 234

The C# version has the potential to be smaller I think. – Adam Speight – 2013-12-11T03:31:32.077

1

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.

HyperNeutrino

Posted 2011-01-28T01:32:54.707

Reputation: 26 575

1

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

mazzy

Posted 2011-01-28T01:32:54.707

Reputation: 4 832

1

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.

Pâris Douady

Posted 2011-01-28T01:32:54.707

Reputation: 101

1

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)

Tuomas Laakkonen

Posted 2011-01-28T01:32:54.707

Reputation: 341

1I'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. – Paŭlo Ebermann – 2015-11-29T10:15:12.330

1

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(''))
"""

Isiah Meadows

Posted 2011-01-28T01:32:54.707

Reputation: 1 546

1

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

applicative_functor

Posted 2011-01-28T01:32:54.707

Reputation: 111

1

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

Cyoce

Posted 2011-01-28T01:32:54.707

Reputation: 2 690

1

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.

orlp

Posted 2011-01-28T01:32:54.707

Reputation: 37 067

174 bytes – ceilingcat – 2019-09-23T06:02:43.733

1

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?

roobs

Posted 2011-01-28T01:32:54.707

Reputation: 299

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.

– Peter Taylor – 2012-09-10T12:34:54.133

0

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.

jpjacobs

Posted 2011-01-28T01:32:54.707

Reputation: 3 440

0

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.

Geza Kerecsenyi

Posted 2011-01-28T01:32:54.707

Reputation: 1 892

0

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
     ]+";"
  })
)

Billy Moon

Posted 2011-01-28T01:32:54.707

Reputation: 101

0

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.)

Conor O'Brien

Posted 2011-01-28T01:32:54.707

Reputation: 36 228

Is this still accurate? – Addison Crump – 2016-02-28T01:29:53.950

@VoteToClose No, I have not yet implemented some of the commands found in this program. – Conor O'Brien – 2016-02-28T01:31:45.043

1‪:c crosses fingers for Simplex implementation – Addison Crump – 2016-02-28T01:43:47.377