Brainfuck详解
tiger2005
2018-08-08 21:09:11
详解哥再度来袭~(前面出过SPJ详解)
你有没有玩过NazoGame呢
是不是觉得第19关很和谐?
![](https://cdn.luogu.com.cn/upload/pic/25012.png)
看看地址,哎,怎么写着
** brainfuck? **
------------
这便是我们今天要讨论的东东
实际上,Brainfuck是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainf*ck或brainf**k,甚至被简称为BF。
这就是一个语言,但它不像C++那么多元化,但难度也一定的增加,因为
**它只有8种关键字!**
虽然还有一些更特殊的语言,chicken只有一个关键字chicken。Whitespace由空格、Tab、回车组成,所以全是白的。
但Brainfuck语言可以和[图灵机](https://baike.so.com/doc/5960496-6173444.html)互相模拟
~~图灵机就是一个模拟数学计算机器人~~
接下来,就看看这8个关键字有什么用。
## 基本操作
我们可以假想
Brainfuck开了一个近乎无限长的数组,大小1byte,一个指针指向一个位置
### 指针操作
```cpp
> 指针右移一位指向下一个字节
< 指针左移一位指向上一个字节
由于指针两边不会无限长,所以会出现溢出空间的情况,编译器会报错。
```
### 字节操作
```cpp
+ 当前指针指向的字节+1
- 当前指针指向的字节-1
```
当然,一个byte只能存256个数,Brainfuck选择存储0-255,但Brainfuck有一种很玄学的东西
0-1=255
255+1=0
也就是说它自动模256···
### 读写操作
```cpp
. 以char的形式输出当前指针指向的字节(48会输出'0')
, 以ASCII的形式读入到当前指针指向的字节(读入'0'会存储48)
```
getch的回车10会变为换行13,打编译器时要注意了。
### 循环操作
```cpp
[ 当当前指针指向的字节不是零时,会进行循环
] 当当前指针指向的字节非零时回到循环,否则退出
```
正确的代码中,所有的循环符号将会分组,两个循环只有分离和包含关系。上面所说的‘循环’就是分组后的循环
所以,8个字符可以与C++转化,这个自己研究去
## 实例
符号介绍完了,来道小题试试
```cpp
,----------[----------------------.,----------]
```
翻译一下?
首先,读入一个字符并减去10
之后,当这个字节非0时循环
循环中将字节减去22输出后重新读入,之后减去10
当它还不是0时继续循环
当它是0时结束循环
什么意思呢
就是将小写字母转大写啦~
回车结束啦~
## 常用算法
### 加减算法
如何将一个字节减48?
最直接的就是48个 - 了
但想一想啊
48=6*8
你可以将下一个字节加上6(保证它是0哦)之后打一个循环
当它非0时往左移一位减去8后挪回来减1就行啦~
代码如下
```cpp
>++++++[<-------->-]<
```
### 复制算法
想想怎么将一个字节上的数挪到下一个字节呢?
```cpp
[>+<-]
```
但你会发现原来那个数字没了!qДq
怎么办呢?
先将这个数复制到另一个地方再同时复制
```cpp
[>>+<<-]>>[<+<+>>-]<<
```
第一个循环将这个数复制到后两位
第二个循环将后两位上的数同时复制到原先那一位和其后面的一位
### 清零算法
清零?
```cpp
[-]
```
不用解释了吧~剩下的就自己去摸索和训练吧
## BF 的特点
当然 Brainfuck还是有一些好处和坏处的
- 读入:快速读入(普通读入int读不进,double超难写)
- 输出:快速输出(输出全是字符)
- 码长:1000 1000多行~有兴趣的可以去玩玩
- 省略:省略所有除关键字外的字符,所以你可以把它藏在一篇文章中
- 出题:给那些不懂的人玩玩
- ~~装逼~~
## 实际应用
拿一道题做例子(下面有提交地址的哦)
小鱼的游泳时间
这道题的读入有两位数,这正好是一个byte能存下来的
但需要输入处理
先读入一个数,减去48
判断下一个字符是否为空格
若不是,赶紧将前一位乘10啊啊啊
之后就是相加啦~
```cpp
,>++++++[<++++++++>-],--------------------------------[----------------<[>++++++++++<-]>[<+>-]<,[-]]
```
但!负数怎么处理呢
首先我们知道,这个负数不会小于-60,所以可以将其加60后进行60整数除法。若结果为1就表明不用处理否则时数减1
思路就是这样,除法代码暂不给出
---
## 彩蛋
编译器(本人的[)](https://www.luogu.org/blog/tiger2005/bf-bian-yi-qi)
P1000的Brainfuc[k](https://www.luogu.org/problemnew/show/T39818)
P1425[的](https://www.luogu.org/problemnew/show/T39960)Brainfuck
P1427的[B](https://www.luogu.org/problemnew/show/T40047)rainfuck
P191[4](https://www.luogu.org/problemnew/show/T40183)的Brainfuck
###### 提交时记得末尾回车哦
---