解释脑力***


113

用您最喜欢的语言编写最短的程序,以解释一个脑力激荡的程序。该程序是从文件中读取的。输入和输出是标准输入和标准输出。

  1. 信元大小:8位无符号。溢出是不确定的。
  2. 数组大小:30000字节(未圈出)
  3. 错误的命令不是输入的一部分
  4. 注释以#开头并扩展到行尾注释不是所有内容+-.,[]<>
  5. 没有EOF符号

这里可以找到一个很好的测试。它读取一个数字,然后打印质数直到该数字。为防止链接腐烂,下面是代码的副本:

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========

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

示例运行:

$ 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 

5
您应该澄清一下1)内存的大小2)内存是否被圈出4)也许还有其他详细信息
Nakilon 2011年

3
我想知道是否应该分为两类:使用eval(或shell进行编译)的程序和不使用eval的程序。
MtnViewMark

34
我希望看到有人用脑袋回答这个问题。
汉尼斯2011年

3
“没有EOF符号”是什么意思?尝试,EOF 时,单元格值保持不变吗?还是由我们决定在尝试,EOF 时选择一个值?还是EOF完全未定义的行为?
Martin Ender

3
同样,当有人尝试将30k单元留在任一侧时会发生什么?磁带头应该保留在原处还是不确定的行为?
Martin Ender

Answers:


46

Perl,120138

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

这可以完美地运行hello.bf和primes.bf:

$ 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

初始化:Perl转换表的操作码存储在中%c。可读形式如下:

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

步骤1:$_使用转换表将程序输入的内容吸入并转换为Perl代码。undef在此步骤中,注释将自动删除(替换为)。

步骤2:解压缩所有$b[$p]事件

步骤3:使用启动程序eval


只要使用Perl的qw语法定义%c直接-好为7个更少字符(你必须说print+chr$b[$p]ord(getc),虽然)
暴徒

我算了18张救了……谢谢!(一分钟内更新)
JB 2012年

1
@olivecoder您到底在说什么?
JB 2012年

%c表在第一行中声明和定义;其字符是完美说明。
JB 2012年

@JB嘿,我不小心按下了您的答案,它已被锁定,您可以编辑此内容,以便我撤消否决吗?
环己醇。

67

Python(无eval),317字节

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)

70
+1f(u,c,k)
乔尔·科内特

9
先生,那是一片美丽的声音
globby 2014年

如果替换while b*c[c[0]]and j<1为-1字节while b*c[c[0]]*(j<1)
Daniil Tutubalin

50

16位8086机器代码:168个字节

这是base64编码的版本,转换并另存为'bf.com',然后从Windows命令提示符运行:'bf progname'

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

编辑

这是一些汇编程序(A86风格)来创建可执行文件(由于我放错了原始源代码,所以我不得不对其进行反向工程!)

    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

我已经添加了程序的源代码版本。我刚刚注意到,非bf字符会导致程序退出而不是被忽略。易于解决,我将其保留为人们自己做的练习。
Skizz 2012年

我记得10年前获得了Linux ELF版本166字节,在这里muppetlabs.com/~breadbox/software/tiny
Emmanuel

39

brainfuck843个 691字节

编辑:决定重新审视此问题,并发现了令人惊讶的多种方式来击球字节

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

这需要输入的形式code!input,其中!input是可选的。它还可以模拟负性细胞,而无需使用负性细胞本身,并且可以存储最多的(30000-(length of code+6))/2细胞。

在线尝试!


为了确保我做对了,如果我使用该程序运行该程序,则可以将其嵌套5个级别,并且仍然处理长度为262的代码输入
。– Draco18s

@ Draco18s我怀疑您之前用完了30000个单元格,因为每个嵌套解释器的大小都呈指数增长。我认为您会获得2,也许是3个级别的深度
Jo King

即使是3深度深处,也会很愚蠢。
Draco18s

27

红宝石1.8.7,188个 185 149 147字符

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

可读版本:

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

如您所见,我无耻地偷了您翻译成宿主语言然后使用eval来运行它的想法。


您可以舍弃与零比较的字节字节,>0而不用测试是否相等:!=0。规格说是无符号的,溢出是不确定的。
匿名co

3e4也会30000
与之

@查理:谢谢。公平地说,我编写代码时并没有说“未签名”。老实说,我不知道您可以写3e4。这是一个非常好的要点,并且要知道。
sepp2k 2011年

File.read($*.pop).bytes- > $<.bytes应太
阿诺·勒布朗

