Esolang——2.brainfuck編程(一)
在上一篇文章中,我們寫(xiě)出了Helloworld程序。但是顯然,如果一個(gè)編程語(yǔ)言不應(yīng)只能輸出helloworld,它還要能干其他事情。接下來(lái),我們將使用其進(jìn)行編程。
在開(kāi)始前注意兩點(diǎn):
第一,本教程所使用的解釋器采用每個(gè)單元數(shù)據(jù)范圍0~255且為超出范圍后取模的規(guī)定。
例如,若指針當(dāng)前所指位置值為0,則執(zhí)行'-'命令后值變?yōu)?55
第二,為了方便,我們約定如下程序中出現(xiàn)的變量名指的是將指針移到變量對(duì)應(yīng)位置。
例如,設(shè)數(shù)組為a[],若指針在a[0],變量x在a[1],變量y在a[3],則x[y+x-]y即為>[>>+<<-]>>
第三,這里講的是如何將平時(shí)的程序給翻譯成bf程序,但brainfuck的一大魅力就是壓縮程序長(zhǎng)度。用這里的方法寫(xiě)出來(lái)的程序只是一種解,不一定是最優(yōu)解。
好的,我們開(kāi)始吧。

注釋
假設(shè)變量x==0
x[
在這里你想打什么就打什么,只要保證'['和']'一比一出現(xiàn)即可,
如果出現(xiàn)右中括號(hào)先于左中括號(hào)出現(xiàn)的情況可以在最外層多加一層中括號(hào)
]
x=0
x[-]
我們只需要把變量循環(huán)減到0就好了
x=y,y=0
x[-]y[x+y-]x
相當(dāng)于把y移到x的位置上,同時(shí)自己清零
x=y
與上面類似。為了恢復(fù)y的值,我們可以設(shè)置一個(gè)中間變量tmp,把y同時(shí)復(fù)制到x和tmp,再把tmp復(fù)制回y。
x[-]tmp[-]y[x+tmp+y-]tmp[y+tmp-]x
x+=y
tmp[-]y[x+tmp+y-]tmp[y+tmp-]x
只需要把x=y中的清空x變量刪去即可。
那么x=y+z怎么辦?我們可以分別運(yùn)行x=y,x+=z。這樣我們就獲得了結(jié)果。
x-=y
tmp[-]y[x-tmp+y-]tmp[y+tmp-]x
類似x+=y不解釋
while(x){code;}
x[
??? code;
x]
"code;"代指可以替換想要的代碼。
if(x){code;}
if(x){code;}可以寫(xiě)成
while(x){
??? code;
??? tmp=x,x=0;
}
x=tmp,tmp=0;
翻譯一下
tmp[-]x[
??? code;
x[tmp+x-]]tmp[x+tmp-]
或者,我們可以使用一種更簡(jiǎn)單的方法
tmp[-]x[
??? code;
tmp]
但這種方法的一大問(wèn)題就是程序執(zhí)行完后指針位置不同。如果x==0,那指針最后在x,否則指針最后在tmp。如果一定要這么寫(xiě)但又不希望指針移動(dòng)可以采用下面的方式。
向某一方向移動(dòng)直至當(dāng)前指針?biāo)冈貫?
向左
[<]
向右
[>]
這樣就可以把原本不同位置的指針定位到同一個(gè)特定的位置
或者我們也可以拓展一下
向某一方向移動(dòng)直至當(dāng)前指針?biāo)冈貫?
向左
-[+<-]+
向右
-[+>-]+
如果想要其他值,就把減號(hào)和加號(hào)的個(gè)數(shù)改動(dòng)一下就好了,不過(guò)這里比較使用的是常量。
if(x){code0;}else{code1;}
該語(yǔ)句可以拆成
tmp=1;
if(x){
??? code0;
??? tmp=0;
}
if(tmp){
??? code1;
}
如果我們采用通解寫(xiě)if,那么翻譯一下后獲得
tmp0[-]+tmp1[-]
x[
??? code0;
tmp0-x[tmp1+x-]]tmp1[x+tmp1-]
tmp0[
??? code1;
tmp0-]
?
tmp0[-]+tmp1[-]x[
??? code0;
tmp0-x[tmp1+x-]]tmp1[x+tmp1-]tmp0[
??? code1;
tmp0-]
如果要采用其他形式的if,相應(yīng)替換即可。比如下面
x=!x
實(shí)際上其可寫(xiě)成
if(x){
??? x=0;
}else{
??? ++x;
}
由于我們不需要保留x,所以相較于上面的if…else…,這里可以壓縮
tmp[-]+x[
tmp-x[-]]tmp[
??? x+
tmp-]x
?
tmp[-]+x[tmp-x[-]]tmp[x+tmp-]x
if(x==0){code;}
實(shí)際上其可以寫(xiě)成
if(x){
??? ;
}else{
??? code;
}
翻譯一下即得
tmp0[-]+tmp1[-]x[
tmp0-x[tmp1+x-]]tmp1[x+tmp1-]tmp0[
??? code;
tmp0-]
?
tmp0[-]+tmp1[-]x[tmp0-x[tmp1+x-]]tmp1[x+tmp1-]tmp0[
??? code;
tmp0-]
for(x=y;x;--x){code;}
可以寫(xiě)成
x=y;
while(x){
??? code;
??? --x;
}
翻譯一下
x[-]tmp[-]y[x+tmp+y-]tmp[y+tmp-]x[
??? code;
x-]
x*=y
x*y可以寫(xiě)作y個(gè)x相加,我們可以使用上述for循環(huán),即
for(tmp=x,x=0;tmp;--tmp){
??? x+=y;
}
翻譯一下即得
tmp0[-]
tmp1[-]x[tmp1+x-]tmp1[
??? y[tmp0+x+y-]tmp0[y+tmp0-]
tmp1-]x
?
tmp0[-]tmp1[-]x[tmp1+x-]tmp1[y[tmp0+x+y-]tmp0[y+tmp0-]tmp1-]x
x**=y
x**y可以寫(xiě)作y個(gè)x相乘,
tmp0=x,x=0;
x++;
for(tmp1=y;tmp1;--tmp1){
??? x*=tmp0;
}
tmp0=0;
翻譯一下
tmp0[-]tmp1[-]tmp2[-]
x[tmp0+x-]
+
y[tmp1+tmp2+y-]tmp2[y+tmp2-]tmp1[
??? tmp3[-]x[tmp2+x-]tmp2[tmp0[tmp3+x+tmp0-]tmp3[tmp0+tmp3-]tmp2-]
tmp1-]
tmp0[-]x
?
tmp0[-]tmp1[-]tmp2[-]x[tmp0+x-]+y[tmp1+tmp2+y-]tmp2[y+tmp2-]tmp1[tmp3[-]x[tmp2+x-]tmp2[tmp0[tmp3+x+tmp0-]tmp3[tmp0+tmp3-]tmp2-]tmp1-]tmp0[-]x
x/=y
tmp0=x,x=0;
tmp1=0;
while(tmp0){
??? for(tmp1=y;tmp1;--tmp1){
??????? --tmp0;
??????? if(tmp0==0){
????????? ??--tmp1;
??????????? if(tmp1){??????? //如果tmp0==0時(shí)tmp1!=0,說(shuō)明沒(méi)有整除,x要減掉一個(gè)后面多加的1
??????????????? --x;
??????????????? tmp1=0;
??????????? }
??????????? ++tmp1;
??????? }
??? }
??? ++x;
}
翻譯后
tmp0[-]tmp1[-]tmp2[-]tmp3[-]
x[tmp0+x-]
tmp0[
??? y[tmp1+tmp2+y-]tmp2[y+tmp2-]tmp1[
??????? tmp2+tmp0-[tmp2-tmp0[tmp3+tmp0-]]tmp3[tmp0+tmp3-]tmp2[
??????????? tmp1-[
??????????????? x-
??????????? tmp1[-]]
??????????? +
??????? tmp2[-]]
??? tmp1-]
??? x+
tmp0]x
?
tmp0[-]tmp1[-]tmp2[-]tmp3[-]x[tmp0+x-]tmp0[y[tmp1+tmp2+y-]tmp2[y+tmp2-]tmp1[tmp2+tmp0-[tmp2-tmp0[tmp3+tmp0-]]tmp3[tmp0+tmp3-]tmp2[tmp1-[x-tmp1[-]]+tmp2[-]]tmp1-]x+tmp0]x
x%=y
while(x){
??? tmp0=x;
??? for(tmp1=y;tmp1;--tmp1){
??????? x--;
??????? if(x==0){
??????????? tmp1--;
??????????? if(tmp1==0){
??????????????? tmp0=0;
??????????? }
??????????? tmp1=1;
??????? }
??? }
}
x=tmp0,tmp0=0;
?
tmp1[-]tmp2[-]tmp3[-]
x[
??? tmp0[-]x[tmp0+tmp1+x-]tmp1[x+tmp1-]
??? y[tmp1+tmp2+y-]tmp2[y+tmp2-]tmp1[
??????? tmp2+x-[tmp2-x[tmp3+x-]]tmp3[x+tmp3-]tmp2[
??????????? tmp3+tmp1-[tmp3-tmp1[-]]tmp3[tmp0[-]tmp3-]
??????????? tmp1+
??????? tmp2-]
??? tmp1-]
x]
tmp0[x+tmp0-]x
?(這個(gè)是我自己寫(xiě)的,期待有大佬優(yōu)化一下)
tmp1[-]tmp2[-]tmp3[-]x[tmp0[-]x[tmp0+tmp1+x-]tmp1[x+tmp1-]y[tmp1+tmp2+y-]tmp2[y+tmp2-]tmp1[tmp2+x-[tmp2-x[tmp3+x-]]tmp3[x+tmp3-]tmp2[tmp3+tmp1-[tmp3-tmp1[-]]tmp3[tmp0[-]tmp3-]tmp1+tmp2-]tmp1-]x]tmp0[x+tmp0-]x
練習(xí)
一、承接輸入
貓程序(cat program(我真不知道該怎么翻))是一個(gè)將標(biāo)準(zhǔn)輸入復(fù)制到標(biāo)準(zhǔn)輸出的程序。
輸入:一串不定長(zhǎng)字符串,以換行符結(jié)尾
輸出:輸入的字符串(包括換行符)
示例:輸入:Hello, World!\n
輸出:Hello, World!\n
二、輸入數(shù)字
brainfuck中所有的輸入都是字符形式,所以沒(méi)辦法直接輸入數(shù)字。
輸入:一個(gè)范圍在0~255間的正整數(shù),以換行符結(jié)尾
輸出:該數(shù)字對(duì)應(yīng)ASCII字符
示例:輸入:97\n
輸出:a
三、數(shù)字輸出
輸入:一個(gè)ASCII字符
輸出:該ASCII字符對(duì)應(yīng)十進(jìn)制正整數(shù)
示例:輸入:a
輸出:97
四、平方數(shù)計(jì)算
輸入:一個(gè)范圍在0~15之間的整數(shù),以換行符結(jié)尾
輸出:該數(shù)字平方數(shù)
示例:輸入:12\n
輸出:144

參考:
[1]Brainfuck algorithms - Esolang?https://esolangs.org/wiki/Brainfuck_constants