From 328762c23dd767d53b71b23f210db35bd87fcbb7 Mon Sep 17 00:00:00 2001 From: habere-et-dispertire Date: Sun, 10 Sep 2023 18:50:57 +0100 Subject: [PATCH 1/4] [rotational-cipher] Implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 💜²⁴ -- 🤝 https://forum.exercism.org/t/new-exercise-contributions/4077 --- config.json | 9 +++ .../rotational-cipher/.docs/instructions.md | 29 +++++++ .../rotational-cipher/.meta/config.json | 19 +++++ .../.meta/solutions/RotationalCipher.rakumod | 6 ++ .../solutions/rotational-cipher.rakutest | 1 + .../.meta/template-data.yaml | 23 ++++++ .../rotational-cipher/.meta/tests.toml | 40 ++++++++++ .../RotationalCipher.rakumod | 4 + .../rotational-cipher.rakutest | 76 +++++++++++++++++++ 9 files changed, 207 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/solutions/RotationalCipher.rakumod create mode 120000 exercises/practice/rotational-cipher/.meta/solutions/rotational-cipher.rakutest create mode 100644 exercises/practice/rotational-cipher/.meta/template-data.yaml create mode 100644 exercises/practice/rotational-cipher/.meta/tests.toml create mode 100644 exercises/practice/rotational-cipher/RotationalCipher.rakumod create mode 100755 exercises/practice/rotational-cipher/rotational-cipher.rakutest diff --git a/config.json b/config.json index 49392c31..7b121689 100644 --- a/config.json +++ b/config.json @@ -724,6 +724,15 @@ "prerequisites": [], "difficulty": 1, "topics": [] + }, + { + "slug": "rotational-cipher", + "name": "Rotational Cipher", + "uuid": "97aeb214-c566-498d-aa91-33358d105418", + "practices": [], + "prerequisites": [], + "difficulty": 1, + "topics": [] } ] }, diff --git a/exercises/practice/rotational-cipher/.docs/instructions.md b/exercises/practice/rotational-cipher/.docs/instructions.md new file mode 100644 index 00000000..4dee51b3 --- /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..acb8e705 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "habere-et-dispertire" + ], + "files": { + "solution": [ + "RotationalCipher.rakumod" + ], + "test": [ + "rotational-cipher.rakutest" + ], + "example": [ + ".meta/solutions/RotationalCipher.rakumod" + ] + }, + "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/solutions/RotationalCipher.rakumod b/exercises/practice/rotational-cipher/.meta/solutions/RotationalCipher.rakumod new file mode 100644 index 00000000..4aac8c34 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/solutions/RotationalCipher.rakumod @@ -0,0 +1,6 @@ +unit module RotationalCipher; + +sub caesar-cipher ( Str $message, Int $shift-key --> Str ) is export { + $message.trans( 'A'..'Z' => rotate ( 'A'..'Z' ).Slip, $shift-key ) + .trans: 'a'..'z' => rotate ( 'a'..'z' ).Slip, $shift-key; +} diff --git a/exercises/practice/rotational-cipher/.meta/solutions/rotational-cipher.rakutest b/exercises/practice/rotational-cipher/.meta/solutions/rotational-cipher.rakutest new file mode 120000 index 00000000..6a5bd283 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/solutions/rotational-cipher.rakutest @@ -0,0 +1 @@ +../../rotational-cipher.rakutest \ No newline at end of file diff --git a/exercises/practice/rotational-cipher/.meta/template-data.yaml b/exercises/practice/rotational-cipher/.meta/template-data.yaml new file mode 100644 index 00000000..c66f44bb --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/template-data.yaml @@ -0,0 +1,23 @@ +unit: module + +properties: + rotate: + test: |- + sprintf(q:to/END/, %case.Str, %case.Int, %case.Str, %case.raku); + cmp-ok( + caesar-cipher("%s", %s), + "eq", + "%s", + %s, + ); + END + +example: |- + sub caesar-cipher ( Str $message, Int $shift-key --> Str ) is export { + $message.trans( 'A'..'Z' => rotate ( 'A'..'Z' ).Slip, $shift-key ) + .trans: 'a'..'z' => rotate ( 'a'..'z' ).Slip, $shift-key; + } + +stub: |- + sub caesar-cipher ( Str $message, Int $shift-key --> Str ) is export { + } 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/RotationalCipher.rakumod b/exercises/practice/rotational-cipher/RotationalCipher.rakumod new file mode 100644 index 00000000..c9320e9a --- /dev/null +++ b/exercises/practice/rotational-cipher/RotationalCipher.rakumod @@ -0,0 +1,4 @@ +unit module RotationalCipher; + +sub caesar-cipher ( Str $message, Int $shift-key --> Str ) is export { +} diff --git a/exercises/practice/rotational-cipher/rotational-cipher.rakutest b/exercises/practice/rotational-cipher/rotational-cipher.rakutest new file mode 100755 index 00000000..a40d6d7b --- /dev/null +++ b/exercises/practice/rotational-cipher/rotational-cipher.rakutest @@ -0,0 +1,76 @@ +#!/usr/bin/env raku +use Test; +use lib $?FILE.IO.dirname; +use RotationalCipher; + +cmp-ok( # begin: 74e58a38-e484-43f1-9466-877a7515e10f + caesar-cipher("a", 0), + "eq", + "a", + "rotate a by 0, same output as input", +); # end: 74e58a38-e484-43f1-9466-877a7515e10f + +cmp-ok( # begin: 7ee352c6-e6b0-4930-b903-d09943ecb8f5 + caesar-cipher("a", 1), + "eq", + "b", + "rotate a by 1", +); # end: 7ee352c6-e6b0-4930-b903-d09943ecb8f5 + +cmp-ok( # begin: edf0a733-4231-4594-a5ee-46a4009ad764 + caesar-cipher("a", 26), + "eq", + "a", + "rotate a by 26, same output as input", +); # end: edf0a733-4231-4594-a5ee-46a4009ad764 + +cmp-ok( # begin: e3e82cb9-2a5b-403f-9931-e43213879300 + caesar-cipher("m", 13), + "eq", + "z", + "rotate m by 13", +); # end: e3e82cb9-2a5b-403f-9931-e43213879300 + +cmp-ok( # begin: 19f9eb78-e2ad-4da4-8fe3-9291d47c1709 + caesar-cipher("n", 13), + "eq", + "a", + "rotate n by 13 with wrap around alphabet", +); # end: 19f9eb78-e2ad-4da4-8fe3-9291d47c1709 + +cmp-ok( # begin: a116aef4-225b-4da9-884f-e8023ca6408a + caesar-cipher("OMG", 5), + "eq", + "TRL", + "rotate capital letters", +); # end: a116aef4-225b-4da9-884f-e8023ca6408a + +cmp-ok( # begin: 71b541bb-819c-4dc6-a9c3-132ef9bb737b + caesar-cipher("O M G", 5), + "eq", + "T R L", + "rotate spaces", +); # end: 71b541bb-819c-4dc6-a9c3-132ef9bb737b + +cmp-ok( # begin: ef32601d-e9ef-4b29-b2b5-8971392282e6 + caesar-cipher("Testing 1 2 3 testing", 4), + "eq", + "Xiwxmrk 1 2 3 xiwxmrk", + "rotate numbers", +); # end: ef32601d-e9ef-4b29-b2b5-8971392282e6 + +cmp-ok( # begin: 32dd74f6-db2b-41a6-b02c-82eb4f93e549 + caesar-cipher("Let's eat, Grandma!", 21), + "eq", + "Gzo'n zvo, Bmviyhv!", + "rotate punctuation", +); # end: 32dd74f6-db2b-41a6-b02c-82eb4f93e549 + +cmp-ok( # begin: 9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9 + caesar-cipher("The quick brown fox jumps over the lazy dog.", 13), + "eq", + "Gur dhvpx oebja sbk whzcf bire gur ynml qbt.", + "rotate all letters", +); # end: 9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9 + +done-testing; From 0af186c706a11b3869a3ee0f53877f9cef448e1b Mon Sep 17 00:00:00 2001 From: habere-et-dispertire Date: Tue, 12 Sep 2023 09:01:35 +0100 Subject: [PATCH 2/4] [dogfooding] ROT13( ROT13 ) == input --- .../.meta/template-data.yaml | 22 +- .../rotational-cipher.rakutest | 220 +++++++++++++----- 2 files changed, 176 insertions(+), 66 deletions(-) diff --git a/exercises/practice/rotational-cipher/.meta/template-data.yaml b/exercises/practice/rotational-cipher/.meta/template-data.yaml index c66f44bb..7c9462cb 100644 --- a/exercises/practice/rotational-cipher/.meta/template-data.yaml +++ b/exercises/practice/rotational-cipher/.meta/template-data.yaml @@ -4,12 +4,22 @@ properties: rotate: test: |- sprintf(q:to/END/, %case.Str, %case.Int, %case.Str, %case.raku); - cmp-ok( - caesar-cipher("%s", %s), - "eq", - "%s", - %s, - ); + subtest "%1$s" => { + cmp-ok( + caesar-cipher("%1$s", %2$s), + "eq", + "%3$s", + %4$s, + ); + if %2$s == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("%1$s", %2$s),13), + "eq", + "%1$s", + %4$s, + ); + } + } END example: |- diff --git a/exercises/practice/rotational-cipher/rotational-cipher.rakutest b/exercises/practice/rotational-cipher/rotational-cipher.rakutest index a40d6d7b..8539d852 100755 --- a/exercises/practice/rotational-cipher/rotational-cipher.rakutest +++ b/exercises/practice/rotational-cipher/rotational-cipher.rakutest @@ -3,74 +3,174 @@ use Test; use lib $?FILE.IO.dirname; use RotationalCipher; -cmp-ok( # begin: 74e58a38-e484-43f1-9466-877a7515e10f - caesar-cipher("a", 0), - "eq", - "a", - "rotate a by 0, same output as input", -); # end: 74e58a38-e484-43f1-9466-877a7515e10f +subtest "a" => { # begin: 74e58a38-e484-43f1-9466-877a7515e10f + cmp-ok( + caesar-cipher("a", 0), + "eq", + "a", + "rotate a by 0, same output as input", + ); + if 0 == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("a", 0),13), + "eq", + "a", + "rotate a by 0, same output as input", + ); + } +} # end: 74e58a38-e484-43f1-9466-877a7515e10f -cmp-ok( # begin: 7ee352c6-e6b0-4930-b903-d09943ecb8f5 - caesar-cipher("a", 1), - "eq", - "b", - "rotate a by 1", -); # end: 7ee352c6-e6b0-4930-b903-d09943ecb8f5 +subtest "a" => { # begin: 7ee352c6-e6b0-4930-b903-d09943ecb8f5 + cmp-ok( + caesar-cipher("a", 1), + "eq", + "b", + "rotate a by 1", + ); + if 1 == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("a", 1),13), + "eq", + "a", + "rotate a by 1", + ); + } +} # end: 7ee352c6-e6b0-4930-b903-d09943ecb8f5 -cmp-ok( # begin: edf0a733-4231-4594-a5ee-46a4009ad764 - caesar-cipher("a", 26), - "eq", - "a", - "rotate a by 26, same output as input", -); # end: edf0a733-4231-4594-a5ee-46a4009ad764 +subtest "a" => { # begin: edf0a733-4231-4594-a5ee-46a4009ad764 + cmp-ok( + caesar-cipher("a", 26), + "eq", + "a", + "rotate a by 26, same output as input", + ); + if 26 == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("a", 26),13), + "eq", + "a", + "rotate a by 26, same output as input", + ); + } +} # end: edf0a733-4231-4594-a5ee-46a4009ad764 -cmp-ok( # begin: e3e82cb9-2a5b-403f-9931-e43213879300 - caesar-cipher("m", 13), - "eq", - "z", - "rotate m by 13", -); # end: e3e82cb9-2a5b-403f-9931-e43213879300 +subtest "m" => { # begin: e3e82cb9-2a5b-403f-9931-e43213879300 + cmp-ok( + caesar-cipher("m", 13), + "eq", + "z", + "rotate m by 13", + ); + if 13 == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("m", 13),13), + "eq", + "m", + "rotate m by 13", + ); + } +} # end: e3e82cb9-2a5b-403f-9931-e43213879300 -cmp-ok( # begin: 19f9eb78-e2ad-4da4-8fe3-9291d47c1709 - caesar-cipher("n", 13), - "eq", - "a", - "rotate n by 13 with wrap around alphabet", -); # end: 19f9eb78-e2ad-4da4-8fe3-9291d47c1709 +subtest "n" => { # begin: 19f9eb78-e2ad-4da4-8fe3-9291d47c1709 + cmp-ok( + caesar-cipher("n", 13), + "eq", + "a", + "rotate n by 13 with wrap around alphabet", + ); + if 13 == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("n", 13),13), + "eq", + "n", + "rotate n by 13 with wrap around alphabet", + ); + } +} # end: 19f9eb78-e2ad-4da4-8fe3-9291d47c1709 -cmp-ok( # begin: a116aef4-225b-4da9-884f-e8023ca6408a - caesar-cipher("OMG", 5), - "eq", - "TRL", - "rotate capital letters", -); # end: a116aef4-225b-4da9-884f-e8023ca6408a +subtest "OMG" => { # begin: a116aef4-225b-4da9-884f-e8023ca6408a + cmp-ok( + caesar-cipher("OMG", 5), + "eq", + "TRL", + "rotate capital letters", + ); + if 5 == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("OMG", 5),13), + "eq", + "OMG", + "rotate capital letters", + ); + } +} # end: a116aef4-225b-4da9-884f-e8023ca6408a -cmp-ok( # begin: 71b541bb-819c-4dc6-a9c3-132ef9bb737b - caesar-cipher("O M G", 5), - "eq", - "T R L", - "rotate spaces", -); # end: 71b541bb-819c-4dc6-a9c3-132ef9bb737b +subtest "O M G" => { # begin: 71b541bb-819c-4dc6-a9c3-132ef9bb737b + cmp-ok( + caesar-cipher("O M G", 5), + "eq", + "T R L", + "rotate spaces", + ); + if 5 == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("O M G", 5),13), + "eq", + "O M G", + "rotate spaces", + ); + } +} # end: 71b541bb-819c-4dc6-a9c3-132ef9bb737b -cmp-ok( # begin: ef32601d-e9ef-4b29-b2b5-8971392282e6 - caesar-cipher("Testing 1 2 3 testing", 4), - "eq", - "Xiwxmrk 1 2 3 xiwxmrk", - "rotate numbers", -); # end: ef32601d-e9ef-4b29-b2b5-8971392282e6 +subtest "Testing 1 2 3 testing" => { # begin: ef32601d-e9ef-4b29-b2b5-8971392282e6 + cmp-ok( + caesar-cipher("Testing 1 2 3 testing", 4), + "eq", + "Xiwxmrk 1 2 3 xiwxmrk", + "rotate numbers", + ); + if 4 == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("Testing 1 2 3 testing", 4),13), + "eq", + "Testing 1 2 3 testing", + "rotate numbers", + ); + } +} # end: ef32601d-e9ef-4b29-b2b5-8971392282e6 -cmp-ok( # begin: 32dd74f6-db2b-41a6-b02c-82eb4f93e549 - caesar-cipher("Let's eat, Grandma!", 21), - "eq", - "Gzo'n zvo, Bmviyhv!", - "rotate punctuation", -); # end: 32dd74f6-db2b-41a6-b02c-82eb4f93e549 +subtest "Let's eat, Grandma!" => { # begin: 32dd74f6-db2b-41a6-b02c-82eb4f93e549 + cmp-ok( + caesar-cipher("Let's eat, Grandma!", 21), + "eq", + "Gzo'n zvo, Bmviyhv!", + "rotate punctuation", + ); + if 21 == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("Let's eat, Grandma!", 21),13), + "eq", + "Let's eat, Grandma!", + "rotate punctuation", + ); + } +} # end: 32dd74f6-db2b-41a6-b02c-82eb4f93e549 -cmp-ok( # begin: 9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9 - caesar-cipher("The quick brown fox jumps over the lazy dog.", 13), - "eq", - "Gur dhvpx oebja sbk whzcf bire gur ynml qbt.", - "rotate all letters", -); # end: 9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9 +subtest "The quick brown fox jumps over the lazy dog." => { # begin: 9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9 + cmp-ok( + caesar-cipher("The quick brown fox jumps over the lazy dog.", 13), + "eq", + "Gur dhvpx oebja sbk whzcf bire gur ynml qbt.", + "rotate all letters", + ); + if 13 == 13 { + cmp-ok( + caesar-cipher(caesar-cipher("The quick brown fox jumps over the lazy dog.", 13),13), + "eq", + "The quick brown fox jumps over the lazy dog.", + "rotate all letters", + ); + } +} # end: 9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9 done-testing; From 3fce691e59a4163570bce348e9aa4942ba117376 Mon Sep 17 00:00:00 2001 From: habere-et-dispertire Date: Tue, 12 Sep 2023 09:32:03 +0100 Subject: [PATCH 3/4] retrigger checks From 22fc85919ec52dfb30d4527cb4f05ae6636110e2 Mon Sep 17 00:00:00 2001 From: Daniel Mita Date: Thu, 14 Sep 2023 12:47:41 +0100 Subject: [PATCH 4/4] Refactor decryption tests for ROT13 --- .../rotational-cipher/.meta/config.json | 3 + .../.meta/solutions/RotationalCipher.rakumod | 4 +- .../.meta/template-data.yaml | 49 ++-- .../RotationalCipher.rakumod | 2 +- .../rotational-cipher.rakutest | 219 ++++++------------ 5 files changed, 110 insertions(+), 167 deletions(-) diff --git a/exercises/practice/rotational-cipher/.meta/config.json b/exercises/practice/rotational-cipher/.meta/config.json index acb8e705..498a4ae1 100644 --- a/exercises/practice/rotational-cipher/.meta/config.json +++ b/exercises/practice/rotational-cipher/.meta/config.json @@ -2,6 +2,9 @@ "authors": [ "habere-et-dispertire" ], + "contributors": [ + "m-dango" + ], "files": { "solution": [ "RotationalCipher.rakumod" diff --git a/exercises/practice/rotational-cipher/.meta/solutions/RotationalCipher.rakumod b/exercises/practice/rotational-cipher/.meta/solutions/RotationalCipher.rakumod index 4aac8c34..1876e2a1 100644 --- a/exercises/practice/rotational-cipher/.meta/solutions/RotationalCipher.rakumod +++ b/exercises/practice/rotational-cipher/.meta/solutions/RotationalCipher.rakumod @@ -1,6 +1,6 @@ unit module RotationalCipher; -sub caesar-cipher ( Str $message, Int $shift-key --> Str ) is export { - $message.trans( 'A'..'Z' => rotate ( 'A'..'Z' ).Slip, $shift-key ) +sub caesar-cipher ( Str :$text, Int :$shift-key --> Str ) is export { + $text.trans( 'A'..'Z' => rotate ( 'A'..'Z' ).Slip, $shift-key ) .trans: 'a'..'z' => rotate ( 'a'..'z' ).Slip, $shift-key; } diff --git a/exercises/practice/rotational-cipher/.meta/template-data.yaml b/exercises/practice/rotational-cipher/.meta/template-data.yaml index 7c9462cb..61768b74 100644 --- a/exercises/practice/rotational-cipher/.meta/template-data.yaml +++ b/exercises/practice/rotational-cipher/.meta/template-data.yaml @@ -3,31 +3,44 @@ unit: module properties: rotate: test: |- - sprintf(q:to/END/, %case.Str, %case.Int, %case.Str, %case.raku); - subtest "%1$s" => { - cmp-ok( - caesar-cipher("%1$s", %2$s), - "eq", - "%3$s", - %4$s, - ); - if %2$s == 13 { + my Str:D $template.=new; + if %case != 13 { + $template = q:to/END/; cmp-ok( - caesar-cipher(caesar-cipher("%1$s", %2$s),13), - "eq", - "%1$s", - %4$s, + caesar-cipher( :text(%s), :shift-key(%s) ), + "eq", + %s, + %s, ); - } + END } - END + else { + $template = q:to/END/; + subtest %4$s => { + cmp-ok( + caesar-cipher( :text(%1$s), :shift-key(%2$s) ), + "eq", + %3$s, + "encrypt", + ); + + cmp-ok( + caesar-cipher( :text(%3$s), :shift-key(%2$s) ), + "eq", + %1$s, + "decrypt", + ); + } + END + } + sprintf($template, %case.raku, %case, %case.raku, %case.raku); example: |- - sub caesar-cipher ( Str $message, Int $shift-key --> Str ) is export { - $message.trans( 'A'..'Z' => rotate ( 'A'..'Z' ).Slip, $shift-key ) + sub caesar-cipher ( Str :$text, Int :$shift-key --> Str ) is export { + $text.trans( 'A'..'Z' => rotate ( 'A'..'Z' ).Slip, $shift-key ) .trans: 'a'..'z' => rotate ( 'a'..'z' ).Slip, $shift-key; } stub: |- - sub caesar-cipher ( Str $message, Int $shift-key --> Str ) is export { + sub caesar-cipher ( :$text, :$shift-key ) is export { } diff --git a/exercises/practice/rotational-cipher/RotationalCipher.rakumod b/exercises/practice/rotational-cipher/RotationalCipher.rakumod index c9320e9a..c34b7765 100644 --- a/exercises/practice/rotational-cipher/RotationalCipher.rakumod +++ b/exercises/practice/rotational-cipher/RotationalCipher.rakumod @@ -1,4 +1,4 @@ unit module RotationalCipher; -sub caesar-cipher ( Str $message, Int $shift-key --> Str ) is export { +sub caesar-cipher ( :$text, :$shift-key ) is export { } diff --git a/exercises/practice/rotational-cipher/rotational-cipher.rakutest b/exercises/practice/rotational-cipher/rotational-cipher.rakutest index 8539d852..d394378e 100755 --- a/exercises/practice/rotational-cipher/rotational-cipher.rakutest +++ b/exercises/practice/rotational-cipher/rotational-cipher.rakutest @@ -3,174 +3,101 @@ use Test; use lib $?FILE.IO.dirname; use RotationalCipher; -subtest "a" => { # begin: 74e58a38-e484-43f1-9466-877a7515e10f - cmp-ok( - caesar-cipher("a", 0), - "eq", - "a", - "rotate a by 0, same output as input", - ); - if 0 == 13 { - cmp-ok( - caesar-cipher(caesar-cipher("a", 0),13), - "eq", - "a", - "rotate a by 0, same output as input", - ); - } -} # end: 74e58a38-e484-43f1-9466-877a7515e10f +cmp-ok( # begin: 74e58a38-e484-43f1-9466-877a7515e10f + caesar-cipher( :text("a"), :shift-key(0) ), + "eq", + "a", + "rotate a by 0, same output as input", +); # end: 74e58a38-e484-43f1-9466-877a7515e10f -subtest "a" => { # begin: 7ee352c6-e6b0-4930-b903-d09943ecb8f5 - cmp-ok( - caesar-cipher("a", 1), - "eq", - "b", - "rotate a by 1", - ); - if 1 == 13 { - cmp-ok( - caesar-cipher(caesar-cipher("a", 1),13), - "eq", - "a", - "rotate a by 1", - ); - } -} # end: 7ee352c6-e6b0-4930-b903-d09943ecb8f5 +cmp-ok( # begin: 7ee352c6-e6b0-4930-b903-d09943ecb8f5 + caesar-cipher( :text("a"), :shift-key(1) ), + "eq", + "b", + "rotate a by 1", +); # end: 7ee352c6-e6b0-4930-b903-d09943ecb8f5 -subtest "a" => { # begin: edf0a733-4231-4594-a5ee-46a4009ad764 - cmp-ok( - caesar-cipher("a", 26), - "eq", - "a", - "rotate a by 26, same output as input", - ); - if 26 == 13 { +cmp-ok( # begin: edf0a733-4231-4594-a5ee-46a4009ad764 + caesar-cipher( :text("a"), :shift-key(26) ), + "eq", + "a", + "rotate a by 26, same output as input", +); # end: edf0a733-4231-4594-a5ee-46a4009ad764 + +subtest "rotate m by 13" => { # begin: e3e82cb9-2a5b-403f-9931-e43213879300 cmp-ok( - caesar-cipher(caesar-cipher("a", 26),13), - "eq", - "a", - "rotate a by 26, same output as input", + caesar-cipher( :text("m"), :shift-key(13) ), + "eq", + "z", + "encrypt", ); - } -} # end: edf0a733-4231-4594-a5ee-46a4009ad764 -subtest "m" => { # begin: e3e82cb9-2a5b-403f-9931-e43213879300 - cmp-ok( - caesar-cipher("m", 13), - "eq", - "z", - "rotate m by 13", - ); - if 13 == 13 { cmp-ok( - caesar-cipher(caesar-cipher("m", 13),13), - "eq", - "m", - "rotate m by 13", + caesar-cipher( :text("z"), :shift-key(13) ), + "eq", + "m", + "decrypt", ); - } } # end: e3e82cb9-2a5b-403f-9931-e43213879300 -subtest "n" => { # begin: 19f9eb78-e2ad-4da4-8fe3-9291d47c1709 - cmp-ok( - caesar-cipher("n", 13), - "eq", - "a", - "rotate n by 13 with wrap around alphabet", - ); - if 13 == 13 { +subtest "rotate n by 13 with wrap around alphabet" => { # begin: 19f9eb78-e2ad-4da4-8fe3-9291d47c1709 cmp-ok( - caesar-cipher(caesar-cipher("n", 13),13), - "eq", - "n", - "rotate n by 13 with wrap around alphabet", + caesar-cipher( :text("n"), :shift-key(13) ), + "eq", + "a", + "encrypt", ); - } -} # end: 19f9eb78-e2ad-4da4-8fe3-9291d47c1709 -subtest "OMG" => { # begin: a116aef4-225b-4da9-884f-e8023ca6408a - cmp-ok( - caesar-cipher("OMG", 5), - "eq", - "TRL", - "rotate capital letters", - ); - if 5 == 13 { cmp-ok( - caesar-cipher(caesar-cipher("OMG", 5),13), - "eq", - "OMG", - "rotate capital letters", + caesar-cipher( :text("a"), :shift-key(13) ), + "eq", + "n", + "decrypt", ); - } -} # end: a116aef4-225b-4da9-884f-e8023ca6408a +} # end: 19f9eb78-e2ad-4da4-8fe3-9291d47c1709 -subtest "O M G" => { # begin: 71b541bb-819c-4dc6-a9c3-132ef9bb737b - cmp-ok( - caesar-cipher("O M G", 5), - "eq", - "T R L", - "rotate spaces", - ); - if 5 == 13 { - cmp-ok( - caesar-cipher(caesar-cipher("O M G", 5),13), - "eq", - "O M G", - "rotate spaces", - ); - } -} # end: 71b541bb-819c-4dc6-a9c3-132ef9bb737b +cmp-ok( # begin: a116aef4-225b-4da9-884f-e8023ca6408a + caesar-cipher( :text("OMG"), :shift-key(5) ), + "eq", + "TRL", + "rotate capital letters", +); # end: a116aef4-225b-4da9-884f-e8023ca6408a -subtest "Testing 1 2 3 testing" => { # begin: ef32601d-e9ef-4b29-b2b5-8971392282e6 - cmp-ok( - caesar-cipher("Testing 1 2 3 testing", 4), - "eq", - "Xiwxmrk 1 2 3 xiwxmrk", - "rotate numbers", - ); - if 4 == 13 { - cmp-ok( - caesar-cipher(caesar-cipher("Testing 1 2 3 testing", 4),13), - "eq", - "Testing 1 2 3 testing", - "rotate numbers", - ); - } -} # end: ef32601d-e9ef-4b29-b2b5-8971392282e6 +cmp-ok( # begin: 71b541bb-819c-4dc6-a9c3-132ef9bb737b + caesar-cipher( :text("O M G"), :shift-key(5) ), + "eq", + "T R L", + "rotate spaces", +); # end: 71b541bb-819c-4dc6-a9c3-132ef9bb737b + +cmp-ok( # begin: ef32601d-e9ef-4b29-b2b5-8971392282e6 + caesar-cipher( :text("Testing 1 2 3 testing"), :shift-key(4) ), + "eq", + "Xiwxmrk 1 2 3 xiwxmrk", + "rotate numbers", +); # end: ef32601d-e9ef-4b29-b2b5-8971392282e6 + +cmp-ok( # begin: 32dd74f6-db2b-41a6-b02c-82eb4f93e549 + caesar-cipher( :text("Let's eat, Grandma!"), :shift-key(21) ), + "eq", + "Gzo'n zvo, Bmviyhv!", + "rotate punctuation", +); # end: 32dd74f6-db2b-41a6-b02c-82eb4f93e549 -subtest "Let's eat, Grandma!" => { # begin: 32dd74f6-db2b-41a6-b02c-82eb4f93e549 - cmp-ok( - caesar-cipher("Let's eat, Grandma!", 21), - "eq", - "Gzo'n zvo, Bmviyhv!", - "rotate punctuation", - ); - if 21 == 13 { +subtest "rotate all letters" => { # begin: 9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9 cmp-ok( - caesar-cipher(caesar-cipher("Let's eat, Grandma!", 21),13), - "eq", - "Let's eat, Grandma!", - "rotate punctuation", + caesar-cipher( :text("The quick brown fox jumps over the lazy dog."), :shift-key(13) ), + "eq", + "Gur dhvpx oebja sbk whzcf bire gur ynml qbt.", + "encrypt", ); - } -} # end: 32dd74f6-db2b-41a6-b02c-82eb4f93e549 -subtest "The quick brown fox jumps over the lazy dog." => { # begin: 9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9 - cmp-ok( - caesar-cipher("The quick brown fox jumps over the lazy dog.", 13), - "eq", - "Gur dhvpx oebja sbk whzcf bire gur ynml qbt.", - "rotate all letters", - ); - if 13 == 13 { cmp-ok( - caesar-cipher(caesar-cipher("The quick brown fox jumps over the lazy dog.", 13),13), - "eq", - "The quick brown fox jumps over the lazy dog.", - "rotate all letters", + caesar-cipher( :text("Gur dhvpx oebja sbk whzcf bire gur ynml qbt."), :shift-key(13) ), + "eq", + "The quick brown fox jumps over the lazy dog.", + "decrypt", ); - } } # end: 9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9 done-testing;