Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
241 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"track":"elixir","exercise":"rotational-cipher","id":"138e013b55404c058e2011d383b14c1d","url":"https://exercism.io/my/solutions/138e013b55404c058e2011d383b14c1d","handle":"jnaomi","is_requester":true,"auto_approve":false} |
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,4 @@ | ||
# Used by "mix format" | ||
[ | ||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] | ||
] |
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,24 @@ | ||
# The directory Mix will write compiled artifacts to. | ||
/_build/ | ||
|
||
# If you run "mix test --cover", coverage assets end up here. | ||
/cover/ | ||
|
||
# The directory Mix downloads your dependencies sources to. | ||
/deps/ | ||
|
||
# Where third-party dependencies like ExDoc output generated docs. | ||
/doc/ | ||
|
||
# Ignore .fetch files in case you like to edit your project deps locally. | ||
/.fetch | ||
|
||
# If the VM crashes, it generates a dump, let's ignore it too. | ||
erl_crash.dump | ||
|
||
# Also ignore archive artifacts (built via "mix archive.build"). | ||
*.ez | ||
|
||
# Ignore package tarball (built via "mix hex.build"). | ||
rotational_cipher-*.tar | ||
|
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,73 @@ | ||
# Rotational Cipher | ||
|
||
Create an implementation of the rotational cipher, also sometimes called the Caesar cipher. | ||
|
||
The Caesar cipher is a simple shift cipher that relies on | ||
transposing all the letters in the alphabet using an integer key | ||
between `0` and `26`. Using a key of `0` or `26` will always yield | ||
the same output due to modular arithmetic. The letter is shifted | ||
for as many values as the value of the key. | ||
|
||
The general notation for rotational ciphers is `ROT + <key>`. | ||
The most commonly used rotational cipher is `ROT13`. | ||
|
||
A `ROT13` on the Latin alphabet would be as follows: | ||
|
||
```text | ||
Plain: abcdefghijklmnopqrstuvwxyz | ||
Cipher: nopqrstuvwxyzabcdefghijklm | ||
``` | ||
|
||
It is stronger than the Atbash cipher because it has 27 possible keys, and 25 usable keys. | ||
|
||
Ciphertext is written out in the same formatting as the input including spaces and punctuation. | ||
|
||
## Examples | ||
|
||
- ROT5 `omg` gives `trl` | ||
- ROT0 `c` gives `c` | ||
- ROT26 `Cool` gives `Cool` | ||
- ROT13 `The quick brown fox jumps over the lazy dog.` gives `Gur dhvpx oebja sbk whzcf bire gur ynml qbt.` | ||
- ROT13 `Gur dhvpx oebja sbk whzcf bire gur ynml qbt.` gives `The quick brown fox jumps over the lazy dog.` | ||
|
||
## Running tests | ||
|
||
Execute the tests with: | ||
|
||
```bash | ||
$ mix test | ||
``` | ||
|
||
### Pending tests | ||
|
||
In the test suites, all but the first test have been skipped. | ||
|
||
Once you get a test passing, you can unskip the next one by | ||
commenting out the relevant `@tag :pending` with a `#` symbol. | ||
|
||
For example: | ||
|
||
```elixir | ||
# @tag :pending | ||
test "shouting" do | ||
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!" | ||
end | ||
``` | ||
|
||
Or, you can enable all the tests by commenting out the | ||
`ExUnit.configure` line in the test suite. | ||
|
||
```elixir | ||
# ExUnit.configure exclude: :pending, trace: true | ||
``` | ||
|
||
If you're stuck on something, it may help to look at some of | ||
the [available resources](https://exercism.io/tracks/elixir/resources) | ||
out there where answers might be found. | ||
|
||
## Source | ||
|
||
Wikipedia [https://en.wikipedia.org/wiki/Caesar_cipher](https://en.wikipedia.org/wiki/Caesar_cipher) | ||
|
||
## Submitting Incomplete Solutions | ||
It's possible to submit an incomplete solution so you can see how others have completed the exercise. |
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,33 @@ | ||
defmodule RotationalCipher do | ||
@doc """ | ||
Given a plaintext and amount to shift by, return a rotated string. | ||
Example: | ||
iex> RotationalCipher.rotate("Attack at dawn", 13) | ||
"Nggnpx ng qnja" | ||
""" | ||
@letters "abcdefghijklmnopqrstuvwxyz" | ||
@capital "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
|
||
@spec rotate(text :: String.t(), shift :: integer) :: String.t() | ||
def rotate(text, shift) do | ||
text | ||
|> String.graphemes | ||
|> Enum.map(fn x -> | ||
cond do | ||
String.contains?(@letters, x) -> rotate_element(@letters, x, shift) | ||
String.contains?(@capital, x) -> rotate_element(@capital, x, shift) | ||
true -> x | ||
end | ||
end) | ||
|> Enum.join | ||
|
||
end | ||
|
||
def rotate_element(alphabet, element, shift) do | ||
{el_idx, _} = :binary.match(alphabet, element) | ||
new_idx = rem(el_idx + shift, alphabet |> String.length) | ||
|
||
String.at(alphabet, new_idx) | ||
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,28 @@ | ||
defmodule RotationalCipher.MixProject do | ||
use Mix.Project | ||
|
||
def project do | ||
[ | ||
app: :rotational_cipher, | ||
version: "0.1.0", | ||
# elixir: "~> 1.8", | ||
start_permanent: Mix.env() == :prod, | ||
deps: deps() | ||
] | ||
end | ||
|
||
# Run "mix help compile.app" to learn about applications. | ||
def application do | ||
[ | ||
extra_applications: [:logger] | ||
] | ||
end | ||
|
||
# Run "mix help deps" to learn about dependencies. | ||
defp deps do | ||
[ | ||
# {:dep_from_hexpm, "~> 0.3.0"}, | ||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} | ||
] | ||
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,75 @@ | ||
defmodule RotationalCipherTest do | ||
use ExUnit.Case | ||
|
||
# @tag :pending | ||
test "rotate a by 1" do | ||
plaintext = "a" | ||
shift = 1 | ||
assert RotationalCipher.rotate(plaintext, shift) == "b" | ||
end | ||
|
||
# @tag :pending | ||
test "rotate a by 26, same output as input" do | ||
plaintext = "a" | ||
shift = 26 | ||
assert RotationalCipher.rotate(plaintext, shift) == "a" | ||
end | ||
|
||
# @tag :pending | ||
test "rotate a by 0, same output as input" do | ||
plaintext = "a" | ||
shift = 0 | ||
assert RotationalCipher.rotate(plaintext, shift) == "a" | ||
end | ||
|
||
# @tag :pending | ||
test "rotate m by 13" do | ||
plaintext = "m" | ||
shift = 13 | ||
assert RotationalCipher.rotate(plaintext, shift) == "z" | ||
end | ||
|
||
# @tag :pending | ||
test "rotate n by 13 with wrap around alphabet" do | ||
plaintext = "n" | ||
shift = 13 | ||
assert RotationalCipher.rotate(plaintext, shift) == "a" | ||
end | ||
|
||
# @tag :pending | ||
test "rotate capital letters" do | ||
plaintext = "OMG" | ||
shift = 5 | ||
assert RotationalCipher.rotate(plaintext, shift) == "TRL" | ||
end | ||
|
||
# @tag :pending | ||
test "rotate spaces" do | ||
plaintext = "O M G" | ||
shift = 5 | ||
assert RotationalCipher.rotate(plaintext, shift) == "T R L" | ||
end | ||
|
||
# @tag :pending | ||
test "rotate numbers" do | ||
plaintext = "Testing 1 2 3 testing" | ||
shift = 4 | ||
assert RotationalCipher.rotate(plaintext, shift) == "Xiwxmrk 1 2 3 xiwxmrk" | ||
end | ||
|
||
# @tag :pending | ||
test "rotate punctuation" do | ||
plaintext = "Let's eat, Grandma!" | ||
shift = 21 | ||
assert RotationalCipher.rotate(plaintext, shift) == "Gzo'n zvo, Bmviyhv!" | ||
end | ||
|
||
# @tag :pending | ||
test "rotate all letters" do | ||
plaintext = "The quick brown fox jumps over the lazy dog." | ||
shift = 13 | ||
|
||
assert RotationalCipher.rotate(plaintext, shift) == | ||
"Gur dhvpx oebja sbk whzcf bire gur ynml qbt." | ||
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,2 @@ | ||
ExUnit.start() | ||
ExUnit.configure(exclude: :pending, trace: true) |