From ae445325a64cd8eb498c987d4c028e4fd4b678de Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Fri, 11 Oct 2024 11:45:55 +0200 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/example.R | 12 +++ .../practice/atbash-cipher/.meta/tests.toml | 52 +++++++++++ .../practice/atbash-cipher/atbash-cipher.R | 7 ++ .../atbash-cipher/test_atbash-cipher.R | 86 +++++++++++++++++++ 7 files changed, 211 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/example.R create mode 100644 exercises/practice/atbash-cipher/.meta/tests.toml create mode 100644 exercises/practice/atbash-cipher/atbash-cipher.R create mode 100644 exercises/practice/atbash-cipher/test_atbash-cipher.R diff --git a/config.json b/config.json index bbc7d3f..c6ee6d3 100644 --- a/config.json +++ b/config.json @@ -704,6 +704,14 @@ "practices": [], "prerequisites": [], "difficulty": 3 + }, + { + "slug": "atbash-cipher", + "name": "Atbash Cipher", + "uuid": "81133e3d-4feb-4985-8852-3354e8f72847", + "practices": [], + "prerequisites": [], + "difficulty": 3 } ] }, 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..322267b --- /dev/null +++ b/exercises/practice/atbash-cipher/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "atbash-cipher.R" + ], + "test": [ + "test_atbash-cipher.R" + ], + "example": [ + ".meta/example.R" + ] + }, + "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/example.R b/exercises/practice/atbash-cipher/.meta/example.R new file mode 100644 index 0000000..38c7560 --- /dev/null +++ b/exercises/practice/atbash-cipher/.meta/example.R @@ -0,0 +1,12 @@ +mapping <- setNames(c(letters, 0:9), c(rev(letters), 0:9)) + +encode <- function(plaintext) { + chars <- plaintext |> tolower() |> strsplit("") |> unlist() + mapped <- lapply(chars, \(c) mapping[c]) |> unlist() |> na.omit() + grouped <- split(mapped, ceiling(seq_along(mapped) / 5)) + paste0(sapply(grouped, paste0, collapse = ""), collapse = " ") +} + +decode <- function(ciphertext) { + encode(ciphertext) |> gsub(pattern = " ", replacement = "") +} 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/atbash-cipher.R b/exercises/practice/atbash-cipher/atbash-cipher.R new file mode 100644 index 0000000..42ec937 --- /dev/null +++ b/exercises/practice/atbash-cipher/atbash-cipher.R @@ -0,0 +1,7 @@ +encode <- function(plaintext) { + +} + +decode <- function(ciphertext) { + +} diff --git a/exercises/practice/atbash-cipher/test_atbash-cipher.R b/exercises/practice/atbash-cipher/test_atbash-cipher.R new file mode 100644 index 0000000..52ca1c3 --- /dev/null +++ b/exercises/practice/atbash-cipher/test_atbash-cipher.R @@ -0,0 +1,86 @@ +source("./atbash-cipher.R") +library(testthat) + +test_that("Encode yes", { + plaintext <- "yes" + expected <- "bvh" + expect_equal(encode(plaintext), expected) +}) + +test_that("Encode no", { + plaintext <- "no" + expected <- "ml" + expect_equal(encode(plaintext), expected) +}) + +test_that("Encode OMG", { + plaintext <- "OMG" + expected <- "lnt" + expect_equal(encode(plaintext), expected) +}) + +test_that("Encode spaces", { + plaintext <- "O M G" + expected <- "lnt" + expect_equal(encode(plaintext), expected) +}) + +test_that("Encode mindblowingly", { + plaintext <- "mindblowingly" + expected <- "nrmwy oldrm tob" + expect_equal(encode(plaintext), expected) +}) + +test_that("Encode numbers", { + plaintext <- "Testing,1 2 3, testing." + expected <- "gvhgr mt123 gvhgr mt" + expect_equal(encode(plaintext), expected) +}) + +test_that("Encode deep thought", { + plaintext <- "Truth is fiction." + expected <- "gifgs rhurx grlm" + expect_equal(encode(plaintext), expected) +}) + +test_that("Encode all the letters", { + plaintext <- "The quick brown fox jumps over the lazy dog." + expected <- "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt" + expect_equal(encode(plaintext), expected) +}) + +test_that("Decode exercism", { + ciphertext <- "vcvix rhn" + expected <- "exercism" + expect_equal(decode(ciphertext), expected) +}) + +test_that("Decode a sentence", { + ciphertext <- "zmlyh gzxov rhlug vmzhg vkkrm thglm v" + expected <- "anobstacleisoftenasteppingstone" + expect_equal(decode(ciphertext), expected) +}) + +test_that("Decode numbers", { + ciphertext <- "gvhgr mt123 gvhgr mt" + expected <- "testing123testing" + expect_equal(decode(ciphertext), expected) +}) + +test_that("Decode all the letters", { + ciphertext <- "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt" + expected <- "thequickbrownfoxjumpsoverthelazydog" + expect_equal(decode(ciphertext), expected) +}) + +test_that("Decode with too many spaces", { + ciphertext <- "vc vix r hn" + expected <- "exercism" + expect_equal(decode(ciphertext), expected) +}) + +test_that("Decode with no spaces", { + ciphertext <- "zmlyhgzxovrhlugvmzhgvkkrmthglmv" + expected <- "anobstacleisoftenasteppingstone" + expect_equal(decode(ciphertext), expected) +})