diff --git a/config.json b/config.json index d1bc056..385578b 100644 --- a/config.json +++ b/config.json @@ -625,6 +625,14 @@ "practices": [], "prerequisites": [], "difficulty": 2 + }, + { + "slug": "rotational-cipher", + "name": "rotational cipher", + "uuid": "14c90535-2be7-438b-b3af-80fc84336e89", + "practices": [], + "prerequisites": [], + "difficulty": 2 } ] }, 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..9639924 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "rotational_cipher.bal" + ], + "test": [ + "tests/rotational_cipher_test.bal" + ], + "example": [ + ".meta/reference/rotational_cipher.bal" + ] + }, + "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/reference/rotational_cipher.bal b/exercises/practice/rotational-cipher/.meta/reference/rotational_cipher.bal new file mode 100644 index 0000000..8317624 --- /dev/null +++ b/exercises/practice/rotational-cipher/.meta/reference/rotational_cipher.bal @@ -0,0 +1,25 @@ +# Encodes the input text using the rotational cipher technique +# +# + text - the text to encode +# + shiftKey - the number of positions to shift each alphabetic character +# + return - the encoded text +function rotate(string text, int shiftKey) returns string { + string result = ""; + foreach string:Char chr in text { + int codePoint = chr.toCodePointInt(); + int newCodePoint = codePoint; + + if codePoint >= 65 && codePoint <= 90 { + newCodePoint = 65 + (codePoint - 65 + shiftKey) % 26; + } + else if codePoint >= 97 && codePoint <= 122 { + newCodePoint = 97 + (codePoint - 97 + shiftKey) % 26; + } + + // Checkpanic since this shouldn't return an error + string rotated = checkpanic string:'fromCodePointInt(newCodePoint); + result += rotated; + } + + return result; +} 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/Ballerina.toml b/exercises/practice/rotational-cipher/Ballerina.toml new file mode 100644 index 0000000..031e0f1 --- /dev/null +++ b/exercises/practice/rotational-cipher/Ballerina.toml @@ -0,0 +1,5 @@ +[package] +org = "ballerina_exercism" +name = "rotational_cipher" +version = "0.1.0" +distribution = "2201.5.0" diff --git a/exercises/practice/rotational-cipher/Dependencies.toml b/exercises/practice/rotational-cipher/Dependencies.toml new file mode 100644 index 0000000..26923f2 --- /dev/null +++ b/exercises/practice/rotational-cipher/Dependencies.toml @@ -0,0 +1,38 @@ +# AUTO-GENERATED FILE. DO NOT MODIFY. + +# This file is auto-generated by Ballerina for managing dependency versions. +# It should not be modified by hand. + +[ballerina] +dependencies-toml-version = "2" +distribution-version = "2201.5.0" + +[[package]] +org = "ballerina" +name = "jballerina.java" +version = "0.0.0" +scope = "testOnly" + +[[package]] +org = "ballerina" +name = "test" +version = "0.0.0" +scope = "testOnly" +dependencies = [ + {org = "ballerina", name = "jballerina.java"} +] +modules = [ + {org = "ballerina", packageName = "test", moduleName = "test"} +] + +[[package]] +org = "ballerina_exercism" +name = "rotational_cipher" +version = "0.1.0" +dependencies = [ + {org = "ballerina", name = "test"} +] +modules = [ + {org = "ballerina_exercism", packageName = "rotational_cipher", moduleName = "rotational_cipher"} +] + diff --git a/exercises/practice/rotational-cipher/rotational_cipher.bal b/exercises/practice/rotational-cipher/rotational_cipher.bal new file mode 100644 index 0000000..a0e97d9 --- /dev/null +++ b/exercises/practice/rotational-cipher/rotational_cipher.bal @@ -0,0 +1,8 @@ +# Encodes the input text using the rotational cipher technique +# +# + text - the text to encode +# + shiftKey - the number of positions to shift each alphabetic character +# + return - the encoded text +function rotate(string text, int shiftKey) returns string { + // TODO: implement this function +} diff --git a/exercises/practice/rotational-cipher/tests/rotational_cipher_test.bal b/exercises/practice/rotational-cipher/tests/rotational_cipher_test.bal new file mode 100644 index 0000000..c11e4ac --- /dev/null +++ b/exercises/practice/rotational-cipher/tests/rotational_cipher_test.bal @@ -0,0 +1,74 @@ + +import ballerina/test; + + +@test:Config {} +function testRotateABy0SameOutputAsInput() { + test:assertEquals(rotate("a", 0), "a"); +} + +@test:Config { + enable: false +} +function testRotateABy1() { + test:assertEquals(rotate("a", 1), "b"); +} + +@test:Config { + enable: false +} +function testRotateABy26SameOutputAsInput() { + test:assertEquals(rotate("a", 26), "a"); +} + +@test:Config { + enable: false +} +function testRotateMBy13() { + test:assertEquals(rotate("m", 13), "z"); +} + +@test:Config { + enable: false +} +function testRotateNBy13WithWrapAroundAlphabet() { + test:assertEquals(rotate("n", 13), "a"); +} + +@test:Config { + enable: false +} +function testRotateCapitalLetters() { + test:assertEquals(rotate("OMG", 5), "TRL"); +} + +@test:Config { + enable: false +} +function testRotateSpaces() { + test:assertEquals(rotate("O M G", 5), "T R L"); +} + +@test:Config { + enable: false +} +function testRotateNumbers() { + test:assertEquals(rotate("Testing 1 2 3 testing", 4), "Xiwxmrk 1 2 3 xiwxmrk"); +} + +@test:Config { + enable: false +} +function testRotatePunctuation() { + test:assertEquals(rotate("Let's eat, Grandma!", 21), "Gzo'n zvo, Bmviyhv!"); +} + +@test:Config { + enable: false +} +function testRotateAllLetters() { + string text = "The quick brown fox jumps over the lazy dog."; + int shift = 13; + string expected = "Gur dhvpx oebja sbk whzcf bire gur ynml qbt."; + test:assertEquals(rotate(text, shift), expected); +}