ビット演算を使うと、2進数の個々の桁を操作できます。
Elmでは、Bitwiseモジュールでいくつかのビット演算子が提供されています。
数値の個々のビットを操作することを_マスキング_と呼びます。
_マスク_とは、特定のビットをある決まったパターンにした数値で、andやor、xorなどのビット演算子を使って別の数値を操作するために使います。
andは、2つの数値の両方で1になっているビットだけを残して、それらを結合します。
これは、特定のビットがセットされているかどうかを調べるときに便利です。
たとえば、ある数値の4番目のビットが1にセットされているかを調べるには、01000(10進数の8)というマスクとandして、結果が0以外になるかを見ます。
Bitwise.and 13 8 --> 8
-- 13 = 01101
-- 8 = 01000
-- and = 01000 = 8
orは、どちらか一方または両方の数値で1になっているビットを1にして、2つの数値を結合します。
これは、特定のビットを1にするときに便利です。
たとえば、10101の2番目のビットをセットするには、00010というマスクとorします。
Bitwise.or 21 2 --> 23
-- 21 = 10101
-- 2 = 00010
-- or = 10111 = 23
xorは、片方の数値で1、もう片方で0になっているビットを1にして、2つの数値を結合します。
これは、ビットを反転させて反対の値にするときに便利です。
Bitwise.xor 20 5 --> 17
-- 20 = 10100
-- 5 = 00101
-- xor = 10001 = 17
complementは、数値の各ビットを反転させます(0は1に、1は0になります)。
この結果、正の数は負の数に、負の数は正の数になります。
2進数では、負の数は一番左の位を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
右にシフトして0で埋めたい場合は、shiftRightZfByを使います。
Bitwise.shiftRightZfBy 3 -21 --> 536870909
-- -21 = 111...101011
-- shiftRightZfBy 3 = 00111...11101 = 536870909
友達から、重要な秘密が書かれたメッセージが届きました。 他の人に簡単に読まれないように、このメッセージは一連のビット操作によって暗号化されています。 メッセージを復号するための関数を書く必要があります。
メッセージを復号する最初のステップは、暗号化の過程で行ったシフトを元に戻すために、ビットを右にシフトし直すことです。
このあとの復号のステップでは、左側から0が挿入されることを前提としています。
shiftBack関数を実装してください。この関数は、シフトする桁数と値を受け取り、シフトを実行します。
shiftBack 2 42 --> 10
次に、1に設定する必要があるビットがあります。
setBits関数を実装してください。この関数は、マスクと値を受け取り、値のビットを1に設定した結果を返します。
マスクのビットも1になっている位置では、値のビットを1に設定します。
それ以外のビットはそのままにします。
setBits 66 212 --> 64
暗号化の際に、いくつかのビットが反転されています。 メッセージを復号するには、それらを元に反転し直す必要があります。
flipBits関数を実装してください。この関数は、マスクと値を受け取ります。
マスクは、値のどのビットを反転させるかを示します。
マスクのビットが1であれば、値の対応するビットを反転させます。
それ以外のビットはそのままにします。
flipBits 23 157 --> 138
また、復号すると必ず0になるビットもあります。
clearBits関数を実装してください。この関数は、マスクと値を受け取ります。
マスクのビットが1である位置では、valueのビットを0に設定します。
それ以外のビットはそのままにします。
clearBits 2 15 --> 13
必要な関数がすべてそろったので、友達のメッセージを復号できます。
次の処理を行うdecrypt関数を実装してください。
decrypt 380182 --> 11840
前のタスクで実装したすべての関数を使ってdecryptを実装してください。