Brainfuck详解

tiger2005

2018-08-08 21:09:11

Personal

详解哥再度来袭~(前面出过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 ###### 提交时记得末尾回车哦 ---