1
Ruby 1.8.7具有更短的语法来构建文字哈希值:{?a,"foo"},它等效于{?a=>"foo"}。并且此处的测试表明,您实际上可以毫无问题地替换File.read($*.pop).bytes$<。将所有内容都内联到类似内容的地方,eval"a[0]..."+$<.bytes.map{?.,"putc a[i]",...}*";"会使解决方案再缩短几个字符。
Ventero

26

二进制Lambda微积分112

下面的十六进制转储中显示的程序

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

期望其输入包含Brainfuck程序(仅查看0,1,4位以区分,-。+ <>] [),后跟一个],然后是Brainfuck程序的输入。

使用xxd -r> bf.Blc保存上述十六进制转储

https://tromp.github.io/cl/cl.html获取 blc解释器

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

你好,世界!


1
为什么这甚至存在?显然,它甚至存在于研究领域。Oo
Isiah Meadows

因此,这不适用于评论过的Brainfuck程序吗?
kamoroso94 '18

不,并非没有先删除评论。
John Tromp

18

视网膜0.8.2386个 391 386字节

代码包含不可打印的NUL(0x00)字符。它也不是超级高尔夫,因为它已经很慢了,如果我再打高尔夫球,我不知道要花多长时间。在首选样品上似乎超时。

在线解释器或我的程序中可能存在错误(输出中不显示前导新行?)。

接受类似的输入<code>│<input>。不,那不是管道(|)。这是Unicode字符U+2502。该代码还使用Unicode字符ÿ▶◀├║。使用Unicode字符以支持所有ASCII字符的输入。因此,这些字符需要用非ASCII字符与代码分隔。

