Skip to content

Commit 1a146b2

Browse files
authored
Add practice exercise: run-length-encoding (#134)
1 parent e356eec commit 1a146b2

File tree

10 files changed

+292
-0
lines changed

10 files changed

+292
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,14 @@
418418
"prerequisites": [],
419419
"difficulty": 8
420420
},
421+
{
422+
"slug": "run-length-encoding",
423+
"name": "Run-Length Encoding",
424+
"uuid": "065feae7-f6fc-46b9-a226-d3d9df9d192b",
425+
"practices": [],
426+
"prerequisites": [],
427+
"difficulty": 8
428+
},
421429
{
422430
"slug": "scrabble-score",
423431
"name": "Scrabble Score",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Instructions
2+
3+
Implement run-length encoding and decoding.
4+
5+
Run-length encoding (RLE) is a simple form of data compression, where runs (consecutive data elements) are replaced by just one data value and count.
6+
7+
For example we can represent the original 53 characters with only 13.
8+
9+
```text
10+
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" -> "12WB12W3B24WB"
11+
```
12+
13+
RLE allows the original data to be perfectly reconstructed from the compressed data, which makes it a lossless data compression.
14+
15+
```text
16+
"AABCCCDEEEE" -> "2AB3CD4E" -> "AABCCCDEEEE"
17+
```
18+
19+
For simplicity, you can assume that the unencoded string will only contain the letters A through Z (either lower or upper case) and whitespace.
20+
This way data to be encoded will never contain any numbers and numbers inside data to be decoded always represent the count for the following character.
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+
"run-length-encoding.sql"
8+
],
9+
"test": [
10+
"run-length-encoding_test.sql"
11+
],
12+
"example": [
13+
".meta/example.sql"
14+
]
15+
},
16+
"blurb": "Implement run-length encoding and decoding.",
17+
"source": "Wikipedia",
18+
"source_url": "https://en.wikipedia.org/wiki/Run-length_encoding"
19+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
UPDATE "run-length-encoding"
2+
SET result = ''
3+
WHERE string = ''
4+
;
5+
6+
UPDATE "run-length-encoding"
7+
SET result = (
8+
WITH RECURSIVE rcte (input, chr, next_chr, idx, grp) AS (
9+
VALUES (string, NULL, NULL, 0, 1)
10+
UNION ALL
11+
SELECT SUBSTR(input, 2),
12+
SUBSTR(input, 1, 1),
13+
SUBSTR(input, 2, 1),
14+
idx + 1,
15+
IIF(chr <> next_chr, grp + 1, grp)
16+
FROM rcte
17+
WHERE input <> ''
18+
)
19+
SELECT GROUP_CONCAT(PRINTF('%s%s', IIF(cnt = 1, '', cnt), chr), '')
20+
FROM (
21+
SELECT COUNT(*) cnt, chr
22+
FROM rcte
23+
WHERE chr NOT NULL
24+
GROUP BY chr, grp
25+
ORDER BY idx
26+
)
27+
)
28+
WHERE property = 'encode'
29+
AND string <> ''
30+
;
31+
32+
UPDATE "run-length-encoding"
33+
SET result = (
34+
WITH RECURSIVE rcte (input, num, chr) AS (
35+
VALUES (REPLACE(string, ' ', CHAR(7)), NULL, NULL)
36+
UNION ALL
37+
SELECT SUBSTR(LTRIM(input, CAST(input AS INT)), 2),
38+
CAST(input AS INT),
39+
SUBSTR(LTRIM(input, CAST(input AS INT)), 1, 1)
40+
FROM rcte
41+
WHERE input <> ''
42+
)
43+
SELECT REPLACE(GROUP_CONCAT(PRINTF('%.*c', num, chr), ''), CHAR(7), ' ')
44+
FROM rcte
45+
WHERE chr NOT NULL
46+
)
47+
WHERE property = 'decode'
48+
AND string <> ''
49+
;
50+
51+
UPDATE "run-length-encoding"
52+
SET result = (
53+
WITH RECURSIVE rcte (input, num, chr) AS (
54+
VALUES (REPLACE(
55+
(
56+
WITH RECURSIVE rcte (input, chr, next_chr, idx, grp) AS (
57+
VALUES (string, NULL, NULL, 0, 1)
58+
UNION ALL
59+
SELECT SUBSTR(input, 2),
60+
SUBSTR(input, 1, 1),
61+
SUBSTR(input, 2, 1),
62+
idx + 1,
63+
IIF(chr <> next_chr, grp + 1, grp)
64+
FROM rcte
65+
WHERE input <> ''
66+
)
67+
SELECT GROUP_CONCAT(PRINTF('%s%s', IIF(cnt = 1, '', cnt), chr), '')
68+
FROM (
69+
SELECT COUNT(*) cnt, chr
70+
FROM rcte
71+
WHERE chr NOT NULL
72+
GROUP BY chr, grp
73+
ORDER BY idx
74+
)
75+
), ' ', CHAR(7)), NULL, NULL)
76+
UNION ALL
77+
SELECT SUBSTR(LTRIM(input, CAST(input AS INT)), 2),
78+
CAST(input AS INT),
79+
SUBSTR(LTRIM(input, CAST(input AS INT)), 1, 1)
80+
FROM rcte
81+
WHERE input <> ''
82+
)
83+
SELECT REPLACE(GROUP_CONCAT(PRINTF('%.*c', num, chr), ''), CHAR(7), ' ')
84+
FROM rcte
85+
WHERE chr NOT NULL
86+
)
87+
WHERE property = 'consistency'
88+
;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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+
[ad53b61b-6ffc-422f-81a6-61f7df92a231]
13+
description = "run-length encode a string -> empty string"
14+
15+
[52012823-b7e6-4277-893c-5b96d42f82de]
16+
description = "run-length encode a string -> single characters only are encoded without count"
17+
18+
[b7868492-7e3a-415f-8da3-d88f51f80409]
19+
description = "run-length encode a string -> string with no single characters"
20+
21+
[859b822b-6e9f-44d6-9c46-6091ee6ae358]
22+
description = "run-length encode a string -> single characters mixed with repeated characters"
23+
24+
[1b34de62-e152-47be-bc88-469746df63b3]
25+
description = "run-length encode a string -> multiple whitespace mixed in string"
26+
27+
[abf176e2-3fbd-40ad-bb2f-2dd6d4df721a]
28+
description = "run-length encode a string -> lowercase characters"
29+
30+
[7ec5c390-f03c-4acf-ac29-5f65861cdeb5]
31+
description = "run-length decode a string -> empty string"
32+
33+
[ad23f455-1ac2-4b0e-87d0-b85b10696098]
34+
description = "run-length decode a string -> single characters only"
35+
36+
[21e37583-5a20-4a0e-826c-3dee2c375f54]
37+
description = "run-length decode a string -> string with no single characters"
38+
39+
[1389ad09-c3a8-4813-9324-99363fba429c]
40+
description = "run-length decode a string -> single characters with repeated characters"
41+
42+
[3f8e3c51-6aca-4670-b86c-a213bf4706b0]
43+
description = "run-length decode a string -> multiple whitespace mixed in string"
44+
45+
[29f721de-9aad-435f-ba37-7662df4fb551]
46+
description = "run-length decode a string -> lowercase string"
47+
48+
[2a762efd-8695-4e04-b0d6-9736899fbc16]
49+
description = "encode and then decode -> encode followed by decode gives original string"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
DROP TABLE IF EXISTS "run-length-encoding";
2+
CREATE TABLE "run-length-encoding" (
3+
property TEXT NOT NULL,
4+
string TEXT NOT NULL,
5+
result TEXT
6+
);
7+
8+
.mode csv
9+
.import ./data.csv "run-length-encoding"
10+
11+
UPDATE "run-length-encoding" SET result = NULL;
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+
string TEXT NOT NULL,
15+
expected TEXT NOT NULL
16+
);
17+
18+
INSERT INTO tests (uuid, description, property, string, expected)
19+
VALUES
20+
('ad53b61b-6ffc-422f-81a6-61f7df92a231', 'empty string', 'encode', '', ''),
21+
('52012823-b7e6-4277-893c-5b96d42f82de', 'single characters only are encoded without count', 'encode', 'XYZ', 'XYZ'),
22+
('b7868492-7e3a-415f-8da3-d88f51f80409', 'string with no single characters', 'encode', 'AABBBCCCC', '2A3B4C'),
23+
('859b822b-6e9f-44d6-9c46-6091ee6ae358', 'single characters mixed with repeated characters', 'encode', 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB', '12WB12W3B24WB'),
24+
('1b34de62-e152-47be-bc88-469746df63b3', 'multiple whitespace mixed in string', 'encode', ' hsqq qww ', '2 hs2q q2w2 '),
25+
('abf176e2-3fbd-40ad-bb2f-2dd6d4df721a', 'lowercase characters', 'encode', 'aabbbcccc', '2a3b4c'),
26+
('7ec5c390-f03c-4acf-ac29-5f65861cdeb5', 'empty string', 'decode', '', ''),
27+
('ad23f455-1ac2-4b0e-87d0-b85b10696098', 'single characters only', 'decode', 'XYZ', 'XYZ'),
28+
('21e37583-5a20-4a0e-826c-3dee2c375f54', 'string with no single characters', 'decode', '2A3B4C', 'AABBBCCCC'),
29+
('1389ad09-c3a8-4813-9324-99363fba429c', 'single characters with repeated characters', 'decode', '12WB12W3B24WB', 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB'),
30+
('3f8e3c51-6aca-4670-b86c-a213bf4706b0', 'multiple whitespace mixed in string', 'decode', '2 hs2q q2w2 ', ' hsqq qww '),
31+
('29f721de-9aad-435f-ba37-7662df4fb551', 'lowercase string', 'decode', '2a3b4c', 'aabbbcccc'),
32+
('2a762efd-8695-4e04-b0d6-9736899fbc16', 'encode followed by decode gives original string', 'consistency', 'zzz ZZ zZ', 'zzz ZZ zZ');
33+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"encode","",
2+
"encode","XYZ",
3+
"encode","AABBBCCCC",
4+
"encode","WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB",
5+
"encode"," hsqq qww ",
6+
"encode","aabbbcccc",
7+
"decode","",
8+
"decode","XYZ",
9+
"decode","2A3B4C",
10+
"decode","12WB12W3B24WB",
11+
"decode","2 hs2q q2w2 ",
12+
"decode","2a3b4c",
13+
"consistency","zzz ZZ zZ",
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- Schema:
2+
-- CREATE TABLE "run-length-encoding" (
3+
-- property TEXT NOT NULL,
4+
-- string TEXT NOT NULL,
5+
-- result TEXT
6+
-- );
7+
--
8+
-- Task: update the run-length-encoding table and set the result based on the property and string.
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 ./run-length-encoding.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, string, result FROM "run-length-encoding") AS actual
17+
WHERE (actual.property, actual.string, actual.result) =
18+
( tests.property, tests.string, tests.expected);
19+
20+
-- Update message for failed tests to give helpful information:
21+
UPDATE tests
22+
SET message = (
23+
'Result for "'
24+
|| PRINTF('property=%s, string=%s', tests.property, tests.string)
25+
|| '"'
26+
|| ' is <' || COALESCE(actual.result, 'NULL')
27+
|| '> but should be <' || tests.expected || '>'
28+
)
29+
FROM (SELECT property, string, result FROM "run-length-encoding") AS actual
30+
WHERE (actual.property, actual.string) =
31+
( tests.property, tests.string)
32+
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;

0 commit comments

Comments
 (0)