秘密

秘密

学習演習

はじめに

ビット演算

ビット演算を使うと、2進数の個々の桁を操作できます。

Elmでは、Bitwiseモジュールでいくつかのビット演算子が提供されています。

基本的な演算

数値の個々のビットを操作することを_マスキング_と呼びます。 _マスク_とは、特定のビットをある決まったパターンにした数値で、andやor、xorなどのビット演算子を使って別の数値を操作するために使います。

and

andは、2つの数値の両方で1になっているビットだけを残して、それらを結合します。 これは、特定のビットがセットされているかどうかを調べるときに便利です。 たとえば、ある数値の4番目のビットが1にセットされているかを調べるには、01000(10進数の8)というマスクとandして、結果が0以外になるかを見ます。

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

orは、どちらか一方または両方の数値で1になっているビットを1にして、2つの数値を結合します。 これは、特定のビットを1にするときに便利です。 たとえば、10101の2番目のビットをセットするには、00010というマスクとorします。

Bitwise.or 21 2 --> 23
-- 21 = 10101
--  2 = 00010
-- or = 10111 = 23
排他的論理和(xor)

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

説明

友達から、重要な秘密が書かれたメッセージが届きました。 他の人に簡単に読まれないように、このメッセージは一連のビット操作によって暗号化されています。 メッセージを復号するための関数を書く必要があります。

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. 1番目と5番目のビットをクリアする
decrypt 380182 --> 11840

前のタスクで実装したすべての関数を使ってdecryptを実装してください。

GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Elm Exercism

秘密を始める準備はできましたか?

Exercismに登録すれば、28個のコンセプト110個の演習、そして本物の人間によるメンタリングとともに、Elmを学んでマスターできます。すべて無料です。