Some solutions for the julia path
This commit is contained in:
20
julia/secrets/.exercism/config.json
Normal file
20
julia/secrets/.exercism/config.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"authors": [
|
||||
"colinleach"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"secrets.jl"
|
||||
],
|
||||
"test": [
|
||||
"runtests.jl"
|
||||
],
|
||||
"exemplar": [
|
||||
".meta/exemplar.jl"
|
||||
]
|
||||
},
|
||||
"forked_from": [
|
||||
"java/secrets"
|
||||
],
|
||||
"blurb": "Learn about bit manipulation by writing a program to decrypt a message."
|
||||
}
|
||||
1
julia/secrets/.exercism/metadata.json
Normal file
1
julia/secrets/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"julia","exercise":"secrets","id":"3bbfeb59334b4b14a09c7f5a345b04e5","url":"https://exercism.org/tracks/julia/exercises/secrets","handle":"Kimawari","is_requester":true,"auto_approve":false}
|
||||
34
julia/secrets/HELP.md
Normal file
34
julia/secrets/HELP.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests, run this command from within the exercise directory:
|
||||
|
||||
```bash
|
||||
$ julia runtests.jl
|
||||
```
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit secrets.jl` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Julia track's documentation](https://exercism.org/docs/tracks/julia)
|
||||
- The [Julia track's programming category on the forum](https://forum.exercism.org/c/programming/julia)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, we recommend that you submit your code and request mentoring :)
|
||||
|
||||
If you don't want to do that for whatever reason, then you can find the wider Julia community channels [here](https://julialang.org/community/).
|
||||
21
julia/secrets/HINTS.md
Normal file
21
julia/secrets/HINTS.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Hints
|
||||
|
||||
Some (not all) of the tests assume the value is `Int32`, so please avoid forcing it to be anything else.
|
||||
|
||||
## 1. Shift back the bits
|
||||
|
||||
- This is a right-shift.
|
||||
- Note the instruction that the results should be left-filled with zeros.
|
||||
|
||||
## 2. Set some bits
|
||||
|
||||
- Bits are set by bitwise OR with a mask. This is extremely common.
|
||||
|
||||
## 3. Flip specific bits
|
||||
|
||||
- There is an old joke among programmers that cryptographers discovered XOR and forgot to read the rest of the manual.
|
||||
|
||||
## 4. Clear specific bits
|
||||
|
||||
- Simple AND logic will do the opposite of what you need.
|
||||
- How do you flip all the bits in the mask?
|
||||
185
julia/secrets/README.md
Normal file
185
julia/secrets/README.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# Secrets
|
||||
|
||||
Welcome to Secrets on Exercism's Julia Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
|
||||
|
||||
## Introduction
|
||||
|
||||
Binary digits ultimately map directly to the transistors in your CPU or RAM, and whether each is "on" or "off".
|
||||
|
||||
Low-level manipulation, informally called "bit-twiddling", is particularly important in system languages.
|
||||
|
||||
High-level languages like Julia usually abstract away most of this detail.
|
||||
However, a full range of bit-level operations are available in the base language.
|
||||
|
||||
***Note:*** To see human-readable binary output in the REPL, nearly all the examples below need to be wrapped in a `bitstring()` function.
|
||||
This is visually distracting, so most occurrences of this function have been edited out.
|
||||
|
||||
## Bit-shift operations
|
||||
|
||||
Integer types, signed or unsigned, can be represented as a string of 1's and 0's.
|
||||
|
||||
```julia-repl
|
||||
julia> bitstring(UInt8(5))
|
||||
"00000101"
|
||||
```
|
||||
|
||||
Bit-shifts just move everything to the left or right by a specified number of positions.
|
||||
With `UInt` types, some bits drop off one end, and the other end is padded with zeros:
|
||||
|
||||
```julia-repl
|
||||
julia> ux::UInt8 = 5
|
||||
5
|
||||
|
||||
julia> bitstring(ux)
|
||||
"00000101"
|
||||
|
||||
julia> ux << 2 # left by 2
|
||||
"00010100"
|
||||
|
||||
julia> ux >> 1 # right by 1
|
||||
"00000010"
|
||||
```
|
||||
|
||||
Each left-shift doubles the value and each right-shift halves it (subject to truncation).
|
||||
This is more obvious in decimal representation:
|
||||
|
||||
```julia-repl
|
||||
julia> 3 << 2
|
||||
12
|
||||
|
||||
julia> 24 >> 3
|
||||
3
|
||||
```
|
||||
|
||||
Such bit-shifting is much faster than "proper" arithmetic, making the technique very popular in low-level coding.
|
||||
|
||||
With signed integers, we need to be a bit more careful.
|
||||
|
||||
Left shifts are relatively simple:
|
||||
|
||||
```julia-repl
|
||||
julia> sx = Int8(5)
|
||||
5
|
||||
|
||||
julia> sx # positive integer
|
||||
"00000101"
|
||||
|
||||
julia> sx << 2
|
||||
"00010100"
|
||||
|
||||
julia> -sx # negative integer
|
||||
"11111011"
|
||||
|
||||
julia> -sx << 2
|
||||
"11101100"
|
||||
```
|
||||
|
||||
Left-shifting positive signed integers is thus the same as with unsigned integers.
|
||||
|
||||
Negative values are stored in [two's complement][2complement] form, which means that the left-most bit is 1.
|
||||
No problem for a left-shift, but when right-shifting how do we pad the left-most bits?
|
||||
|
||||
```julia-repl
|
||||
julia> sx >> 2 # simple for positive values!
|
||||
"00000001"
|
||||
|
||||
julia> -sx # negative integer
|
||||
"11111011"
|
||||
|
||||
julia> -sx >> 2 # pad with repeated sign bit
|
||||
"11111110"
|
||||
|
||||
julia> -sx >>> 2 # pad with 0
|
||||
"00111110"
|
||||
```
|
||||
|
||||
The `>>` operator performs arithmetic shift, preserving the sign bit.
|
||||
|
||||
The `>>>` operator performs logical shift, padding with zeros as if the number was unsigned.
|
||||
|
||||
## Bitwise logic
|
||||
|
||||
We saw in a previous Concept that the operators `&&` (and), `||` (or) and `!` (not) are used with boolean values.
|
||||
|
||||
There are equivalent operators `&` (bitwise and), `|` (bitwise or) and `~` (a tilde, bitwise not) to compare the bits in two integers.
|
||||
|
||||
```julia-repl
|
||||
julia> 0b1011 & 0b0010 # bit is 1 in both numbers
|
||||
"00000010"
|
||||
|
||||
julia> 0b1011 | 0b0010 # bit is 1 in at least one number
|
||||
"00001011"
|
||||
|
||||
julia> ~0b1011 # flip all bits
|
||||
"11110100"
|
||||
|
||||
julia> xor(0b1011, 0b0010) # bit is 1 in exactly one number, not both
|
||||
"00001001"
|
||||
```
|
||||
|
||||
Here, `xor()` is exclusive-or, used as a function.
|
||||
|
||||
[2complement]: https://en.wikipedia.org/wiki/Two%27s_complement
|
||||
|
||||
## Instructions
|
||||
|
||||
Your friend has just sent you a message with an important secret.
|
||||
Not wanting to make it easy for others to read it, the message was encrypted by performing a series of bit manipulations.
|
||||
You will need to write the functions 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 right.
|
||||
There will be further steps in the decryption process that assume 0s are inserted from the left hand side.
|
||||
|
||||
Implement the `shift_back()` function that takes a value and the number of places to shift and peforms the shift.
|
||||
|
||||
```julia
|
||||
shift_back(0b1001, 2) # => 0b0010
|
||||
```
|
||||
|
||||
## 2. Set some bits
|
||||
|
||||
Next, there are some bits that need to be set to 1.
|
||||
|
||||
Implement the `set_bits()` function that takes a value and a mask and returns the result of setting the bits in value to 1.
|
||||
A bit from `value` should be set to 1 where the bit in the `mask` is also 1.
|
||||
All other bits should be kept unchanged.
|
||||
|
||||
```julia
|
||||
set_bits(0b0110, 0b0101) # => 0b0111
|
||||
```
|
||||
|
||||
## 3. Flip specific bits
|
||||
|
||||
Some bits are flipped during encryption.
|
||||
They will need to be flipped back to decrypt the message.
|
||||
|
||||
Implement the `flip_bits()` function that takes a value and the mask.
|
||||
The mask indicates which bits in the value to flip.
|
||||
If the bit is 1 in `mask`, the bit is flipped in the `value`.
|
||||
All other bits are kept unchanged.
|
||||
|
||||
```julia
|
||||
flip_bits(0b1100, 0b0101) # => 0b1001
|
||||
```
|
||||
|
||||
## 4. Clear specific bits
|
||||
|
||||
Lastly, there are also certain bits that always decrypt to 0.
|
||||
|
||||
Implement the `clear_bits()` function that takes a value and a mask.
|
||||
The bits in the `value` should be set to 0 where the bit in the mask is 1.
|
||||
All other bits should be kept unchanged.
|
||||
|
||||
```julia
|
||||
clear_bits(0b0110, 0b0101) # => 0b0010
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @colinleach
|
||||
30
julia/secrets/runtests.jl
Normal file
30
julia/secrets/runtests.jl
Normal file
@@ -0,0 +1,30 @@
|
||||
using Test
|
||||
|
||||
include("secrets.jl")
|
||||
|
||||
@testset verbose = true "tests" begin
|
||||
|
||||
@testset "1. Shift back the bits" begin
|
||||
@test shift_back(8, 2) == 2
|
||||
|
||||
# The original Java code uses a signed integer, so we use Int32 here
|
||||
# Fails with Int64!
|
||||
@test shift_back(Int32(-2_144_333_657), 3) == 268_829_204
|
||||
end
|
||||
|
||||
@testset "2. Set bits" begin
|
||||
@test set_bits(5, 3) == 7
|
||||
@test set_bits(5_652, 26_150) == 30_262
|
||||
end
|
||||
|
||||
@testset "3. Flip bits" begin
|
||||
@test flip_bits(5, 11) == 14
|
||||
@test flip_bits(38_460, 15_471) == 43_603
|
||||
end
|
||||
|
||||
@testset "4. Clear bits" begin
|
||||
@test clear_bits(5, 11) == 4
|
||||
@test clear_bits(90, 240) == 10
|
||||
end
|
||||
|
||||
end
|
||||
15
julia/secrets/secrets.jl
Normal file
15
julia/secrets/secrets.jl
Normal file
@@ -0,0 +1,15 @@
|
||||
function shift_back(value, amount)
|
||||
return value >>> amount
|
||||
end
|
||||
|
||||
function set_bits(value, mask)
|
||||
return value | mask
|
||||
end
|
||||
|
||||
function flip_bits(value, mask)
|
||||
return value ⊻ mask
|
||||
end
|
||||
|
||||
function clear_bits(value, mask)
|
||||
return value & ~mask
|
||||
end
|
||||
Reference in New Issue
Block a user