秘密

秘密

学習演習

はじめに

ビット操作

Javaには、byte、short、int、long、charのビットを操作するための演算子があります。

シフト演算子

<<を使うとビットを左にシフトでき、>>を使うと右にシフトできます。

// Shift two places to the left
0b0000_1011 << 2;
// # => 0b0010_1100

// Shift two places to the right
0b0000_1011 >> 2;
// # => 0b0000_0010

<<演算子は常に右側に0を挿入します。 ただし、>>は一番左のビットと同じビットを挿入します(数値が負なら1、正なら0)。

// Shift 2 places to the right preserves the sign
// This is a negative value, whose binary representation is
// 1000_0000_0000_0000_0000_0000_0010_0110
int value = -0x7FFFFFDA;

// Shift two places to the right, preserving the sign bit
value >> 2;
// # => 1110_0000_0000_0000_0000_0000_0000_1001

右にシフトするときに0を挿入したい場合は、代わりに>>>を使います。

// Shift two places to the right, inserting 0s on the left
value >>> 2;
// # => 0010_0000_0000_0000_0000_0000_0000_1001

ビット演算

ビット単位のAND

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

0b0110_0101 & 0b0011_1100;
// # => 0b0010_0100
ビット単位のOR

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

0b0110_0101 | 0b0011_1100;
// # => 0b0111_1101
ビット単位のXOR

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

0b0110_0101 ^ 0b0011_1100;
// # => 0b0101_1001
ビット単位のNOT(~)

最後に、ビット単位のNOT演算子(~)は各ビットを反転します。 これまでの演算子とは異なり、これは単項演算子であり、1つの値だけに作用します。

~0b0110_0101;
// # => 0b1001_1010

説明

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

1. ビットをシフトし直す

メッセージを復号する最初のステップは、暗号化の過程で行ったシフトを元に戻すことです。ビットを右にシフトし直します。 このあとの復号のステップでは、左側から0が挿入されることを前提としています。

値とシフトする桁数を受け取り、シフトを実行するSecrets.shiftBackメソッドを実装しましょう。

Secrets.shiftBack(0b1001, 2);
# => 0b0010

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

次に、1に設定する必要があるビットがあります。

値とマスクを受け取り、値のビットを1に設定した結果を返すSecrets.setBitsメソッドを実装しましょう。 マスクのビットが1のところでは、値の対応するビットも1に設定します。 それ以外のビットは変更しません。

Secrets.setBits(0b0110, 0b0101);
# => 0b0111

3. 特定のビットを反転させる

暗号化の際に、いくつかのビットが反転しています。 メッセージを復号するには、それらを反転し直す必要があります。

値とマスクを受け取るSecrets.flipBitsメソッドを実装しましょう。 マスクは、値のどのビットを反転させるかを示します。 マスクのビットが1であれば、値の対応するビットを反転します。 それ以外のビットは変更しません。

Secrets.flipBits(0b1100, 0b0101);
# => 0b1001

4. 特定のビットをクリアする

最後に、復号すると必ず0になるビットもあります。

値とマスクを受け取るSecrets.clearBitsメソッドを実装しましょう。 マスクのビットが1のところでは、valueのビットを0に設定します。 それ以外のビットは変更しません。

Secrets.clearBits(0b0110, 0b0101);
# => 0b0010
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Java Exercism

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

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