From 4c19fe2d71dbd1b0e150bde1898368b77d3d9fa9 Mon Sep 17 00:00:00 2001 From: BNAndras <20251272+BNAndras@users.noreply.github.com> Date: Sun, 15 Mar 2026 22:15:36 -0700 Subject: [PATCH 1/2] add `rotational-cipher` --- config.json | 8 +++ exercises/practice/rotational-cipher/.busted | 5 ++ .../rotational-cipher/.docs/instructions.md | 29 +++++++++++ .../rotational-cipher/.meta/config.json | 19 +++++++ .../rotational-cipher/.meta/example.moon | 11 ++++ .../.meta/spec_generator.moon | 11 ++++ .../rotational-cipher/.meta/tests.toml | 40 ++++++++++++++ .../rotational-cipher/rotational_cipher.moon | 4 ++ .../rotational_cipher_spec.moon | 52 +++++++++++++++++++ 9 files changed, 179 insertions(+) create mode 100644 exercises/practice/rotational-cipher/.busted 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/example.moon create mode 100644 exercises/practice/rotational-cipher/.meta/spec_generator.moon create mode 100644 exercises/practice/rotational-cipher/.meta/tests.toml create mode 100644 exercises/practice/rotational-cipher/rotational_cipher.moon create mode 100644 exercises/practice/rotational-cipher/rotational_cipher_spec.moon diff --git a/config.json b/config.json index 6050599..b9b385f 100644 --- a/config.json +++ b/config.json @@ -170,6 +170,14 @@ "prerequisites": [], "difficulty": 2 }, + { + "slug": "rotational-cipher", + "name": "Rotational Cipher", + "uuid": "365fb81f-c059-4231-954b-bac1878e2a0c", + "practices": [], + "prerequisites": [], + "difficulty": 2 + }, { "slug": "rna-transcription", "name": "RNA Transcription", diff --git a/exercises/practice/rotational-cipher/.busted b/exercises/practice/rotational-cipher/.busted new file mode 100644 index 0000000..86b84e7 --- /dev/null +++ b/exercises/practice/rotational-cipher/.busted @@ -0,0 +1,5 @@ +return { + default = { + ROOT = { '.' } + } +} diff --git a/exercises/practice/rotational-cipher/.docs/instructions.md b/exercises/practice/rotational-cipher/.docs/instructions.md new file mode 100644 index 0000000..4bf64ca --- /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 0000000..d920778 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "rotational_cipher.moon" + ], + "test": [ + "rotational_cipher_spec.moon" + ], + "example": [ + ".meta/example.moon" + ] + }, + "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/example.moon b/exercises/practice/rotational-cipher/.meta/example.moon new file mode 100644 index 0000000..4889100 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/example.moon @@ -0,0 +1,11 @@ +{ + rotate: (text, shift_key) -> + text\gsub '.', (char) -> + byte = string.byte char + if byte >= 97 and byte <= 122 + string.char (byte - 97 + shift_key) % 26 + 97 + elseif byte >= 65 and byte <= 90 + string.char (byte - 65 + shift_key) % 26 + 65 + else + char +} diff --git a/exercises/practice/rotational-cipher/.meta/spec_generator.moon b/exercises/practice/rotational-cipher/.meta/spec_generator.moon new file mode 100644 index 0000000..5c53ae0 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/spec_generator.moon @@ -0,0 +1,11 @@ +{ + module_name: 'RotationalCipher', + + generate_test: (case, level) -> + lines = { + "result = RotationalCipher.rotate #{quote case.input.text}, #{case.input.shiftKey}", + "expected = #{quote case.expected}", + "assert.are.equal expected, result" + } + table.concat [indent line, level for line in *lines], '\n' +} diff --git a/exercises/practice/rotational-cipher/.meta/tests.toml b/exercises/practice/rotational-cipher/.meta/tests.toml new file mode 100644 index 0000000..53441ed --- /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/rotational_cipher.moon b/exercises/practice/rotational-cipher/rotational_cipher.moon new file mode 100644 index 0000000..8fc1d85 --- /dev/null +++ b/exercises/practice/rotational-cipher/rotational_cipher.moon @@ -0,0 +1,4 @@ +{ + rotate: (text, shift_key) -> + error 'Implement me' +} diff --git a/exercises/practice/rotational-cipher/rotational_cipher_spec.moon b/exercises/practice/rotational-cipher/rotational_cipher_spec.moon new file mode 100644 index 0000000..f673f9d --- /dev/null +++ b/exercises/practice/rotational-cipher/rotational_cipher_spec.moon @@ -0,0 +1,52 @@ +RotationalCipher = require 'rotational_cipher' + +describe 'rotational-cipher', -> + it 'rotate a by 0, same output as input', -> + result = RotationalCipher.rotate 'a', 0 + expected = 'a' + assert.are.equal expected, result + + pending 'rotate a by 1', -> + result = RotationalCipher.rotate 'a', 1 + expected = 'b' + assert.are.equal expected, result + + pending 'rotate a by 26, same output as input', -> + result = RotationalCipher.rotate 'a', 26 + expected = 'a' + assert.are.equal expected, result + + pending 'rotate m by 13', -> + result = RotationalCipher.rotate 'm', 13 + expected = 'z' + assert.are.equal expected, result + + pending 'rotate n by 13 with wrap around alphabet', -> + result = RotationalCipher.rotate 'n', 13 + expected = 'a' + assert.are.equal expected, result + + pending 'rotate capital letters', -> + result = RotationalCipher.rotate 'OMG', 5 + expected = 'TRL' + assert.are.equal expected, result + + pending 'rotate spaces', -> + result = RotationalCipher.rotate 'O M G', 5 + expected = 'T R L' + assert.are.equal expected, result + + pending 'rotate numbers', -> + result = RotationalCipher.rotate 'Testing 1 2 3 testing', 4 + expected = 'Xiwxmrk 1 2 3 xiwxmrk' + assert.are.equal expected, result + + pending 'rotate punctuation', -> + result = RotationalCipher.rotate "Let's eat, Grandma!", 21 + expected = "Gzo'n zvo, Bmviyhv!" + assert.are.equal expected, result + + pending 'rotate all letters', -> + result = RotationalCipher.rotate 'The quick brown fox jumps over the lazy dog.', 13 + expected = 'Gur dhvpx oebja sbk whzcf bire gur ynml qbt.' + assert.are.equal expected, result From e4b685baee1a56acf3f7934390040824d9238afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Tue, 17 Mar 2026 17:26:54 -0700 Subject: [PATCH 2/2] Bump difficulty Co-authored-by: Glenn Jackman --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index b9b385f..8a8f418 100644 --- a/config.json +++ b/config.json @@ -176,7 +176,7 @@ "uuid": "365fb81f-c059-4231-954b-bac1878e2a0c", "practices": [], "prerequisites": [], - "difficulty": 2 + "difficulty": 3 }, { "slug": "rna-transcription",