在线尝试

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\`.*├|║.*

请注意那里有尾随换行符。

简要说明:

0x00用于磁带,它是无限的。第一个替换形式以形式设置解释器▶<code>│<input>├<output>║▶<tape>,其中第一个是代码的指针,第二个是磁带的指针。

ÿ0xFF(255),用于音译(用于实现+-)将单元格回绕到零。

仅用于可读性(以防程序在中间停止或您希望看到程序在中间执行)。否则,您将无法确定指针的移动方向。

注释代码:

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

单击此处以零位代替空字节的代码。任何出现的$0都不应替换为null。

编辑:现在支持空输入并禁止尾随换行符。

现在支持无限输出。(403字节)


我有点希望我<code><tape>彼此相邻放置(尽管会有更多的字符),这样,如果我决定这么做的话,过渡到SMBF解释器会更容易。
mbomb007 '16

14

TI-BASIC,264字节

由于TI-BASIC的局限性,因此实际上违反了规则2,因此不符合此挑战。计算器的RAM非常有限,执行类似操作30000->dim(L1(我将L1用于堆栈/数组)将迫使其抛出ERR:MEMORY。这样,堆栈/数组的大小为1,如果指针指向的元素超过其末尾,则堆栈/数组会增大。它也违反了规则3,因为它已经违反了规则2,因此我也不必担心单元大小的限制。

顺便说一句,也许还是可以打高尔夫球……自从首次提交以来,我为此做了一两个编辑,但是如果下面的版本不起作用,请回到15年5月6日开始使用代码代替。另外,由于TI-BASIC中实际上没有ASCII,因此它将任何大小的数字(以及任何返回数字的变量,例如变量或表达式)作为输入,并依次输出数字。

使用SourceCoder将其构建为.8xp文件,然后使用TI-Connect或TILP或其他方式将其发送到计算器,并通过在双引号中包括Brainfuck程序,双引号,冒号和任何TI-BASIC程序来运行它。举例来说,如果你把它命名为BRAINF,你会像这样运行的程序:"brainfuck goes here":prgmBRAINF。但是,如果您的calc上有一个外壳程序,当它检测到prgm令牌时会拦截其他命令,请执行以下操作:"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

如果您没有将计算器连接到计算机的方法,而是想在计算器上键入它(我无法想象您为什么要这么做,但是我离题了),请注意,这->是“ STO>打开”上方的按钮键,~是ENTER旁边的负号,并将的所有实例替换为L<number>在上找到的相应列表标记2ND -> <number on keypad>

感谢thomas-kwa(至少,我认为这是他的Stack用户名)帮助我优化了这一点,尤其是使用[]指令。


1
您需要周围的围裙Ans+S吗?
扎卡里

@Zacharý好收获,没有。我一定不确定PEMDAS的工作原理或其他内容...但是,我将避免编辑,因为已经很长时间了,将这篇文章放在最前面绝对是不值得的,因为有两个字节与其他方法相比,减少不会给答案带来任何优势。
MI Wright

1
我记得大约2-3年前,当我使用此程序在计算器上解释Brainf ***时。而且,这是一个令人费解的问题,老实说,我认为这应该是最重要的。
扎卡里

1
实际上,我认为整行都可以S-sum(not(cumSum(L4(Ans)=seq(L4(X),X,Ans+1,dim(L4->S。(a-a=0)。嘿,不要担心在这里忘记一个操作顺序,我已经看到很多人%在挑战中忘记了(mod)的操作顺序。
扎卡里

1
哦,是的 好的,这至少可以减少10个字节,因为if也可以做成单线,再加上其他一些东西,那么……也可以进行编辑。您已经让我像一年来第一次鞭打计算器来检查这些东西,哈哈
MI Wright

13

Python的275 248 255

我决定尝试一下。

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 

12
整洁的是,您正在使用Brainfuck生成python源代码。

1
您可以剥离1个字符,“将sys导入为s”,然后在其余部分中将“ sys”替换为“ s”

请注意,这实际上是247个字符。(请参阅exec t?后的讨厌空间)。如果您使用S.Mark的技巧并将整个for周期分成一行,则可以将其缩小到243个字符。
Oleh Prypin 2011年

这在包含[]的有效有效的bf程序的任何输入上均失败。我建议进行修改以解决此问题,但增加字符数。要进一步减少字符数,可以from sys import *使用,并使用'i+=1,...'.split(',')代替['i+=1',...]
2011年

7
我愿意+1,但已提出许多改进建议,但尚未实施。
mbomb007 '16

12

Haskell,457413个字符

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

此代码将BF程序“编译”为状态为无穷字符串上的拉链的IO动作State -> IO State

不幸的是我不得不花费29个字符才能关闭缓冲。没有这些,它就可以工作,但是在必须键入输入之前您看不到提示。编译器本身(bfk)只有99个字符,运行时(#%)是216个。带初始状态的驱动程序另有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 

2011年2月15日更新:结合了JB的建议,进行了一些重命名,并且收紧了main


1
您应该能够从just那里获得缓冲IO,而从just System(-19)得到参数。缓冲问题也使我感到困扰,因为规范并没有真正提及它,而最受好评的答案甚至都没有涉及I / O。如果必须保留它,则它可能hFlush比每次更改全局缓冲模式(-34 + 15)短得多。
JB

11

输送机,953

这可能是您见过的最漂亮的代码:

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
                                     ^=<=< (
                                       ^===<

8
您能否添加说明和实现的链接?我想了解美丽。;)
DLosc 2015年

1
好吧,我目前正在开发它,在github.com/loovjo/Conveyor上有一个编译器和一个非常糟糕的解释。如果您想了解源代码,则它可读性很强。
Loovjo 2015年

9

Ç 284 362(从文件)

#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);}

素数:

灌注至: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
按任意键继续 。。。

VS2008编译成功

原始解决方案无法识别最初设置为零的循环。还有一些打高尔夫球的空间。但最后解决了素数程序。

取消高尔夫:

#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);
}

测试:

你好,世界

腐烂13


您是否在l每次循环时都检查相同的指针()?我认为您应该检查头部(p)的当前位置。
亚历山德鲁

我将指针传递给缓冲区,将指针传递给流。它在循环末尾进行检查,以查看l缓冲区中的指针是否已达到零并中断,否则它将流重置为原始循环[。这对于嵌套[循环是必需的。
snmcdonald 2011年

1
是的 我是这么想的。第一次进入循环时,您不应检查指针的值,而应检查当前指针的值。检查问题中的测试。您的程序挂起。
亚历山德鲁(Alexandru)

1
您可以替换break;elsereturn;
Alexandru

3
我认为您可以替换(c==62)?a:b(c-62)?b:a
亚历山德鲁

9

PHP 5.4、296 294 273 263 263 261 209 191 183 178 166个字符:

我没有使用eval就给了它一个镜头,但最终我不得不使用它

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

所有命令均有效。这会严重滥用变量,并发出警告。但是,如果将其php.ini更改为静默警告(或将stderr管道传递到/ dev / null),则效果很好。

验证(这是Wikipedia的“ Hello World!”示例):http : //codepad.viper-7.com/O9lYjl

Ungolfed,367个 365 335 296 267字符:

<?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);

这应该通过命令行运行: php bf.php hello.bf


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

相当简单的转换说明然后Invoke-Expression

历史:

  • 2011-02-13 22:24(220)第一次尝试。
  • 2011-02-13 22:25(218)3e4比短30000
  • 2011-02-13 22:28(216)不必要的换行。匹配整数而不是字符更短。
  • 2011-02-13 22:34(207)使用索引代替哈希表的哈希表switch
  • 2011-02-13 22:40(205)更好地转换为字符串会删除两个括号。
  • 2011-02-13 22:42(204)在的参数之后不需要空格Write-Host

8

C,333个字符

这是我的第一个BF解释器,也是我实际上必须调试的第一个高尔夫球。

这可以在Mac OS X / GCC上运行素数生成器,但是#include<string.h>如果隐式定义strchr碰巧在其他平台上不起作用,则可能需要额外增加19个字符的费用。此外,它假设O_RDONLY == 0。除此之外intM省去声明保存3个字符,但这似乎不符合C99。同样的,第三个*b()

这取决于ASCII编码的细节。Brainfuck运算符都是互补的对,在ASCII码空间中相距2。该程序中的每个功能都实现一对运算符。

#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]();
}

我认为您可以通过对所有大数字使用“ e”表示法来进一步缩小它。
luser droog 2011年

@luser:最初我也很惊讶,但是语言和编译器不允许这样做。我确实设法通过调整来缩小了另外4个字符,并且使用a #define代替函数表也可能会更麻烦。我只喜欢数字333和表格:v)。
Potatoswatter 2011年

啊对。我真的应该知道这一点。E表示法是浮点常量的产生,而声明则需要一个整数。顺便说一句,这可能是作弊,但请查看nieko.net/projects/brainfuck以获取UrbanMüller的版本。最大的收获似乎是大量使用||
luser droog

8

CJam,75个字节

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

在线尝试:字符串反向器Hello World

说明

在STDIN的第一行上获取代码,并在其下面的所有行上输入。

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.

那神奇的名单呢?

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

结果列表如下:

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)

我们只需通过将左括号(CJam的“减量”)更改为右括号(CJam的“增量”),就可以为+和生成>来自-和的摘要<


最短答案和最大赢家
杰克·吉芬

7

F#:489个字符

下面的程序不会跳转到'['/']'指令,而是在源代码中扫描下一个匹配的标记。这当然会使它变慢,但仍然可以找到100以下的质数。F#整数类型不会溢出而是会包装。

这是简短的版本:

[<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

一个讨厌的陷阱是,primes.bf程序在Windows换行符上阻塞。为了运行它,我必须将输入数字保存到UNIX格式的文本文档中,并使用管道将其输入程序中:

interpret.exe prime.bf < number.txt

编辑:在Windows cmd.exe中也可以输入Alt + 010,然后按Enter。

这是更长的版本:

[<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 

我通过不按Enter而是Ctrl + J来解决Enter问题:-)
Joey

Ctrl + J对我不起作用,但是输入Alt + 010,然后按Enter键即可。
cfern

7

Delphi,397 382 378 371 366 364 328个字符

吃这个德尔福!

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.

这是缩进和注释的相同代码:

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.

这花了我几个小时,因为它不是我通常编写的那种代码,但是很享受!

注意:首要测试有效,但不能止于100,因为它在#10(LF)之前读取#13(CR)...在CRLF OS上运行时,其他提交是否也会遇到此问题?


哇!我从来没有期望过用Delphi简洁地胜过C!直到您将我的想法应用于CI猜想之前;-)
PatrickvL 2011年

7

C,260 + 23 = 283字节

我创建了一个C程序,可以在这里找到。

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++;}}

必须通过进行编译,gcc -D"q(a,b)"="*c-a||(b);" -o pmmbf pmmbf.c并且可以通过以下方式进行调用:pmmbf ",[.-]" 30000第一个参数(引号)包含要运行的bf程序,第二个参数确定磁带应该有多大。


1
我认为您需要为该-D"q(a,b)"="*c-a||(b);"选项添加23个字符,因为(至少在我的有限理解中)这似乎可以帮助您缩小代码。
加雷斯

该选项包含在发布的文本中。这样做的原因是避免使用冗长的单词define和换行符,但我认为这并不是真的。无论如何用引号,评论,gcc -D我完全看不到优势。
Potatoswatter

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);}

作为./a.out primes.bf运行

非高尔夫版本:

#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
}

5

Python 2,223

我承认我回收了我的旧程序(但必须对其进行相当大的更改,因为旧版本没有输入,但是有错误检查...)。

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

运行质数计算器正常。

我现在看到Alexandru的答案有一些相似之处。无论如何,我都会发布mny答案,因为我认为其中包含一些新想法。


5

C(gcc) Linux x86_64, 884 621 525 487 439 383 358 354字节

*z,*mmap();d[7500];(*p)();*j(a,g)char*a;{char*t=a,*n,c,q=0;for(;read(g,&c,!q);)t=c==91?n=j(t+9,g),z=mempcpy(t,L"\xf003e80Ƅ",5),*z=n-t-9,n:c==93?q=*t++=233,z=t,*z=a-13-t,z+1:stpcpy(t,c-62?c-60?c-43?c-45?c-46?c-44?"":"1\xc0P_\xF\5":"RXR_\xF\5":L"໾":L"۾":L"컿":L"웿");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);}

在线尝试!

这是一个JIT,可在运行时将BF代码编译为x86_64机器语言。这执行了直翻译所以经常发生的诸如序列>>><<<+++---没有合并成更快的指令。

少打高尔夫球的版本:

// 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);)
    t=c==91? // [
        // cmpb $0x0,(%rsi)
        // je n-t-9
        n=j(t+9,g),
        z=mempcpy(t,L"\xf003e80Ƅ",5)
        *z=n-t-9,
        n
      :
        c==93? // ]
          // jmp a-13-t
          q=*t++=233,
          z=t,
          *z=a-13-t,
          z+1
        :
          stpcpy(t,c-62? // >
                     c-60? // <
                       c-43? // +
                         c-45? // -
                           c-46? // .
                             c-44? // ,
                               ""
                             :
                               // 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);
}

4

C,374 368

从文件读取。通过PRIME.BF测试。

用法:./ 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;}}


重新格式化:

#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;
    }
}

3000 vs30000。您的缓冲区太小。程序大小也太小。
亚历山德鲁(Alexandru)

我打错了,固定了。程序大小是什么意思?如果您指的是最大文件大小,则没有指定应处理的最小文件大小。
jtjacques 2011年

4

卢阿(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]"))()

可读版本:

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

完美运作

Lua,478,未加载字符串

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

可读版本:

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

4

Brainfuck,948个字节

好吧,那花了一段时间。我打的是Brainfuck自我解释器,而不是我。

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

4

调用 594字节

简而言之:调用没有经典意义上的算术运算符,它只有按位运算。您不能只是“添加一个”等。调用也严格基于堆栈。

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

示例1:打印一些东西

输入:

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

输出:

PPCG rocks!

示例2:输出平方数最大为100

输入:

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

输出:

0
1
4
9
16
25
36
49
64
81
100

此示例可能需要花几分钟时间才能执行,并且可能会导致“此选项卡被冻结”消息。忽略它,然后等待。


4
您的网站域已过期。同样,这个答案是非竞争性的,因为这种语言比挑战性要新。
mbomb007 '16

3

OCaml(lex),497个字符

OCamllex是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}

另存为b.mll并运行

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

我不喜欢手工解析,因此我使用了提供的词法分析器生成器。从阅读的标记中,我们为整个Brainf * ck程序编写了一个函数。


3

C#(2861个字符,约84行)

这不是解决问题的最漂亮方法,可能也不是所有的“高尔夫式”解决方案,因为我对长度的关注不如应有的那样。(我没有删除注释或多余的空格。)我只是想尝试一种新语言,以查看是否可以。如果再次执行此操作,则放弃使用堆栈来从']'返回,然后回头看。在不使用命令行参数的情况下运行,它将运行问题描述中给出的hello world程序。它接受一个命令行参数,即要运行的程序的文件名。

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();

        }
    }

}

编辑:删除未使用的引用。


1
@ mbomb007-更新。完全忘记了我什至做到了这一点。(甚至都没有意识到有人甚至读过这些老问题)
theB 2015年

人们不仅会继续阅读,还会回答并打高尔夫球。
mbomb007 '16

3

C(gcc)273268字节

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

在线尝试!

-5感谢吊顶猫

接受来自stdin的输入。

这有点依赖于环境,但是非常一致。这实际上是c的评估解决方案。它将适当的C程序写入文件wc,对其进行编译,然后将其作为所需的可执行文件运行。因此,作为额外的效果,它实际上编译了bf代码,并a.out为其保留了二进制代码。请注意,根据系统,您可能需要修改最后一个字符串。特别是大多数Windows c编译器将默认可执行文件称为“ a.exe”。幸运的是,据我所知,它们都具有相同的长度,因此字节数相同。(尽管如果您没有定义cc,则可能需要在compile命令中添加gcc之类的字母,并增加1个字节)。

我知道这个线程有点旧,但是我还没有看到这种风格的C解决方案,因此我想添加它。



2

[编辑]

C ++ 11、355从文件读取:

#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]();
}

测试

http://ideone.com/b7vO4

[旧版本]

C ++ 11、391,以查看运行情况: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]();
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.