From 91647031dc6a5a300f4ab34336b94f30fb4b21c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Mon, 23 Feb 2026 09:27:13 -0800 Subject: [PATCH] Add canonical tests for decoding --- .../practice/atbash-cipher/.meta/config.json | 3 +- .../practice/atbash-cipher/.meta/example.lua | 37 ++---- .../atbash-cipher/.meta/spec_generator.lua | 13 ++ .../practice/atbash-cipher/atbash-cipher.lua | 11 +- .../atbash-cipher/atbash-cipher_spec.lua | 117 ++++++++++++++---- 5 files changed, 126 insertions(+), 55 deletions(-) create mode 100644 exercises/practice/atbash-cipher/.meta/spec_generator.lua diff --git a/exercises/practice/atbash-cipher/.meta/config.json b/exercises/practice/atbash-cipher/.meta/config.json index fdc664b2..13700337 100644 --- a/exercises/practice/atbash-cipher/.meta/config.json +++ b/exercises/practice/atbash-cipher/.meta/config.json @@ -3,7 +3,8 @@ "ryanplusplus" ], "contributors": [ - "aarti" + "aarti", + "BNAndras" ], "files": { "solution": [ diff --git a/exercises/practice/atbash-cipher/.meta/example.lua b/exercises/practice/atbash-cipher/.meta/example.lua index 7d763937..0dfba108 100644 --- a/exercises/practice/atbash-cipher/.meta/example.lua +++ b/exercises/practice/atbash-cipher/.meta/example.lua @@ -1,32 +1,17 @@ -local alphabet = 'abcdefghijklmnopqrstuvwxyz' -local decoder_ring = setmetatable({}, { - __index = function() - return '' - end -}) - -for i = 1, #alphabet do - decoder_ring[alphabet:sub(i, i)] = alphabet:reverse():sub(i, i) -end - -for i = 0, 9 do - decoder_ring[tostring(i)] = tostring(i) +local function inverse_char(char) + return string.char(219 - string.byte(char)) end -local function transcribe(plaintext) - return plaintext:lower():gsub('.', decoder_ring) +local function encode(phrase) + local clean = string.gsub(string.lower(phrase), "[^a-z0-9]", "") + local decoded = string.gsub(clean, "[a-z]", inverse_char) + local spaced = string.gsub(decoded, ".....", "%0 ") + return string.match(spaced, "^%s*(.-)%s*$") or spaced end -local function split_chunks(s) - local chunks = {} - s:gsub('..?.?.?.?', function(chunk) - table.insert(chunks, chunk) - end) - return table.concat(chunks, ' ') +local function decode(phrase) + local clean = string.gsub(string.lower(phrase), "[^a-z0-9]", "") + return string.gsub(clean, "[a-z]", inverse_char) end -return { - encode = function(plaintext) - return split_chunks(transcribe(plaintext)) - end -} +return { encode = encode, decode = decode } diff --git a/exercises/practice/atbash-cipher/.meta/spec_generator.lua b/exercises/practice/atbash-cipher/.meta/spec_generator.lua new file mode 100644 index 00000000..24c52e65 --- /dev/null +++ b/exercises/practice/atbash-cipher/.meta/spec_generator.lua @@ -0,0 +1,13 @@ +return { + module_name = 'atbash_cipher', + + generate_test = function(case) + local lines = {} + table.insert(lines, string.format("local phrase = '%s'", case.input.phrase)) + table.insert(lines, string.format("local expected = '%s'", case.expected)) + table.insert(lines, string.format("local result = atbash_cipher.%s(phrase)", case.property)) + table.insert(lines, "assert.are.same(expected, result)") + + return table.concat(lines, "\n") + end +} diff --git a/exercises/practice/atbash-cipher/atbash-cipher.lua b/exercises/practice/atbash-cipher/atbash-cipher.lua index 65d7467d..9267c1de 100644 --- a/exercises/practice/atbash-cipher/atbash-cipher.lua +++ b/exercises/practice/atbash-cipher/atbash-cipher.lua @@ -1,4 +1,7 @@ -return { - encode = function(plaintext) - end -} +local function encode(phrase) +end + +local function decode(phrase) +end + +return { encode = encode, decode = decode } diff --git a/exercises/practice/atbash-cipher/atbash-cipher_spec.lua b/exercises/practice/atbash-cipher/atbash-cipher_spec.lua index 32d35e71..45227741 100644 --- a/exercises/practice/atbash-cipher/atbash-cipher_spec.lua +++ b/exercises/practice/atbash-cipher/atbash-cipher_spec.lua @@ -1,36 +1,105 @@ -local encode = require('atbash-cipher').encode +local atbash_cipher = require('atbash-cipher') describe('atbash-cipher', function() - it('should encode single letter plaintexts', function() - assert.are.equal('m', encode('n')) - end) + describe('encode', function() + it('encode yes', function() + local phrase = 'yes' + local expected = 'bvh' + local result = atbash_cipher.encode(phrase) + assert.are.same(expected, result) + end) - it('should encode single-chunk plaintexts', function() - assert.are.equal('svool', encode('hello')) - end) + it('encode no', function() + local phrase = 'no' + local expected = 'ml' + local result = atbash_cipher.encode(phrase) + assert.are.same(expected, result) + end) - it('should encode multi-chunk plaintexts', function() - assert.are.equal('nrmwy oldrm tob', encode('mindblowingly')) - end) + it('encode omg', function() + local phrase = 'OMG' + local expected = 'lnt' + local result = atbash_cipher.encode(phrase) + assert.are.same(expected, result) + end) - it('should encode all letters as lower-case', function() - assert.are.equal('svool', encode('HeLLo')) - end) + it('encode spaces', function() + local phrase = 'O M G' + local expected = 'lnt' + local result = atbash_cipher.encode(phrase) + assert.are.same(expected, result) + end) - it('should not encode whitespace', function() - assert.are.equal('svool', encode('h e l l o')) - end) + it('encode mindblowingly', function() + local phrase = 'mindblowingly' + local expected = 'nrmwy oldrm tob' + local result = atbash_cipher.encode(phrase) + assert.are.same(expected, result) + end) - it('should not encode punctuation', function() - assert.are.equal('svool', encode('h,e,l,l,o')) - end) + it('encode numbers', function() + local phrase = 'Testing,1 2 3, testing.' + local expected = 'gvhgr mt123 gvhgr mt' + local result = atbash_cipher.encode(phrase) + assert.are.same(expected, result) + end) - it('should not encode numbers', function() - assert.are.equal('sv11l', encode('he11o')) + it('encode deep thought', function() + local phrase = 'Truth is fiction.' + local expected = 'gifgs rhurx grlm' + local result = atbash_cipher.encode(phrase) + assert.are.same(expected, result) + end) + + it('encode all the letters', function() + local phrase = 'The quick brown fox jumps over the lazy dog.' + local expected = 'gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt' + local result = atbash_cipher.encode(phrase) + assert.are.same(expected, result) + end) end) - it('should encode all letters', function() - assert.are - .equal('gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt', encode('The quick brown fox jumps over the lazy dog.')) + describe('decode', function() + it('decode exercism', function() + local phrase = 'vcvix rhn' + local expected = 'exercism' + local result = atbash_cipher.decode(phrase) + assert.are.same(expected, result) + end) + + it('decode a sentence', function() + local phrase = 'zmlyh gzxov rhlug vmzhg vkkrm thglm v' + local expected = 'anobstacleisoftenasteppingstone' + local result = atbash_cipher.decode(phrase) + assert.are.same(expected, result) + end) + + it('decode numbers', function() + local phrase = 'gvhgr mt123 gvhgr mt' + local expected = 'testing123testing' + local result = atbash_cipher.decode(phrase) + assert.are.same(expected, result) + end) + + it('decode all the letters', function() + local phrase = 'gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt' + local expected = 'thequickbrownfoxjumpsoverthelazydog' + local result = atbash_cipher.decode(phrase) + assert.are.same(expected, result) + end) + + it('decode with too many spaces', function() + local phrase = 'vc vix r hn' + local expected = 'exercism' + local result = atbash_cipher.decode(phrase) + assert.are.same(expected, result) + end) + + it('decode with no spaces', function() + local phrase = 'zmlyhgzxovrhlugvmzhgvkkrmthglmv' + local expected = 'anobstacleisoftenasteppingstone' + local result = atbash_cipher.decode(phrase) + assert.are.same(expected, result) + end) end) end)