大忙人系列-程序猿在想什么 (一中) 禁止套娃
三. brainf**k
为什么叫这个名字呢,因为写这个语言的代码就如同在干自己的大脑一样,故得此名。
逻辑结构上图灵机有四个部分组成,无限长的存储带,可以任意移动增删改存储格上的数字或符号的读写头,状态机,以及控制程序指令令机器进入一个新的状态或保持状态不变。显然,brainf**k甚至挺契合这原始的定义。
那么,如何用brainf**k正常地写程序呢?
鉴于说不定有的人不想去百度了,在这里就贴一下brainf**k的指令集。
> 读写头右移
< 读写头左移
+ 当前元素自增
- 当前元素自减
. 打印当前元素
, 输入到当前元素
[ 若元素为0跳转到匹配的],否则继续,为循环开始头
] 跳转到匹配的[
为了不被说成水字数(写这个专栏的还好意思说?),下面一个符号加上一个数代表重复运算多少次吧。
可预见的是,这破玩意儿似乎连个加法都不太能正常地做到。为了避免因为信息量过大而烧脑,就从最简单的东西开始做起吧。
第一题,读入一个字符串以0结尾。
,[>,]
读入,不是0就要读下一个。
第二题,以换行为分界,读入一个字符串
难度似乎瞬间就上了不少。众所周知,换行符ASCII是10(不想考虑换行与回车之间的亲(P)密(Y)关系了)。
那么,问题就是当前值不为10,就读下一个喽。
-10[+10>,-10]+10
热身玩了,接下来来看看普通编程语言的各种语句能怎么整。
while(x) {sth}
最简单的: x[sth x]
brainf**k天然支持while
if(x) {sth.}
temp[-]
x[ sth temp ]x
和while一样,只不过多一步强制结束
if(x) {sth1} else {sth2}
temp0[-]+ ;temp0=1
temp1[-] ;temp1=0
x[ ;while(x) {
sth1
temp0- ;temp0=0
x[temp1+x-] ;temp1=x
] ;}
temp1[x+temp1-] ;x=temp1
temp0[
sth2
temp0-]
比较明显的用了两个变量来将if-else转为两个if
有了if有了while,那么任意程序都可以肆无忌惮随心所欲了。感兴趣的不如试着用brainf**k写个brainf**k?
四. 生命游戏
生命游戏也是个被说烂了的东西。在一个二维平面上,如果一个细胞周围有3细胞为生(一个细胞周围共有8个细胞),则该细胞生。如果一个细胞周围有2个细胞为生,则该细胞的生死状态保持不变;其它情况下,该细胞为死。
生命游戏中,一个比较核心的东西是个叫“滑翔机”的由5个活的细胞组成,形状如下:
001
110
011
可以预见的,如果没有什么外部干扰,这个滑翔机可以飞到天荒地老。当两个滑翔机撞在一起的时候,可以调整距离与周期到最后刚好消失掉(撞机了还想活?)。
有了滑翔机,当然要有个发射滑翔机的东西——滑翔机枪啦。
那么我们第一个逻辑门非门·of the·生命游戏出来了——一个滑翔机枪不停输出滑翔机,如果有输入(滑翔机),那么两机相撞就会变成无输出。第一个非门。
想造一个与门的话,先需要一个滑翔机枪加上一个吞噬者。吞噬者形状大致如下:
0011
0101
0100
1100
假设机枪往右侧发滑翔机并且被吞噬者吃掉。输出为向上的方向,那么当且仅当有两波滑翔机向上飞行,一波抵消,一波出去,这个时候才有输出。(与门get)
或门类似,一开始两个滑翔机枪垂直,所有的飞机抵消;两个输入中任意一个有飞机过来,抵消其中一个机枪,那么剩下的那个机枪就可以有输出了。当然,当两个输入都有飞机时看情况需要吞噬者把输入的飞机吃掉。
有了与、或、非,不试试锁存器啊状态机啊什么的神奇玩意儿吗?