成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

然并卵:BF 科普 & BF 解釋器的 JS 實(shí)現(xiàn)

HackerShell / 3721人閱讀

摘要:最近在上做練習(xí),某道題的內(nèi)容是實(shí)現(xiàn)一個(gè)簡稱語言解釋器等等均可。這篇文章準(zhǔn)備聊聊相關(guān)的一些知識(shí)和實(shí)現(xiàn)的細(xì)節(jié)。誕生于上世紀(jì)年代,曾運(yùn)用于早期的,想詳細(xì)了解的童鞋可以瀏覽維基百科。例如,當(dāng)某個(gè)存儲(chǔ)單元的值為時(shí),其執(zhí)行指令的結(jié)果為。

最近在 Codewars上做練習(xí),某道題的內(nèi)容是實(shí)現(xiàn)一個(gè) brainFuck(簡稱BF語言) 解釋器(c/python/js等等均可)。動(dòng)手實(shí)踐的過程還是很有趣的,中間也遇到了各種各樣的問題,最終通過測試,代碼也比較接近目前的 JS 高分 solution。這篇文章準(zhǔn)備聊聊相關(guān)的一些知識(shí)和實(shí)現(xiàn)的細(xì)節(jié)。

“腦洞大開”的語言 —— BF 簡介

BrainFuck(后文以簡寫B(tài)F指代),單是名字就很容易讓人腦洞大開,有種不可描述的“哲學(xué)”韻味。所以如果你忍不住 google 一下相關(guān)圖片的話,你會(huì)可能搜到類似下面的圖片:

畫面是不是已經(jīng)很生動(dòng)了?

BF 字面上的含義已經(jīng)暗示了這是一種不太直觀和容易閱讀的語言,當(dāng)然,在當(dāng)下也不會(huì)是一種通用語言。她屬于 Esolang(全稱 Esoteric programming language,直譯:深?yuàn)W的編程語言) 的范疇。

BF誕生于上世紀(jì)30年代,曾運(yùn)用于早期的 PC(Amiga),想詳細(xì)了解的童鞋可以瀏覽 維基百科。

BF 在當(dāng)下有什么應(yīng)用場景呢?

我想,對一個(gè)吃瓜群眾來說,了解了它,對寫作 逼格腦力 的提升是很有用的。BF 具有極簡主義(搞設(shè)計(jì)的童鞋的不妨了解下下)和功能齊全(圖靈完全)的特點(diǎn),旨在為用戶帶來困惑和挑戰(zhàn),豐富勞動(dòng)人民的業(yè)余生活。

8 種運(yùn)算符及其操作

BF 作為一種極簡的計(jì)算機(jī)語言,僅有8種運(yùn)算符,分別為: < > + - , . [ ],其功能對照如下表所示:

