Skip to content

Commit 38771e5

Browse files
authored
Add practice exercise: series (#132)
1 parent 11c486c commit 38771e5

File tree

10 files changed

+243
-0
lines changed

10 files changed

+243
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,14 @@
394394
"prerequisites": [],
395395
"difficulty": 8
396396
},
397+
{
398+
"slug": "series",
399+
"name": "Series",
400+
"uuid": "83a5f56d-b75b-424b-84e6-22609cff8da5",
401+
"practices": [],
402+
"prerequisites": [],
403+
"difficulty": 8
404+
},
397405
{
398406
"slug": "state-of-tic-tac-toe",
399407
"name": "State of Tic-Tac-Toe",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Instructions
2+
3+
Given a string of digits, output all the contiguous substrings of length `n` in that string in the order that they appear.
4+
5+
For example, the string "49142" has the following 3-digit series:
6+
7+
- "491"
8+
- "914"
9+
- "142"
10+
11+
And the following 4-digit series:
12+
13+
- "4914"
14+
- "9142"
15+
16+
And if you ask for a 6-digit series from a 5-digit string, you deserve whatever you get.
17+
18+
Note that these series are only required to occupy _adjacent positions_ in the input;
19+
the digits need not be _numerically consecutive_.
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+
"series.sql"
8+
],
9+
"test": [
10+
"series_test.sql"
11+
],
12+
"example": [
13+
".meta/example.sql"
14+
]
15+
},
16+
"blurb": "Given a string of digits, output all the contiguous substrings of length `n` in that string.",
17+
"source": "A subset of the Problem 8 at Project Euler",
18+
"source_url": "https://projecteuler.net/problem=8"
19+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
UPDATE series
2+
SET error = 'slice length cannot be zero'
3+
WHERE slice_length = 0
4+
AND error ISNULL
5+
;
6+
UPDATE series
7+
SET error = 'series cannot be empty'
8+
WHERE input = ''
9+
AND error ISNULL
10+
;
11+
UPDATE series
12+
SET error = 'slice length cannot be greater than series length'
13+
WHERE slice_length > LENGTH(input)
14+
AND error ISNULL
15+
;
16+
UPDATE series
17+
SET error = 'slice length cannot be negative'
18+
WHERE slice_length < 0
19+
AND error ISNULL
20+
;
21+
22+
UPDATE series
23+
SET result = (
24+
WITH RECURSIVE to_series (digits, serie) AS (
25+
VALUES (input, NULL)
26+
UNION ALL
27+
SELECT SUBSTR(digits, 2), SUBSTR(digits, 1, slice_length)
28+
FROM to_series
29+
WHERE digits <> ''
30+
)
31+
SELECT GROUP_CONCAT(serie, CHAR(10)) AS series
32+
FROM to_series WHERE LENGTH(serie) = slice_length
33+
)
34+
WHERE error ISNULL
35+
;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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+
[7ae7a46a-d992-4c2a-9c15-a112d125ebad]
13+
description = "slices of one from one"
14+
15+
[3143b71d-f6a5-4221-aeae-619f906244d2]
16+
description = "slices of one from two"
17+
18+
[dbb68ff5-76c5-4ccd-895a-93dbec6d5805]
19+
description = "slices of two"
20+
21+
[19bbea47-c987-4e11-a7d1-e103442adf86]
22+
description = "slices of two overlap"
23+
24+
[8e17148d-ba0a-4007-a07f-d7f87015d84c]
25+
description = "slices can include duplicates"
26+
27+
[bd5b085e-f612-4f81-97a8-6314258278b0]
28+
description = "slices of a long series"
29+
30+
[6d235d85-46cf-4fae-9955-14b6efef27cd]
31+
description = "slice length is too large"
32+
33+
[d7957455-346d-4e47-8e4b-87ed1564c6d7]
34+
description = "slice length is way too large"
35+
36+
[d34004ad-8765-4c09-8ba1-ada8ce776806]
37+
description = "slice length cannot be zero"
38+
39+
[10ab822d-8410-470a-a85d-23fbeb549e54]
40+
description = "slice length cannot be negative"
41+
42+
[c7ed0812-0e4b-4bf3-99c4-28cbbfc246a2]
43+
description = "empty series is invalid"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
DROP TABLE IF EXISTS series;
2+
CREATE TABLE series (
3+
input TEXT NOT NULL,
4+
slice_length INTEGER NOT NULL,
5+
result TEXT ,
6+
error TEXT
7+
);
8+
9+
.mode csv
10+
.import ./data.csv series
11+
12+
UPDATE series SET result = NULL, error = 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+
input TEXT NOT NULL,
14+
slice_length INTEGER NOT NULL,
15+
expected_result TEXT,
16+
expected_error TEXT
17+
);
18+
19+
INSERT INTO tests (uuid, description, input, slice_length, expected_result, expected_error)
20+
VALUES
21+
('7ae7a46a-d992-4c2a-9c15-a112d125ebad', 'slices of one from one', '1', 1, '1', NULL),
22+
('3143b71d-f6a5-4221-aeae-619f906244d2', 'slices of one from two', '12', 1, '1\n2', NULL),
23+
('dbb68ff5-76c5-4ccd-895a-93dbec6d5805', 'slices of two', '35', 2, '35', NULL),
24+
('19bbea47-c987-4e11-a7d1-e103442adf86', 'slices of two overlap', '9142', 2, '91\n14\n42', NULL),
25+
('8e17148d-ba0a-4007-a07f-d7f87015d84c', 'slices can include duplicates', '777777', 3, '777\n777\n777\n777', NULL),
26+
('bd5b085e-f612-4f81-97a8-6314258278b0', 'slices of a long series', '918493904243', 5, '91849\n18493\n84939\n49390\n93904\n39042\n90424\n04243', NULL),
27+
('6d235d85-46cf-4fae-9955-14b6efef27cd', 'slice length is too large', '12345', 6, NULL, 'slice length cannot be greater than series length'),
28+
('d7957455-346d-4e47-8e4b-87ed1564c6d7', 'slice length is way too large', '12345', 42, NULL, 'slice length cannot be greater than series length'),
29+
('d34004ad-8765-4c09-8ba1-ada8ce776806', 'slice length cannot be zero', '12345', 0, NULL, 'slice length cannot be zero'),
30+
('10ab822d-8410-470a-a85d-23fbeb549e54', 'slice length cannot be negative', '123', -1, NULL, 'slice length cannot be negative'),
31+
('c7ed0812-0e4b-4bf3-99c4-28cbbfc246a2', 'empty series is invalid', '', 1, NULL, 'series cannot be empty');
32+
33+
UPDATE tests SET expected_result = REPLACE(expected_result, '\n', CHAR(10));

