祕密

祕密

學習練習

簡介

位元運算

位元運算讓我們可以操作二進位數字裡的個別位元。

Elm 在它的 Bitwise 模組 中提供了幾個位元運算子。

基本運算

修改數字中的個別位元稱為_遮罩_。 _遮罩_是一個數字,其中特定的位元以特定方式設定,讓我們能用 and、or 和 xor 等位元運算子來操作另一個數字。

and

and 會把兩個數字合併,只保留在兩個數字中都是 1 的位元。 這在檢查某個位元是否被設定時很有用。 舉例來說,要檢查某個數字的第 4 個位元是否設為 1,可以把它和遮罩 01000(十進位的 8)做 and,然後看看結果是不是非零:

Bitwise.and 13 8 --> 8
--  13 = 01101
--   8 = 01000
-- and = 01000 = 8
or

or 會把兩個數字合併,只要某個位元在其中一個或兩個數字中是 1,就把結果的該位元設為 1。 這在把某個特定位元設為 1 時很有用。 舉例來說,要把 10101 的第 2 個位元設為 1,可以把它和遮罩 00010 做 or:

Bitwise.or 21 2 --> 23
-- 21 = 10101
--  2 = 00010
-- or = 10111 = 23
互斥或(xor)

xor 會把兩個數字合併,如果某個位元在一個數字中是 1、在另一個數字中是 0,就把結果的該位元設為 1。 這在把某個位元翻轉成相反值時很有用:

Bitwise.xor 20 5 --> 17
--  20 = 10100
--   5 = 00101
-- xor = 10001 = 17
補數

complement 會反轉數字中的每個位元(0 變成 1,1 變成 0)。

要注意,這會讓正數變成負數,負數變成正數。 這是因為二進位中的負數是以最左邊的位元為 1 來表示。

Bitwise.complement 21 --> -22
--         21 = 00000000000000000000000000010101
-- complement = 11111111111111111111111111101010 = -22
位移

以下運算子會把位元向左或向右移動指定的位置數量,效果等同於乘以或除以 2 的次方。

shiftLeftBy 會把位元向左移,並從右側補 0。 舉例來說,把 21 向左移 3 個位置:

Bitwise.shiftLeftBy 3 21 --> 168
--  21 = 10101
-- shiftLeftBy 3 = 10101000 = 168

這等同於 21 * 2^3 = 21 * 2 * 2 * 2 = 168。

shiftRightBy:把位元向右移:

Bitwise.shiftRightBy 2 21 --> 5
--  21 = 10101
-- shiftRightBy 2 = 00101 = 5

向右移 2 個位置等同於整數除以 4。

要注意,這個函式會複製最左邊位元的值。 因此,負數會維持負數:

Bitwise.shiftRightBy 3 -21 --> -3
--  -21 = 111...101011
-- shiftRightBy 3 = 111...11101 = -3

如果你想向右移位並補零,可以使用 shiftRightZfBy:

Bitwise.shiftRightZfBy 3 -21 --> 536870909
--  -21 = 111...101011
-- shiftRightZfBy 3 = 00111...11101 = 536870909

說明

你的朋友剛傳來一則訊息,裡頭有個重要的秘密。 他不想讓別人輕易讀懂,所以把訊息經過一連串的位元操作加密了。 你需要撰寫幾個函式來協助解密這則訊息。

1. 將位元移回

解密訊息的第一步,是把加密時位移過的位元往右移回來。 解密過程後續的步驟會假設左側補進的是 0。

實作 shiftBack 函式,它接收要位移的位數和一個值,並執行位移。

shiftBack 2 42 --> 10

2. 設定一些位元

接下來,有些位元需要設成 1。

實作 setBits 函式,它接收一個遮罩和一個值,並把值中的位元設為 1。 當遮罩中的某個位元是 1 時,值中對應的位元也應該設為 1。 其他所有位元則保持不變。

setBits 66 212 --> 64

3. 翻轉特定的位元

加密過程中有些位元被翻轉了。 要解密訊息,就得把它們翻轉回來。

實作 flipBits 函式,它接收一個遮罩和一個值。 遮罩指出值中哪些位元要翻轉。 如果遮罩中的位元是 1,就把值中對應的位元翻轉。 其他所有位元則保持不變。

flipBits 23 157 --> 138

4. 清除特定的位元

另外還有一些位元,解密後一定是 0。

實作 clearBits 函式,它接收遮罩和值。 當遮罩中的位元是 1 時,value 中對應的位元應該設為 0。 其他所有位元則保持不變。

clearBits 2 15 --> 13

5. 解密訊息

現在你已經有需要的所有函式,可以解碼朋友傳來的訊息了。 實作 decrypt 函式,依序執行下列操作:

  1. 用你朋友出生的年份(1996)設定位元
  2. 用你們初次見面的年份(2009)翻轉結果
  3. 依照你們一起修的課堂數(5)把位元移回
  4. 清除第一個和第五個位元。
decrypt 380182 --> 11840

請用你在前面幾個任務中實作的函式來完成 decrypt。

透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Elm Exercism

準備好開始 祕密 了嗎?

註冊 Exercism,透過 28 個概念110 個練習 和真人引導來學習並精通 Elm,全部免費。