指令 含義
< 指針減一(指針左移)
> 指針加一(指針右移)
+ 指針指向的字節(jié)的值加一(當(dāng)前單元的數(shù)值+1)
- 指針指向的字節(jié)的值減一(當(dāng)前單元的數(shù)值-1)
, 輸入內(nèi)容到指針指向的單元(輸入一個(gè)字符,將其ASCII碼保存到當(dāng)前指針?biāo)竼卧?/td>
. 將指針指向的存儲(chǔ)單元的內(nèi)容作為字符輸出(將ASCII碼輸出為字符)
[ 如果指針指向的存儲(chǔ)單元為零,向后跳轉(zhuǎn)到對應(yīng)的 ] 指令處
] 如果指針指向的存儲(chǔ)單元不為零,向前跳轉(zhuǎn)到對應(yīng)的 [ 指令處

BF基于一個(gè)簡單的機(jī)器模型,除了八個(gè)指令,這個(gè)機(jī)器還包括:一個(gè)以字節(jié)為單位、被初始化為零的數(shù)組、一個(gè)指向該數(shù)組的指針(初始時(shí)指向數(shù)組的第一個(gè)字節(jié))、以及用于輸入輸出的兩個(gè)字節(jié)流。

對 BF 比較有意思的比擬可以是這樣的:

如果把機(jī)器內(nèi)存看成是一個(gè)無限長的“小火車”(類似于ArrayList的數(shù)據(jù)結(jié)構(gòu)),每個(gè)車廂(存儲(chǔ)單元)里面的貨物默認(rèn)都是數(shù)字 0,列車上僅有一個(gè)列車員(數(shù)據(jù)指針);

<> 相當(dāng)于列車員在車廂間進(jìn)行移動(dòng),只有當(dāng)列車員在某節(jié)車廂時(shí),才能對車廂的貨物進(jìn)行操作;

+- 相當(dāng)于列車員對當(dāng)前所在車廂的貨物進(jìn)行增減;

, 相當(dāng)于列車在裝貨,列車員將當(dāng)前所在車廂的貨物替換為貨運(yùn)站輸入的單批次貨物(一個(gè)字符的ASCII碼);

. 會(huì)將當(dāng)前車廂里的貨物名稱(單個(gè)字符)輸出來;

[] 相當(dāng)于列車員在滿足條件的兩節(jié)車廂間來回移動(dòng);

這里要注意的是,數(shù)組的每個(gè)單元都是一個(gè)字節(jié)大小;- 命令允許溢出,它可以用 255 個(gè) + 命令來代替。例如,當(dāng)某個(gè)存儲(chǔ)單元的值為 255 時(shí),其執(zhí)行指令 + 的結(jié)果為 0。類似的, 0 執(zhí)行指令 - 的結(jié)果為 255.

與通用語言的類比

據(jù)此,BF的運(yùn)算符與通用語言的類比如下(以C語言為例):

BrainFuck C
< --ptr;
> ++ptr;
+ ++*ptr;
- --*ptr;
, *ptr = getchar();
. putchar(*ptr);
[ while (*ptr) {
] }
BF 解釋器的 JS 函數(shù)實(shí)現(xiàn) 代碼奉上:
function brainLuck(code, input) {             // @1
  const inputChars = input.split("");         // @2

  const codes = code.split("");               // @3
  let codeIdx = 0;

  const arr = [];                             // @4
  let arrIdx = 0;
  let outputStr = "";                         // @5

  while (codeIdx < code.length) {             // @6
    const ops = codes[codeIdx];

    const handleLeftBracket = () => {         // @7
      if (~~arr[arrIdx] === 0) {
        let cnt = 1;

        while (cnt) {
          codeIdx++;
          if (codes[codeIdx] === "[") {
            cnt += 1;
          }
          if (codes[codeIdx] === "]") {
            cnt -= 1;
          }
        }
      }
    };

    const handleRightBracket = () => {        // @8
      if (~~arr[arrIdx] !== 0) {
        let cnt = 1;

        while (cnt) {
          codeIdx--;
          if (codes[codeIdx] === "]") {
            cnt += 1;
          }
          if (codes[codeIdx] === "[") {
            cnt -= 1;
          }
        }
      }
    };

    switch (ops) {                            // @9
      case ">":
        arrIdx += 1;
        break;
      case "<":
        arrIdx -= 1;
        break;
      case "+":
        arr[arrIdx] = (~~arr[arrIdx] + 1) % 256;
        break;
      case "-":
        arr[arrIdx] = (~~arr[arrIdx] || 256) - 1;
        break;
      case ",":
        const iptChar = inputChars.shift();
        arr[arrIdx] = iptChar ? iptChar.charCodeAt(0) : arr[arrIdx];
        break;
      case ".":
        outputStr += String.fromCharCode(arr[arrIdx]);
        break;
      case "[":
        handleLeftBracket();
        break;
      case "]":
        handleRightBracket();
        break;
    }

    codeIdx++;                               // @10
  }

  return outputStr;                          // @11
}
實(shí)現(xiàn)思路闡述(與代碼中注釋的序號(hào)對應(yīng)):

(1) 我們實(shí)現(xiàn)了一個(gè)函數(shù) brainLuck 用以模擬 BF 語言的解釋執(zhí)行,函數(shù) brainLuck 的用例如下:

const code = ",+[-.,+]";
const input = "Parksben" + String.fromCharCode(255);

const output = brainLuck(code, input);
console.log(output); // -> "Parksben"

(2) 將輸入的字符串切割為單個(gè)字符,暫存進(jìn)數(shù)組 inputChars;

(3) 將 BF 程序切割為單個(gè)操作符,方便遍歷每個(gè)指令,用 codeIdx 作為下標(biāo)進(jìn)行遍歷;

(4) 聲明一個(gè)數(shù)組 arr 用以模擬機(jī)器內(nèi)存,過程產(chǎn)生的數(shù)值存儲(chǔ)到此數(shù)組中;

(5) 用字符串 outputStr 存儲(chǔ)程序的輸出;

(6) 遍歷 BF 運(yùn)算符,對不同指令進(jìn)行相應(yīng)的操作;

(7) 方法 handleLeftBracket,用以匹配到與當(dāng)前 [ 對應(yīng)的 ](通過操作下標(biāo) codeIdx);

(8) 方法 handleRightBracket,用以匹配到與當(dāng)前 ] 對應(yīng)的 [(通過操作下標(biāo) codeIdx);

(9) 用以處理不同指令的 switch 語句;

(10) codeIdx 加一,以向前遍歷 codes;

(11) 程序輸出;

延伸閱讀

Brainfuck: a Programming Language or a Joke?

丹尼爾·克里斯托法尼的一些 BF 實(shí)例

深?yuàn)W的編程語言 - 維基百科

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/96890.html

相關(guān)文章

  • 關(guān)于修改DOM是異步還是同步問題

    摘要:還請同學(xué)跟我多多探討關(guān)于修改是異步還是同步的問題先來看代碼上述代碼的結(jié)果完全就是同步的表現(xiàn),如果是異步的話,毫無疑問,第一個(gè)下的每個(gè)內(nèi)容都應(yīng)該是,第二個(gè)也應(yīng)該是。 回 @bf 同學(xué) 本篇文章不是筆記也不是心得,而是關(guān)于一個(gè)問題的討論,問題最初出現(xiàn)于https://segmentfault.com/q/1010000005630545?_ea=903562 由于 @bf 同學(xué)不方便...

    qingshanli1988 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

HackerShell

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<