exercises/practice/series/data.csv

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"1",1,,
2+
"12",1,,
3+
"35",2,,
4+
"9142",2,,
5+
"777777",3,,
6+
"918493904243",5,,
7+
"12345",6,,
8+
"12345",42,,
9+
"12345",0,,
10+
"123",-1,,
11+
"",1,,

exercises/practice/series/series.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- Schema:
2+
-- CREATE TABLE series (
3+
-- input TEXT NOT NULL,
4+
-- slice_length INTEGER NOT NULL,
5+
-- result TEXT ,
6+
-- error TEXT
7+
-- );
8+
--
9+
-- Task: update the series table and set the result or the error columns based on the input.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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 ./series.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 input, slice_length, result, error FROM series) AS actual
17+
WHERE (actual.input, actual.slice_length) = (tests.input, tests.slice_length)
18+
AND (actual.result = tests.expected_result
19+
OR COALESCE(actual.result, tests.expected_result) ISNULL)
20+
AND (actual.error = tests.expected_error
21+
OR COALESCE(actual.error, tests.expected_error) ISNULL);
22+
23+
-- Update message for failed tests to give helpful information:
24+
UPDATE tests
25+
SET message = (
26+
'Result for "'
27+
|| PRINTF('input=''%s'' and slice_length=''%s''',
28+
actual.input,
29+
actual.slice_length)
30+
|| '"'
31+
|| ' is <'
32+
|| PRINTF('result=%s and error="%s"',
33+
COALESCE(actual.result, 'NULL'),
34+
COALESCE(actual.error, 'NULL'))
35+
|| '> but should be <'
36+
|| PRINTF('result=%s and error="%s"',
37+
COALESCE(tests.expected_result, '"NULL"'),
38+
COALESCE(tests.expected_error, 'NULL'))
39+
|| '>'
40+
)
41+
FROM (SELECT input, slice_length, result, error FROM series) AS actual
42+
WHERE (actual.input, actual.slice_length) = (tests.input, tests.slice_length)
43+
AND tests.status = 'fail';
44+
45+
-- Save results to ./output.json (needed by the online test-runner)
46+
.mode json
47+
.once './output.json'
48+
SELECT description, status, message, output, test_code, task_id
49+
FROM tests;
50+
51+
-- Display test results in readable form for the student:
52+
.mode table
53+
SELECT description, status, message
54+
FROM tests;

0 commit comments

Comments
 (0)