BrainFuck
Dec 4, 2016
1 | ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. |
上面这段 BrainFuck 代码输出结果是 Hello World! 。是不是第一次看到这样的代码的时候一脸懵〇。
原语
BrainFuck 是一种故意刁难程序员的图灵完备语言。语言的执行类似栈的出栈入栈,搭配一个指向栈顶的指针,进行相应的输出输入等操作。整个语言只有 8 个原语
原语 | 操作 | 类比C语言 |
---|---|---|
> | 指针 + 1 | ++ptr |
< | 指针 - 1 | –ptr |
+ | 指针指向的数据 + 1 | ++*ptr |
- | 指针指向的数据 - 1 | –*ptr |
. | 输出指针指向的数据 | putChar(*ptr) |
, | 接受数据输入,存在指针所指向的位置 | *ptr = getChar() |
[ | 循环开始,数据为零则结束循环 | while(*ptr){ |
] | 循环结束 | } |
BrainFuck 只接受这 8 个字符,其他字符全部忽略。所以注释可以直接写,只要注释中没有原语。
简单的程序
BrainFuck 中所有数据都初始化为 0 ,模型看起来像是这样的
1 | (0) 0 0 0 0 0 0 0 0 ... ()用于表示当前指针的位置 |
输出以 ASCII 编码输出。输出后数据不会清零。
ASCII 中第一个可见字符是 !
,ASCII 码为 33 。所以只要用 +
加 33 次就可以从 0 变成 33 了。之后输出即可。
1 | +++++++++++++++++++++++++++++++++. |
直接写 33 个 +
似乎有点蠢。既然做的事是重复的事情,用循环是最自然的。
$33 = 3 \times 11$ 。循环 3 次,每次加 11 就可以了。
1 | +++ (3) 0 0 0 0 0 …… 写入循环次数 |
完整的代码
1 | +++[>+++++++++++<-]>. |
22 个字符,比原来 34 个字符少了 12 个字符。
Hello World!
Hello World!
的输出方式也是类似的。
1 | ++++++++++ (10) 0 0 0 0 0 …… |
也不是很难嘛。只不过把实现的思想隐藏到了代码中。
最后
1 | ++++++++++[>++++>+++++++++++>+++<<<-]>+++.++++++.>+++++.>+++. |