From 5e6369abe162d466f53438e794a883d7854b4e09 Mon Sep 17 00:00:00 2001 From: Andrei Galusca Date: Tue, 23 May 2023 11:00:33 +0300 Subject: [PATCH 1/2] atbash-cipher: implement exercise --- config.json | 8 ++ .../atbash-cipher/.docs/instructions.md | 27 ++++++ .../practice/atbash-cipher/.meta/config.json | 19 ++++ .../.meta/examples/atbashCipher.example.u | 29 +++++++ .../atbash-cipher/.meta/testAnnotation.json | 58 +++++++++++++ .../atbash-cipher/.meta/testLoader.md | 9 ++ .../practice/atbash-cipher/.meta/tests.toml | 52 +++++++++++ .../atbash-cipher/atbashCipher.test.u | 87 +++++++++++++++++++ .../practice/atbash-cipher/atbashCipher.u | 6 ++ 9 files changed, 295 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/examples/atbashCipher.example.u create mode 100644 exercises/practice/atbash-cipher/.meta/testAnnotation.json create mode 100644 exercises/practice/atbash-cipher/.meta/testLoader.md create mode 100644 exercises/practice/atbash-cipher/.meta/tests.toml create mode 100644 exercises/practice/atbash-cipher/atbashCipher.test.u create mode 100644 exercises/practice/atbash-cipher/atbashCipher.u diff --git a/config.json b/config.json index 9e3dba8..bb88785 100644 --- a/config.json +++ b/config.json @@ -376,6 +376,14 @@ "practices": [], "prerequisites": [], "difficulty": 1 + }, + { + "slug": "atbash-cipher", + "name": "Atbash-Cipher", + "uuid": "660bfdb0-dd6d-494b-8a15-070f6dbe233b", + "practices": [], + "prerequisites": [], + "difficulty": 1 } ] }, 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..90ce7c0 --- /dev/null +++ b/exercises/practice/atbash-cipher/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "dreig" + ], + "files": { + "solution": [ + "atbashCipher.u" + ], + "test": [ + "atbashCipher.test.u" + ], + "example": [ + ".meta/examples/atbashCipher.example.u" + ] + }, + "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/examples/atbashCipher.example.u b/exercises/practice/atbash-cipher/.meta/examples/atbashCipher.example.u new file mode 100644 index 0000000..bb600ce --- /dev/null +++ b/exercises/practice/atbash-cipher/.meta/examples/atbashCipher.example.u @@ -0,0 +1,29 @@ +atbashCipher.encodeSingle : Char -> Char +atbashCipher.encodeSingle c = Map.get c mapping |> Optional.getOrElse c + +atbashCipher.mapping : Map Char Char +atbashCipher.mapping = + use Char rangeClosed + List.zip (rangeClosed ?a ?z) (rangeClosed ?a ?z |> List.reverse) + |> Map.fromList + +atbashCipher.encode : Text -> Text +atbashCipher.encode input = + use List map + toCharList input + |> List.filter isAlphaNum + |> map ascii.toLower + |> map encodeSingle + |> List.chunk 5 + |> map fromCharList + |> Text.join " " + +atbashCipher.decode : Text -> Text +atbashCipher.decode input = + use List map + toCharList input + |> List.filter isAlphaNum + |> map ascii.toLower + |> map encodeSingle + |> fromCharList + diff --git a/exercises/practice/atbash-cipher/.meta/testAnnotation.json b/exercises/practice/atbash-cipher/.meta/testAnnotation.json new file mode 100644 index 0000000..42be5cf --- /dev/null +++ b/exercises/practice/atbash-cipher/.meta/testAnnotation.json @@ -0,0 +1,58 @@ +[ + { + "test_code": "atbashCipher.test.ex1 = let\n actual = encode \"yes\"\n expected = \"bvh\"\n Test.label \"encode yes\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex1" + }, + { + "test_code": "atbashCipher.test.ex2 = let\n actual = encode \"no\"\n expected = \"ml\"\n Test.label \"encode no\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex2" + }, + { + "test_code": "atbashCipher.test.ex3 = let\n actual = encode \"OMG\"\n expected = \"lnt\"\n Test.label \"encode OMG\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex3" + }, + { + "test_code": "atbashCipher.test.ex4 = let\n actual = encode \"O M G\"\n expected = \"lnt\"\n Test.label \"encode spaces\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex4" + }, + { + "test_code": "atbashCipher.test.ex5 = let\n actual = encode \"mindblowingly\"\n expected = \"nrmwy oldrm tob\"\n Test.label \"encode mindblowingly\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex5" + }, + { + "test_code": "atbashCipher.test.ex6 = let\n actual = encode \"Testing,1 2 3, testing.\"\n expected = \"gvhgr mt123 gvhgr mt\"\n Test.label \"encode numbers\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex6" + }, + { + "test_code": "atbashCipher.test.ex7 = let\n actual = encode \"Truth is fiction.\"\n expected = \"gifgs rhurx grlm\"\n Test.label \"encode deep thought\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex7" + }, + { + "test_code": "atbashCipher.test.ex8 = let\n actual = encode \"The quick brown fox jumps over the lazy dog.\"\n expected = \"gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt\"\n Test.label \"encode all the letters\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex8" + }, + { + "test_code": "atbashCipher.test.ex9 = let\n actual = decode \"vcvix rhn\"\n expected = \"exercism\"\n Test.label \"decode exercism\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex9" + }, + { + "test_code": "atbashCipher.test.ex10 = let\n actual = decode \"zmlyh gzxov rhlug vmzhg vkkrm thglm v\"\n expected = \"anobstacleisoftenasteppingstone\"\n Test.label \"decode a sentence\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex10" + }, + { + "test_code": "atbashCipher.test.ex11 = let\n actual = decode \"gvhgr mt123 gvhgr mt\"\n expected = \"testing123testing\"\n Test.label \"decode numbers\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex11" + }, + { + "test_code": "atbashCipher.test.ex12 = let\n actual = decode \"gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt\"\n expected = \"thequickbrownfoxjumpsoverthelazydog\"\n Test.label \"decode all the letters\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex12" + }, + { + "test_code": "atbashCipher.test.ex13 = let\n actual = decode \"vc vix r hn\"\n expected = \"exercism\"\n Test.label \"decode with too many spaces\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex13" + }, + { + "test_code": "atbashCipher.test.ex14 = let\n actual = decode \"zmlyhgzxovrhlugvmzhgvkkrmthglmv\"\n expected = \"anobstacleisoftenasteppingstone\"\n Test.label \"decode with no spaces\" <| Test.expect (actual == expected)", + "name": "atbashCipher.test.ex14" + } +] diff --git a/exercises/practice/atbash-cipher/.meta/testLoader.md b/exercises/practice/atbash-cipher/.meta/testLoader.md new file mode 100644 index 0000000..eb030a2 --- /dev/null +++ b/exercises/practice/atbash-cipher/.meta/testLoader.md @@ -0,0 +1,9 @@ +# Testing transcript for atbash-cipher exercise + +```ucm +.> load ./atbashCipher.u +.> add +.> load ./atbashCipher.test.u +.> add +.> move.term atbashCipher.tests tests +``` 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/atbashCipher.test.u b/exercises/practice/atbash-cipher/atbashCipher.test.u new file mode 100644 index 0000000..549aa74 --- /dev/null +++ b/exercises/practice/atbash-cipher/atbashCipher.test.u @@ -0,0 +1,87 @@ +atbashCipher.test.ex1 = let + actual = encode "yes" + expected = "bvh" + Test.label "encode yes" <| Test.expect (actual == expected) + +atbashCipher.test.ex2 = let + actual = encode "no" + expected = "ml" + Test.label "encode no" <| Test.expect (actual == expected) + +atbashCipher.test.ex3 = let + actual = encode "OMG" + expected = "lnt" + Test.label "encode OMG" <| Test.expect (actual == expected) + +atbashCipher.test.ex4 = let + actual = encode "O M G" + expected = "lnt" + Test.label "encode spaces" <| Test.expect (actual == expected) + +atbashCipher.test.ex5 = let + actual = encode "mindblowingly" + expected = "nrmwy oldrm tob" + Test.label "encode mindblowingly" <| Test.expect (actual == expected) + +atbashCipher.test.ex6 = let + actual = encode "Testing,1 2 3, testing." + expected = "gvhgr mt123 gvhgr mt" + Test.label "encode numbers" <| Test.expect (actual == expected) + +atbashCipher.test.ex7 = let + actual = encode "Truth is fiction." + expected = "gifgs rhurx grlm" + Test.label "encode deep thought" <| Test.expect (actual == expected) + +atbashCipher.test.ex8 = let + actual = encode "The quick brown fox jumps over the lazy dog." + expected = "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt" + Test.label "encode all the letters" <| Test.expect (actual == expected) + +atbashCipher.test.ex9 = let + actual = decode "vcvix rhn" + expected = "exercism" + Test.label "decode exercism" <| Test.expect (actual == expected) + +atbashCipher.test.ex10 = let + actual = decode "zmlyh gzxov rhlug vmzhg vkkrm thglm v" + expected = "anobstacleisoftenasteppingstone" + Test.label "decode a sentence" <| Test.expect (actual == expected) + +atbashCipher.test.ex11 = let + actual = decode "gvhgr mt123 gvhgr mt" + expected = "testing123testing" + Test.label "decode numbers" <| Test.expect (actual == expected) + +atbashCipher.test.ex12 = let + actual = decode "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt" + expected = "thequickbrownfoxjumpsoverthelazydog" + Test.label "decode all the letters" <| Test.expect (actual == expected) + +atbashCipher.test.ex13 = let + actual = decode "vc vix r hn" + expected = "exercism" + Test.label "decode with too many spaces" <| Test.expect (actual == expected) + +atbashCipher.test.ex14 = let + actual = decode "zmlyhgzxovrhlugvmzhgvkkrmthglmv" + expected = "anobstacleisoftenasteppingstone" + Test.label "decode with no spaces" <| Test.expect (actual == expected) + +test> atbashCipher.tests = runAll [ + atbashCipher.test.ex1, + atbashCipher.test.ex2, + atbashCipher.test.ex3, + atbashCipher.test.ex4, + atbashCipher.test.ex5, + atbashCipher.test.ex6, + atbashCipher.test.ex7, + atbashCipher.test.ex8, + atbashCipher.test.ex9, + atbashCipher.test.ex10, + atbashCipher.test.ex11, + atbashCipher.test.ex12, + atbashCipher.test.ex13, + atbashCipher.test.ex14, +] + diff --git a/exercises/practice/atbash-cipher/atbashCipher.u b/exercises/practice/atbash-cipher/atbashCipher.u new file mode 100644 index 0000000..e7db336 --- /dev/null +++ b/exercises/practice/atbash-cipher/atbashCipher.u @@ -0,0 +1,6 @@ +atbashCipher.encode : Text -> Text +atbashCipher.encode input = todo "implement encode" + +atbashCipher.decode : Text -> Text +atbashCipher.decode input = todo "implement decode" + From d6cab9d7e43604c623a46f98fe9e1600efe5ddad Mon Sep 17 00:00:00 2001 From: dreig Date: Wed, 24 May 2023 13:04:28 +0300 Subject: [PATCH 2/2] Update config.json change exercise name to conform to the convention for other exercise --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index bb88785..a52d23c 100644 --- a/config.json +++ b/config.json @@ -379,7 +379,7 @@ }, { "slug": "atbash-cipher", - "name": "Atbash-Cipher", + "name": "Atbash Cipher", "uuid": "660bfdb0-dd6d-494b-8a15-070f6dbe233b", "practices": [], "prerequisites": [],