From e0d3380ea0fffe7e75415b9398904d3d7924c505 Mon Sep 17 00:00:00 2001 From: Eric Willigers Date: Thu, 20 Jun 2024 19:37:06 +1000 Subject: [PATCH] Add atbash-cipher exercise --- config.json | 8 +++ .../atbash-cipher/.docs/instructions.md | 27 ++++++++ .../practice/atbash-cipher/.meta/config.json | 19 ++++++ .../practice/atbash-cipher/.meta/tests.toml | 52 ++++++++++++++++ exercises/practice/atbash-cipher/dub.sdl | 2 + .../atbash-cipher/example/atbash_cipher.d | 38 ++++++++++++ .../atbash-cipher/source/atbash_cipher.d | 61 +++++++++++++++++++ 7 files changed, 207 insertions(+) create mode 100644 exercises/practice/atbash-cipher/.docs/instructions.md create mode 100644 exercises/practice/atbash-cipher/.meta/config.json create mode 100644 exercises/practice/atbash-cipher/.meta/tests.toml create mode 100644 exercises/practice/atbash-cipher/dub.sdl create mode 100644 exercises/practice/atbash-cipher/example/atbash_cipher.d create mode 100644 exercises/practice/atbash-cipher/source/atbash_cipher.d diff --git a/config.json b/config.json index 616b3ff..eecda5b 100644 --- a/config.json +++ b/config.json @@ -462,6 +462,14 @@ "string_manipulation" ] }, + { + "slug": "atbash-cipher", + "name": "Atbash Cipher", + "uuid": "c845c319-60f8-409d-88a6-84a7c529eaf7", + "practices": [], + "prerequisites": [], + "difficulty": 4 + }, { "slug": "circular-buffer", "name": "Circular Buffer", diff --git a/exercises/practice/atbash-cipher/.docs/instructions.md b/exercises/practice/atbash-cipher/.docs/instructions.md new file mode 100644 index 0000000..21ca2ce --- /dev/null +++ b/exercises/practice/atbash-cipher/.docs/instructions.md @@ -0,0 +1,27 @@ +# Instructions + +Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East. + +The Atbash cipher is a simple substitution cipher that relies on transposing all the letters in the alphabet such that the resulting alphabet is backwards. +The first letter is replaced with the last letter, the second with the second-last, and so on. + +An Atbash cipher for the Latin alphabet would be as follows: + +```text +Plain: abcdefghijklmnopqrstuvwxyz +Cipher: zyxwvutsrqponmlkjihgfedcba +``` + +It is a very weak cipher because it only has one possible key, and it is a simple mono-alphabetic substitution cipher. +However, this may not have been an issue in the cipher's time. + +Ciphertext is written out in groups of fixed length, the traditional group size being 5 letters, leaving numbers unchanged, and punctuation is excluded. +This is to make it harder to guess things based on word boundaries. +All text will be encoded as lowercase letters. + +## Examples + +- Encoding `test` gives `gvhg` +- Encoding `x123 yes` gives `c123b vh` +- Decoding `gvhg` gives `test` +- Decoding `gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt` gives `thequickbrownfoxjumpsoverthelazydog` diff --git a/exercises/practice/atbash-cipher/.meta/config.json b/exercises/practice/atbash-cipher/.meta/config.json new file mode 100644 index 0000000..ec72cee --- /dev/null +++ b/exercises/practice/atbash-cipher/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "source/atbash_cipher.d" + ], + "test": [ + "source/atbash_cipher.d" + ], + "example": [ + "example/atbash_cipher.d" + ] + }, + "blurb": "Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Atbash" +} diff --git a/exercises/practice/atbash-cipher/.meta/tests.toml b/exercises/practice/atbash-cipher/.meta/tests.toml new file mode 100644 index 0000000..c082d07 --- /dev/null +++ b/exercises/practice/atbash-cipher/.meta/tests.toml @@ -0,0 +1,52 @@ +# 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. + +[2f47ebe1-eab9-4d6b-b3c6-627562a31c77] +description = "encode -> encode yes" + +[b4ffe781-ea81-4b74-b268-cc58ba21c739] +description = "encode -> encode no" + +[10e48927-24ab-4c4d-9d3f-3067724ace00] +description = "encode -> encode OMG" + +[d59b8bc3-509a-4a9a-834c-6f501b98750b] +description = "encode -> encode spaces" + +[31d44b11-81b7-4a94-8b43-4af6a2449429] +description = "encode -> encode mindblowingly" + +[d503361a-1433-48c0-aae0-d41b5baa33ff] +description = "encode -> encode numbers" + +[79c8a2d5-0772-42d4-b41b-531d0b5da926] +description = "encode -> encode deep thought" + +[9ca13d23-d32a-4967-a1fd-6100b8742bab] +description = "encode -> encode all the letters" + +[bb50e087-7fdf-48e7-9223-284fe7e69851] +description = "decode -> decode exercism" + +[ac021097-cd5d-4717-8907-b0814b9e292c] +description = "decode -> decode a sentence" + +[18729de3-de74-49b8-b68c-025eaf77f851] +description = "decode -> decode numbers" + +[0f30325f-f53b-415d-ad3e-a7a4f63de034] +description = "decode -> decode all the letters" + +[39640287-30c6-4c8c-9bac-9d613d1a5674] +description = "decode -> decode with too many spaces" + +[b34edf13-34c0-49b5-aa21-0768928000d5] +description = "decode -> decode with no spaces" diff --git a/exercises/practice/atbash-cipher/dub.sdl b/exercises/practice/atbash-cipher/dub.sdl new file mode 100644 index 0000000..470b0fe --- /dev/null +++ b/exercises/practice/atbash-cipher/dub.sdl @@ -0,0 +1,2 @@ +name "atbash-cipher" +buildRequirements "disallowDeprecations" diff --git a/exercises/practice/atbash-cipher/example/atbash_cipher.d b/exercises/practice/atbash-cipher/example/atbash_cipher.d new file mode 100644 index 0000000..1205ab8 --- /dev/null +++ b/exercises/practice/atbash-cipher/example/atbash_cipher.d @@ -0,0 +1,38 @@ +module atbash_cipher; + +import std.ascii : isAlphaNum, isDigit, toLower; + +pure string encode(immutable string phrase) +{ + size_t nextSpace = 5; + string result; + foreach (dchar c; phrase) { + if (!isAlphaNum(c)) { + continue; + } + if (result.length == nextSpace) { + result ~= ' '; + nextSpace += 6; + } + if (!isDigit(c)) { + c = 'a' + 'z' - toLower(c); + } + result ~= c; + } + return result; +} + +pure string decode(immutable string phrase) +{ + string result; + foreach (dchar c; phrase) { + if (c == ' ') { + continue; + } + if (!isDigit(c)) { + c = 'a' + 'z' - c; + } + result ~= c; + } + return result; +} diff --git a/exercises/practice/atbash-cipher/source/atbash_cipher.d b/exercises/practice/atbash-cipher/source/atbash_cipher.d new file mode 100644 index 0000000..ce706d5 --- /dev/null +++ b/exercises/practice/atbash-cipher/source/atbash_cipher.d @@ -0,0 +1,61 @@ +module atbash_cipher; + +pure string encode(immutable string phrase) +{ + // implement this function +} + +pure string decode(immutable string phrase) +{ + // implement this function +} + +unittest +{ + immutable int allTestsEnabled = 0; + + // Encode yes + assert(encode("yes") == "bvh"); + + static if (allTestsEnabled) + { + // Encode no + assert(encode("no") == "ml"); + + // Encode OMG + assert(encode("OMG") == "lnt"); + + // Encode spaces + assert(encode("O M G") == "lnt"); + + // Encode mindblowingly + assert(encode("mindblowingly") == "nrmwy oldrm tob"); + + // Encode numbers + assert(encode("Testing,1 2 3, testing.") == "gvhgr mt123 gvhgr mt"); + + // Encode deep thought + assert(encode("Truth is fiction.") == "gifgs rhurx grlm"); + + // Encode all the letters + assert(encode("The quick brown fox jumps over the lazy dog.") == "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt"); + + // Decode exercism + assert(decode("vcvix rhn") == "exercism"); + + // Decode a sentence + assert(decode("zmlyh gzxov rhlug vmzhg vkkrm thglm v") == "anobstacleisoftenasteppingstone"); + + // Decode numbers + assert(decode("gvhgr mt123 gvhgr mt") == "testing123testing"); + + // Decode all the letters + assert(decode("gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt") == "thequickbrownfoxjumpsoverthelazydog"); + + // Decode with too many spaces + assert(decode("vc vix r hn") == "exercism"); + + // Decode with no spaces + assert(decode("zmlyhgzxovrhlugvmzhgvkkrmthglmv") == "anobstacleisoftenasteppingstone"); + } +}