秘密

秘密

学習演習

はじめに

Crystalには、Intをバイナリレベルで操作するためのビット演算子があります。

シフト演算子

Crystalには、ビットを左(<<)または右(>>)にシフトするシフト演算子があります。

左シフト(<<)

左シフト演算子(<<)は、ビットを左にシフトします。 シフトする値は左側に、シフトする桁数は右側に指定します。

0b0010 << 1
# => 0b0100

0b0010 << 2
# => 0b1000

数値が負の場合、代わりに右にシフトします。

0b0010 << -1
# => 0b0001

右シフト(>>)

右シフト演算子(>>)は、ビットを右にシフトします。 左シフト演算子と同様に、シフトする値は左側に、シフトする桁数は右側に指定します。

0b0100 >> 1
# => 0b0010

0b0100 >> 2
# => 0b0001

同じように、数値が負の場合、演算子は左にシフトします。

0b0100 >> -1
# => 0b1000

二項演算子

Crystalには、ビット単位の演算を行うための3つの二項演算子(&、|、^)と、~演算子があります。

ビット単位のAND(&)

二項AND演算子(&)は、2つの値に対してビット単位のANDを実行します。 1つ目の値の各ビットを、2つ目の値の同じ位置にあるビットと比較します。 両方のビットが1であれば、結果のビットは1になります。 それ以外の場合は0になります。

0b0011 & 0b1010
# => 0b0010

ビット単位のOR(|)

二項OR演算子(|)は、2つの値に対してビット単位のORを実行します。 これも、1つ目の値の各ビットを、2つ目の値の同じ位置にあるビットと比較します。 どちらかのビットが1であれば、結果のビットは1になります。 それ以外の場合は0になります。

0b0011 | 0b1010
# => 0b1011

ビット単位のXOR(^)

二項XOR演算子(^)は、ビット単位のXORを実行します。 ビット単位のAND演算子やビット単位のOR演算子と同様に、1つ目の値の各ビットを、2つ目の値の同じ位置にあるビットと比較します。 それらのうち_1つだけ_が1であれば、結果のビットは1になります。 それ以外の場合は0です。

0b0011 ^ 0b1010
# => 0b1001

ビット単位のNOT(~)

最後に、ビット単位のNOT演算子(~)は、値の各ビットを反転させます。 他の二項演算子とは異なり、これは単項演算子で、右側の値だけを対象に操作します。

~0b1110_0010
# => 0b0001_1101

説明

友達が、大切な秘密を書いたメッセージを送ってきました。 他の人に簡単に読まれたくないということで、そのメッセージは一連のビット操作を使って暗号化されています。 このメッセージを復号するには、プログラムを書く必要があります。

1. ビットを左に戻す

メッセージを復号する最初のステップは、暗号化のときにシフトされたビットを、左にシフトして元に戻すことです。 何ビット左にシフトするかは、メッセージによって異なります。

値と、左にシフトするビット数を受け取るメソッドSecrets.shift_backを実装しましょう。

Secrets.shift_back(0b0001, 2)
# => 0b0100

2. ビットマスクを適用する

次のステップは、特定のビットの値を取り出すためにビットマスクを適用することです。 マスクを適用するには、値とマスクの間でビット単位のAND演算を行います。

値を受け取り、マスクを適用するメソッドSecrets.apply_maskを実装しましょう。

Secrets.apply_mask(0b0110, 0b0101)
# => 0b0100

3. ビットをいくつか立てる

ビットを左にシフトすると、新しい0のビットがいくつか加わります。 これらの新しいビットのいくつかは、1に設定する必要があります。 ビット単位のORは、ほかのビットを保ったまま特定のビットを1に設定するのに役立ちます。

2つの値を受け取り、ビット単位のOR演算を行うメソッドSecrets.set_bitsを実装しましょう。

Secrets.set_bits(0b0110, 0b0101)
# => 0b111

4. XORを逆算する

暗号化の過程の一部では、取り決めた値とのXOR演算が行われます。 元の値に戻すには、暗号化された値をもう一度、取り決めた値とXORするだけで済みます。 ただし、ちょっとした誤解から、友達はXORを適用する前に、取り決めた値のビットを反転させてしまいました(つまり、取り決めた値にビット単位のNOTを適用しました)。

暗号化された値と取り決めた値を受け取り、元の値を計算するメソッドSecrets.reverse_xorを実装しましょう。

Secrets.reverse_xor(0b1100, 0b0101)
# => 0b(0110)
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Crystal Exercism

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

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