From 45111716bb24220891715f49e108c6e1d3c8f56b Mon Sep 17 00:00:00 2001 From: Jie Date: Fri, 30 Aug 2024 12:19:10 +0200 Subject: [PATCH] Add new practice exercise `rotational-cipher` (#707) --- config.json | 12 ++++ .../rotational-cipher/.docs/instructions.md | 29 +++++++++ .../rotational-cipher/.meta/config.json | 19 ++++++ .../.meta/src/RotationalCipher.example.elm | 31 ++++++++++ .../rotational-cipher/.meta/tests.toml | 40 ++++++++++++ exercises/practice/rotational-cipher/elm.json | 29 +++++++++ .../src/RotationalCipher.elm | 6 ++ .../rotational-cipher/tests/Tests.elm | 61 +++++++++++++++++++ 8 files changed, 227 insertions(+) create mode 100644 exercises/practice/rotational-cipher/.docs/instructions.md create mode 100644 exercises/practice/rotational-cipher/.meta/config.json create mode 100644 exercises/practice/rotational-cipher/.meta/src/RotationalCipher.example.elm create mode 100644 exercises/practice/rotational-cipher/.meta/tests.toml create mode 100644 exercises/practice/rotational-cipher/elm.json create mode 100644 exercises/practice/rotational-cipher/src/RotationalCipher.elm create mode 100644 exercises/practice/rotational-cipher/tests/Tests.elm diff --git a/config.json b/config.json index c923d31b..94eab478 100644 --- a/config.json +++ b/config.json @@ -1352,6 +1352,18 @@ "custom-types" ], "difficulty": 4 + }, + { + "slug": "rotational-cipher", + "name": "Rotational Cipher", + "uuid": "dd371b3e-666c-4015-a618-df53ad94014d", + "practices": [], + "prerequisites": [ + "strings", + "comparison", + "lists" + ], + "difficulty": 3 } ] }, diff --git a/exercises/practice/rotational-cipher/.docs/instructions.md b/exercises/practice/rotational-cipher/.docs/instructions.md new file mode 100644 index 00000000..4bf64ca1 --- /dev/null +++ b/exercises/practice/rotational-cipher/.docs/instructions.md @@ -0,0 +1,29 @@ +# Instructions + +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 + `. +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.` diff --git a/exercises/practice/rotational-cipher/.meta/config.json b/exercises/practice/rotational-cipher/.meta/config.json new file mode 100644 index 00000000..8db453f5 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "jiegillet" + ], + "files": { + "solution": [ + "src/RotationalCipher.elm" + ], + "test": [ + "tests/Tests.elm" + ], + "example": [ + ".meta/src/RotationalCipher.example.elm" + ] + }, + "blurb": "Create an implementation of the rotational cipher, also sometimes called the Caesar cipher.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Caesar_cipher" +} diff --git a/exercises/practice/rotational-cipher/.meta/src/RotationalCipher.example.elm b/exercises/practice/rotational-cipher/.meta/src/RotationalCipher.example.elm new file mode 100644 index 00000000..5fd13404 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/src/RotationalCipher.example.elm @@ -0,0 +1,31 @@ +module RotationalCipher exposing (rotate) + +import Char + + +rotate : String -> Int -> String +rotate text shiftKey = + text + |> String.toList + |> List.map (shiftChar shiftKey) + |> String.fromList + + +shiftChar : Int -> Char -> Char +shiftChar shiftKey char = + let + shift refCode = + (Char.toCode char - refCode) + |> (+) shiftKey + |> modBy 26 + |> (+) refCode + |> Char.fromCode + in + if 'a' <= char && char <= 'z' then + shift (Char.toCode 'a') + + else if 'A' <= char && char <= 'Z' then + shift (Char.toCode 'A') + + else + char diff --git a/exercises/practice/rotational-cipher/.meta/tests.toml b/exercises/practice/rotational-cipher/.meta/tests.toml new file mode 100644 index 00000000..53441ed2 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/tests.toml @@ -0,0 +1,40 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[74e58a38-e484-43f1-9466-877a7515e10f] +description = "rotate a by 0, same output as input" + +[7ee352c6-e6b0-4930-b903-d09943ecb8f5] +description = "rotate a by 1" + +[edf0a733-4231-4594-a5ee-46a4009ad764] +description = "rotate a by 26, same output as input" + +[e3e82cb9-2a5b-403f-9931-e43213879300] +description = "rotate m by 13" + +[19f9eb78-e2ad-4da4-8fe3-9291d47c1709] +description = "rotate n by 13 with wrap around alphabet" + +[a116aef4-225b-4da9-884f-e8023ca6408a] +description = "rotate capital letters" + +[71b541bb-819c-4dc6-a9c3-132ef9bb737b] +description = "rotate spaces" + +[ef32601d-e9ef-4b29-b2b5-8971392282e6] +description = "rotate numbers" + +[32dd74f6-db2b-41a6-b02c-82eb4f93e549] +description = "rotate punctuation" + +[9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9] +description = "rotate all letters" diff --git a/exercises/practice/rotational-cipher/elm.json b/exercises/practice/rotational-cipher/elm.json new file mode 100644 index 00000000..22c9e137 --- /dev/null +++ b/exercises/practice/rotational-cipher/elm.json @@ -0,0 +1,29 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/core": "1.0.5", + "elm/json": "1.1.3", + "elm/parser": "1.1.0", + "elm/random": "1.0.0", + "elm/regex": "1.0.0", + "elm/time": "1.0.0" + }, + "indirect": {} + }, + "test-dependencies": { + "direct": { + "elm-explorations/test": "2.1.0", + "rtfeldman/elm-iso8601-date-strings": "1.1.4" + }, + "indirect": { + "elm/bytes": "1.0.8", + "elm/html": "1.0.0", + "elm/virtual-dom": "1.0.3" + } + } +} diff --git a/exercises/practice/rotational-cipher/src/RotationalCipher.elm b/exercises/practice/rotational-cipher/src/RotationalCipher.elm new file mode 100644 index 00000000..059ca123 --- /dev/null +++ b/exercises/practice/rotational-cipher/src/RotationalCipher.elm @@ -0,0 +1,6 @@ +module RotationalCipher exposing (rotate) + + +rotate : String -> Int -> String +rotate text shiftKey = + Debug.todo "Please implement rotate" diff --git a/exercises/practice/rotational-cipher/tests/Tests.elm b/exercises/practice/rotational-cipher/tests/Tests.elm new file mode 100644 index 00000000..3b03cb4b --- /dev/null +++ b/exercises/practice/rotational-cipher/tests/Tests.elm @@ -0,0 +1,61 @@ +module Tests exposing (tests) + +import Expect +import RotationalCipher +import Test exposing (Test, describe, skip, test) + + +tests : Test +tests = + describe "RotationalCipher" + [ -- skip <| + test "rotate a by 0, same output as input" <| + \() -> + RotationalCipher.rotate "a" 0 + |> Expect.equal "a" + , skip <| + test "rotate a by 1" <| + \() -> + RotationalCipher.rotate "a" 1 + |> Expect.equal "b" + , skip <| + test "rotate a by 26, same output as input" <| + \() -> + RotationalCipher.rotate "a" 26 + |> Expect.equal "a" + , skip <| + test "rotate m by 13" <| + \() -> + RotationalCipher.rotate "m" 13 + |> Expect.equal "z" + , skip <| + test "rotate n by 13 with wrap around alphabet" <| + \() -> + RotationalCipher.rotate "n" 13 + |> Expect.equal "a" + , skip <| + test "rotate capital letters" <| + \() -> + RotationalCipher.rotate "OMG" 5 + |> Expect.equal "TRL" + , skip <| + test "rotate spaces" <| + \() -> + RotationalCipher.rotate "O M G" 5 + |> Expect.equal "T R L" + , skip <| + test "rotate numbers" <| + \() -> + RotationalCipher.rotate "Testing 1 2 3 testing" 4 + |> Expect.equal "Xiwxmrk 1 2 3 xiwxmrk" + , skip <| + test "rotate punctuation" <| + \() -> + RotationalCipher.rotate "Let's eat, Grandma!" 21 + |> Expect.equal "Gzo'n zvo, Bmviyhv!" + , skip <| + test "rotate all letters" <| + \() -> + RotationalCipher.rotate "The quick brown fox jumps over the lazy dog." 13 + |> Expect.equal "Gur dhvpx oebja sbk whzcf bire gur ynml qbt." + ]