-
-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add secrets exercise for bit manipulation
- Loading branch information
Showing
11 changed files
with
331 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Hints | ||
|
||
## 1. Shift back the bits | ||
- Crystal has an [operator][shifts] for left shifting bits. | ||
|
||
## 2. Apply a bit mask | ||
- Crystal has a [bitwise AND][binary] operator. | ||
|
||
## 3. Set some bits | ||
- Crystal has a [bitwise OR][binary] operator. | ||
|
||
## 4. Reverse XOR | ||
- An XOR can be reversed by applying an XOR on the same value. | ||
- Crystal has operators for [bitwise NOT][not] and bitwise [XOR][xor]. | ||
|
||
[shifts]: https://crystal-lang.org/reference/syntax_and_semantics/operators.html#shifts | ||
[binary]: https://crystal-lang.org/reference/syntax_and_semantics/operators.html#binary | ||
[not]: https://crystal-lang.org/reference/syntax_and_semantics/operators.html#other-unary-operators | ||
[xor]: https://crystal-lang.org/reference/syntax_and_semantics/operators.html#binary |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Instructions | ||
|
||
Your has just sent you a message with an important secret. | ||
Not wanting to make it easy for others to read it, the message has been encrypted using a series of bit manipulations. | ||
You will need to write a program to help decrypt the message. | ||
|
||
## 1. Shift back the bits | ||
|
||
The first step in decrypting the message is to undo the shifting from the encryption process by shifting the bits back to the left. | ||
The number of places to shift can vary between messages. | ||
|
||
Implement the method `Secrets.shift_back` that takes a value and the number of places to shift left. | ||
|
||
```crystal | ||
Secrets.shift_back(0b0001, 2) | ||
# => 0b0100 | ||
``` | ||
|
||
## 2. Apply a bit mask | ||
|
||
The next step is apply a bit mask to extract the value of certain bits. | ||
The mask is applied by performing a bitwise AND between the value and the mask. | ||
|
||
Implement the method `Secrets.apply_mask` that takes a value and applies a mask. | ||
|
||
```crystal | ||
Secrets.apply_mask(0b0110, 0b0101) | ||
# => 0b0100 | ||
``` | ||
|
||
## 3. Set some bits | ||
|
||
Shifting bits to the left has added some new 0 bits. | ||
Some of these new bits need to be set to 1. | ||
The bitwise OR is useful for setting certain bits to 1 while preserving the rest. | ||
|
||
Implement the method `Secrets.set_bits` that takes two values and performs a bitwise OR. | ||
|
||
```crystal | ||
Secrets.set_bits(0b0110, 0b0101) | ||
# => 0b111 | ||
``` | ||
|
||
## 4. Reverse XOR | ||
|
||
Part of the encryption process applies a XOR with an agreed value. | ||
To get back to the original value, the encrypted value can simply be XOR again with the agreed value. | ||
However, due to a misunderstanding, your friend flipped the agreed value's bits (i.e. applied a bitwise NOT to the agreed value) before applying the XOR. | ||
|
||
Implement the `Secrets.reverse_xor` method that takes the encrypted and agreed values and calculates the original value. | ||
|
||
```crystal | ||
Secrets.reverse_xor(0b1100, 0b0101) | ||
# => 0b(0110) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Bit Manipulation | ||
|
||
Crystal has bitwise operators for manipulating [`Integers`][integers] at the binary level. | ||
|
||
## Shift operators | ||
|
||
Crystal has [shift operators][shift] for shifting bits to the left (`<<`) or the right (`>>`). | ||
|
||
### Shift left(`<<`) | ||
|
||
The shift left operator (`<<`) shifts the bits to the left. | ||
The value to shift is specified on the left side and the number of places to shift is on the right. | ||
|
||
```crystal | ||
0b0010 << 1 | ||
# => 0b0100 | ||
0b0010 << 2 | ||
# => 0b1000 | ||
``` | ||
|
||
If the number is negative, it will shift to the right instead. | ||
|
||
```crystal | ||
0b0010 << -1 | ||
# => 0b0001 | ||
``` | ||
|
||
### Shift right(`>>`) | ||
|
||
The shift right operator (`>>`) shifts the bits to the right. | ||
Like the shift left operator, the value to shift is specified on the left and number of places to shift is on the right. | ||
|
||
```crystal | ||
0b0100 >> 1 | ||
# => 0b0010 | ||
0b0100 >> 2 | ||
# => 0b0001 | ||
``` | ||
|
||
And similarly, the operator will shift to the left if the number is negative. | ||
|
||
```crystal | ||
0b0100 >> -1 | ||
# => 0b1000 | ||
``` | ||
|
||
## Binary operators | ||
|
||
Crystal has 3 [binary operators][binary] (`&`, `|`, `^`) and a `~` operator for performing bitwise operations. | ||
|
||
### Bitwise AND(`&`) | ||
|
||
The binary AND operator (`&`) performs a bitwise AND on two values. | ||
It compares each bit in the first value against the bit in the same position in the second value. | ||
The resulting bit is set to 1 if both bits are 1. | ||
Otherwise, it is set to 0. | ||
|
||
```crystal | ||
0b0011 & 0b1010 | ||
# => 0b0010 | ||
``` | ||
|
||
### Bitwise OR(`|`) | ||
|
||
The binary OR operator (`|`) performs a bitwise OR on two values. | ||
It also compares each bit in the first value against the bit in the same position in the second value. | ||
If either bit is 1, the resulting bit is set 1. | ||
Otherwise, it is set to 0. | ||
|
||
```crystal | ||
0b0011 | 0b1010 | ||
# => 0b1011 | ||
``` | ||
|
||
### Bitwise XOR(`^`) | ||
|
||
The binary XOR operator (`^`) performs a bitwise XOR. | ||
Like the bitwise AND and bitwise OR operators, it compares each bit from the first value against the bit in the same position in the second value. | ||
If _only one_ of them is 1, the resulting bit is 1. | ||
Otherwise, it is 0. | ||
|
||
```crystal | ||
0b0011 ^ 0b1010 | ||
# => 0b1001 | ||
``` | ||
|
||
### Bitwise NOT(`~`) | ||
|
||
Lastly, the bitwise NOT operator (`~`) flips each of the value's bits. | ||
Unlike the other binary operators, this is a unary operator, operating on only on the value to the right. | ||
|
||
```crystal | ||
~0b1110_0010 | ||
# => 0b0001_1101 | ||
``` | ||
|
||
[integers]: https://crystal-lang.org/api/Int.html | ||
[shift]: https://crystal-lang.org/reference/syntax_and_semantics/operators.html#shifts | ||
[binary]: https://crystal-lang.org/reference/syntax_and_semantics/operators.html#binary |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"authors": [ | ||
"kahgoh" | ||
], | ||
"files": { | ||
"solution": [ | ||
"src/secrets.cr" | ||
], | ||
"test": [ | ||
"spec/secrets_spec.cr" | ||
], | ||
"exemplar": [ | ||
".meta/src/exemplar.cr" | ||
] | ||
}, | ||
"forked_from": [ | ||
"elixir/secrets" | ||
], | ||
"icon": "secrets", | ||
"blurb": "Learn about bit manipulation by writing a program to decrypt a message." | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
## Goal | ||
|
||
The goal of this exercise is to teach the student about bitwise operations in Crystal. | ||
|
||
## Learning objectives | ||
|
||
- Learn about the bitwise operators <<, >>, &, |, ^ and ~ | ||
|
||
## Concepts | ||
|
||
`bit-operators`: | ||
|
||
- `>>` | ||
- `<<` | ||
- `&` | ||
- `|` | ||
- `^` | ||
- `~` | ||
|
||
## Prerequisites | ||
|
||
- Binary, Octal, and Hexadecimal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module Secrets | ||
def shift_back(value : UInt8, numberOfPlaces : UInt8) : UInt8 | ||
value << numberOfPlaces | ||
end | ||
|
||
def apply_mask(value : UInt8, mask : UInt8) : UInt8 | ||
value & mask | ||
end | ||
|
||
def set_bits(value1 : UInt8, value2 : UInt8) : UInt8 | ||
value1 | value2 | ||
end | ||
|
||
def reverse_xor(value : UInt8, agreedValue : UInt8) : UInt8 | ||
value ^ ~agreedValue | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
require "spec" | ||
require "../src/*" | ||
|
||
include Secrets | ||
|
||
describe "Secrets" do | ||
describe "shift_back" do | ||
it "should be able to shift 0 places" do | ||
shift_back(15, 0).should eq 15 | ||
end | ||
|
||
it "should be able to shift 1 place to the left" do | ||
shift_back(7, 1).should eq 14 | ||
end | ||
|
||
it "should be able to shift 4 places to the left" do | ||
shift_back(5, 4).should eq 80 | ||
end | ||
|
||
it "should be able to shift bits off" do | ||
shift_back(96, 4).should eq 0 | ||
end | ||
end | ||
|
||
describe "apply_mask" do | ||
it "should be able to AND value with mask bits all 1" do | ||
apply_mask(101, 255).should eq 101 | ||
end | ||
|
||
it "should be able to AND value with mask bits all 0" do | ||
apply_mask(101, 0).should eq 0 | ||
end | ||
|
||
it "should be able to AND value with some bits 1" do | ||
apply_mask(62, 85).should eq 20 | ||
end | ||
end | ||
|
||
describe "set_bits" do | ||
it "should be able to OR value with 0s" do | ||
set_bits(107, 0).should eq 107 | ||
end | ||
|
||
it "should be able to OR with with 1s" do | ||
set_bits(107, 255).should eq 255 | ||
end | ||
|
||
it "should be able to set some bits" do | ||
set_bits(62, 85).should eq 127 | ||
end | ||
end | ||
|
||
describe "reverse_xor" do | ||
it "should be able to reverse with all 1s" do | ||
reverse_xor(106, 255).should eq 106 | ||
end | ||
|
||
it "should be able to reverse with all 0s" do | ||
reverse_xor(106, 0).should eq 149 | ||
end | ||
|
||
it "should be able to reverse with mix of 1s and 0s" do | ||
reverse_xor(62, 85).should eq 148 | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module Secrets | ||
def shift_back(value : UInt8, numberOfPlaces : UInt8) : UInt8 | ||
raise "Please implement the Secrets::shift_back method" | ||
end | ||
|
||
def apply_mask(value : UInt8, mask : UInt8) : UInt8 | ||
raise "Please implement the Secrets::apply_mask method" | ||
end | ||
|
||
def set_bits(value1 : UInt8, value2 : UInt8) : UInt8 | ||
raise "Please implement the Secrets::set_bits method" | ||
end | ||
|
||
def reverse_xor(value : UInt8, agreedValue : UInt8) : UInt8 | ||
raise "Please implement the Secrets::reverse_xor method" | ||
end | ||
end |