Skip to content

Commit 943b42b

Browse files
authored
Add practice exercise: atbash-cipher (#106)
1 parent 0c8e8ef commit 943b42b

File tree

10 files changed

+269
-0
lines changed

10 files changed

+269
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,14 @@
218218
"prerequisites": [],
219219
"difficulty": 8
220220
},
221+
{
222+
"slug": "atbash-cipher",
223+
"name": "Atbash Cipher",
224+
"uuid": "171c0743-9e22-4152-af26-831ca097ea04",
225+
"practices": [],
226+
"prerequisites": [],
227+
"difficulty": 8
228+
},
221229
{
222230
"slug": "collatz-conjecture",
223231
"name": "Collatz Conjecture",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Instructions
2+
3+
Create an implementation of the Atbash cipher, an ancient encryption system created in the Middle East.
4+
5+
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.
6+
The first letter is replaced with the last letter, the second with the second-last, and so on.
7+
8+
An Atbash cipher for the Latin alphabet would be as follows:
9+
10+
```text
11+
Plain: abcdefghijklmnopqrstuvwxyz
12+
Cipher: zyxwvutsrqponmlkjihgfedcba
13+
```
14+
15+
It is a very weak cipher because it only has one possible key, and it is a simple mono-alphabetic substitution cipher.
16+
However, this may not have been an issue in the cipher's time.
17+
18+
Ciphertext is written out in groups of fixed length, the traditional group size being 5 letters, leaving numbers unchanged, and punctuation is excluded.
19+
This is to make it harder to guess things based on word boundaries.
20+
All text will be encoded as lowercase letters.
21+
22+
## Examples
23+
24+
- Encoding `test` gives `gvhg`
25+
- Encoding `x123 yes` gives `c123b vh`
26+
- Decoding `gvhg` gives `test`
27+
- Decoding `gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt` gives `thequickbrownfoxjumpsoverthelazydog`
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"jimmytty"
4+
],
5+
"files": {
6+
"solution": [
7+
"atbash-cipher.sql"
8+
],
9+
"test": [
10+
"atbash-cipher_test.sql"
11+
],
12+
"example": [
13+
".meta/example.sql"
14+
]
15+
},
16+
"blurb": "Create an implementation of the Atbash cipher, an ancient encryption system created in the Middle East.",
17+
"source": "Wikipedia",
18+
"source_url": "https://en.wikipedia.org/wiki/Atbash"
19+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
UPDATE "atbash-cipher"
2+
SET result = (
3+
WITH RECURSIVE rcte (i, c, string) AS (
4+
VALUES(1, NULL, (
5+
WITH RECURSIVE encode (phrase, c) AS (
6+
VALUES(LOWER(phrase), NULL)
7+
UNION ALL
8+
SELECT SUBSTR(phrase, 2), SUBSTR(phrase, 1, 1)
9+
FROM encode
10+
WHERE phrase <> ''
11+
)
12+
SELECT GROUP_CONCAT(c, '') AS result
13+
FROM (
14+
SELECT CASE
15+
WHEN (UNICODE(c) BETWEEN UNICODE('a') AND UNICODE('z'))
16+
THEN CHAR(UNICODE('z') - (UNICODE(c) - UNICODE('a')))
17+
WHEN (UNICODE(c) BETWEEN UNICODE('0') AND UNICODE('9'))
18+
THEN c
19+
END AS c
20+
FROM encode
21+
)
22+
WHERE c NOT NULL
23+
))
24+
UNION ALL
25+
SELECT i + 1,
26+
SUBSTR(string, 1, 1) || IIF(i % 5 = 0, ' ', ''),
27+
SUBSTR(string, 2)
28+
FROM rcte
29+
WHERE string <> ''
30+
)
31+
SELECT TRIM(GROUP_CONCAT(c, '')) FROM rcte
32+
)
33+
WHERE property = 'encode'
34+
;
35+
36+
UPDATE "atbash-cipher"
37+
SET result = (
38+
WITH RECURSIVE decode (phrase, c) AS (
39+
VALUES(phrase, NULL)
40+
UNION ALL
41+
SELECT SUBSTR(phrase, 2), SUBSTR(phrase, 1, 1)
42+
FROM decode
43+
WHERE phrase <> ''
44+
)
45+
SELECT GROUP_CONCAT(c, '') AS result
46+
FROM (
47+
SELECT CASE
48+
WHEN (UNICODE(c) BETWEEN UNICODE('a') AND UNICODE('z'))
49+
THEN CHAR(UNICODE('z') - UNICODE(c) + UNICODE('a'))
50+
WHEN (UNICODE(c) BETWEEN UNICODE('0') AND UNICODE('9')) THEN c
51+
END AS c
52+
FROM decode
53+
)
54+
WHERE c NOT NULL
55+
)
56+
WHERE property = 'decode'
57+
;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[2f47ebe1-eab9-4d6b-b3c6-627562a31c77]
13+
description = "encode -> encode yes"
14+
15+
[b4ffe781-ea81-4b74-b268-cc58ba21c739]
16+
description = "encode -> encode no"
17+
18+
[10e48927-24ab-4c4d-9d3f-3067724ace00]
19+
description = "encode -> encode OMG"
20+
21+
[d59b8bc3-509a-4a9a-834c-6f501b98750b]
22+
description = "encode -> encode spaces"
23+
24+
[31d44b11-81b7-4a94-8b43-4af6a2449429]
25+
description = "encode -> encode mindblowingly"
26+
27+
[d503361a-1433-48c0-aae0-d41b5baa33ff]
28+
description = "encode -> encode numbers"
29+
30+
[79c8a2d5-0772-42d4-b41b-531d0b5da926]
31+
description = "encode -> encode deep thought"
32+
33+
[9ca13d23-d32a-4967-a1fd-6100b8742bab]
34+
description = "encode -> encode all the letters"
35+
36+
[bb50e087-7fdf-48e7-9223-284fe7e69851]
37+
description = "decode -> decode exercism"
38+
39+
[ac021097-cd5d-4717-8907-b0814b9e292c]
40+
description = "decode -> decode a sentence"
41+
42+
[18729de3-de74-49b8-b68c-025eaf77f851]
43+
description = "decode -> decode numbers"
44+
45+
[0f30325f-f53b-415d-ad3e-a7a4f63de034]
46+
description = "decode -> decode all the letters"
47+
48+
[39640287-30c6-4c8c-9bac-9d613d1a5674]
49+
description = "decode -> decode with too many spaces"
50+
51+
[b34edf13-34c0-49b5-aa21-0768928000d5]
52+
description = "decode -> decode with no spaces"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- Schema: CREATE TABLE "atbash-cipher" (
2+
-- property TEXT NOT NULL,
3+
-- phrase TEXT NOT NULL,
4+
-- result TEXT
5+
-- );
6+
-- Task: update the atbash-cipher table and set the result based on
7+
-- property and phrase
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
-- Create database:
2+
.read ./create_fixture.sql
3+
4+
-- Read user student solution and save any output as markdown in user_output.md:
5+
.mode markdown
6+
.output user_output.md
7+
.read ./atbash-cipher.sql
8+
.output
9+
10+
-- Create a clean testing environment:
11+
.read ./create_test_table.sql
12+
13+
-- Comparison of user input and the tests updates the status for each test:
14+
UPDATE tests
15+
SET status = 'pass'
16+
FROM (SELECT property, phrase, result FROM "atbash-cipher") AS actual
17+
WHERE (actual.property, actual.phrase, actual.result) = (tests.property, tests.phrase, tests.expected);
18+
19+
-- Update message for failed tests to give helpful information:
20+
UPDATE tests
21+
SET message = (
22+
'Result for "'
23+
|| JSON_OBJECT(
24+
'property', tests.property,
25+
'phrase', tests.phrase
26+
)
27+
|| '"'
28+
|| ' is <' || COALESCE(actual.result, 'NULL')
29+
|| '> but should be <' || tests.expected || '>'
30+
)
31+
FROM (SELECT property, phrase, result FROM "atbash-cipher") AS actual
32+
WHERE (actual.property, actual.phrase) = (tests.property, tests.phrase) AND tests.status = 'fail';
33+
34+
-- Save results to ./output.json (needed by the online test-runner)
35+
.mode json
36+
.once './output.json'
37+
SELECT description, status, message, output, test_code, task_id
38+
FROM tests;
39+
40+
-- Display test results in readable form for the student:
41+
.mode table
42+
SELECT description, status, message
43+
FROM tests;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
DROP TABLE IF EXISTS "atbash-cipher";
2+
CREATE TABLE "atbash-cipher" (
3+
property TEXT NOT NULL,
4+
phrase TEXT NOT NULL,
5+
result TEXT
6+
);
7+
8+
.mode csv
9+
.import ./data.csv "atbash-cipher"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
DROP TABLE IF EXISTS tests;
2+
CREATE TABLE IF NOT EXISTS tests (
3+
-- uuid and description are taken from the test.toml file
4+
uuid TEXT PRIMARY KEY,
5+
description TEXT NOT NULL,
6+
-- The following section is needed by the online test-runner
7+
status TEXT DEFAULT 'fail',
8+
message TEXT,
9+
output TEXT,
10+
test_code TEXT,
11+
task_id INTEGER DEFAULT NULL,
12+
-- Here are columns for the actual tests
13+
property TEXT NOT NULL,
14+
phrase TEXT NOT NULL,
15+
expected TEXT NOT NULL
16+
);
17+
18+
INSERT INTO tests (uuid, description, property, phrase, expected)
19+
VALUES
20+
('2f47ebe1-eab9-4d6b-b3c6-627562a31c77','encode yes','encode','yes','bvh'),
21+
('b4ffe781-ea81-4b74-b268-cc58ba21c739','encode no','encode','no','ml'),
22+
('10e48927-24ab-4c4d-9d3f-3067724ace00','encode OMG','encode','OMG','lnt'),
23+
('d59b8bc3-509a-4a9a-834c-6f501b98750b','encode spaces','encode','O M G','lnt'),
24+
('31d44b11-81b7-4a94-8b43-4af6a2449429','encode mindblowingly','encode','mindblowingly','nrmwy oldrm tob'),
25+
('d503361a-1433-48c0-aae0-d41b5baa33ff','encode numbers','encode','Testing,1 2 3, testing.','gvhgr mt123 gvhgr mt'),
26+
('79c8a2d5-0772-42d4-b41b-531d0b5da926','encode deep thought','encode','Truth is fiction.','gifgs rhurx grlm'),
27+
('9ca13d23-d32a-4967-a1fd-6100b8742bab','encode all the letters','encode','The quick brown fox jumps over the lazy dog.','gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt'),
28+
('bb50e087-7fdf-48e7-9223-284fe7e69851','decode exercism','decode','vcvix rhn','exercism'),
29+
('ac021097-cd5d-4717-8907-b0814b9e292c','decode a sentence','decode','zmlyh gzxov rhlug vmzhg vkkrm thglm v','anobstacleisoftenasteppingstone'),
30+
('18729de3-de74-49b8-b68c-025eaf77f851','decode numbers','decode','gvhgr mt123 gvhgr mt','testing123testing'),
31+
('0f30325f-f53b-415d-ad3e-a7a4f63de034','decode all the letters','decode','gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt','thequickbrownfoxjumpsoverthelazydog'),
32+
('39640287-30c6-4c8c-9bac-9d613d1a5674','decode with too many spaces','decode','vc vix r hn','exercism'),
33+
('b34edf13-34c0-49b5-aa21-0768928000d5','decode with no spaces','decode','zmlyhgzxovrhlugvmzhgvkkrmthglmv','anobstacleisoftenasteppingstone');
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"encode","yes",""
2+
"encode","no",""
3+
"encode","OMG",""
4+
"encode","O M G",""
5+
"encode","mindblowingly",""
6+
"encode","Testing,1 2 3, testing.",""
7+
"encode","Truth is fiction.",""
8+
"encode","The quick brown fox jumps over the lazy dog.",""
9+
"decode","vcvix rhn",""
10+
"decode","zmlyh gzxov rhlug vmzhg vkkrm thglm v",""
11+
"decode","gvhgr mt123 gvhgr mt",""
12+
"decode","gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt",""
13+
"decode","vc vix r hn",""
14+
"decode","zmlyhgzxovrhlugvmzhgvkkrmthglmv",""

0 commit comments

Comments
 (0)