Skip to content

* add practice exercise: proverb #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,14 @@
"prerequisites": [],
"difficulty": 8
},
{
"slug": "proverb",
"name": "Proverb",
"uuid": "10c51241-2399-4a0c-84cf-390a000f3c3b",
"practices": [],
"prerequisites": [],
"difficulty": 8
},
{
"slug": "rest-api",
"name": "REST API",
Expand Down
7 changes: 7 additions & 0 deletions exercises/practice/proverb/.docs/instructions.append.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SQLite-specific instructions

## JSON documentation

[JSON Functions And Operators][json-docs]

[json-docs]: https://www.sqlite.org/json1.html
19 changes: 19 additions & 0 deletions exercises/practice/proverb/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Instructions

For want of a horseshoe nail, a kingdom was lost, or so the saying goes.

Given a list of inputs, generate the relevant proverb.
For example, given the list `["nail", "shoe", "horse", "rider", "message", "battle", "kingdom"]`, you will output the full text of this proverbial rhyme:

```text
For want of a nail the shoe was lost.
For want of a shoe the horse was lost.
For want of a horse the rider was lost.
For want of a rider the message was lost.
For want of a message the battle was lost.
For want of a battle the kingdom was lost.
And all for the want of a nail.
```

Note that the list of inputs may vary; your solution should be able to handle lists of arbitrary length and content.
No line of the output text should be a static, unchanging string; all should vary according to the input given.
19 changes: 19 additions & 0 deletions exercises/practice/proverb/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"jimmytty"
],
"files": {
"solution": [
"proverb.sql"
],
"test": [
"proverb_test.sql"
],
"example": [
".meta/example.sql"
]
},
"blurb": "For want of a horseshoe nail, a kingdom was lost, or so the saying goes. Output the full text of this proverbial rhyme.",
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/For_Want_of_a_Nail"
}
33 changes: 33 additions & 0 deletions exercises/practice/proverb/.meta/example.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
UPDATE proverb
SET result = ''
WHERE JSON(strings) = '[]'
;

UPDATE proverb
SET result = (
WITH RECURSIVE to_pieces (strings, i, len, piece) AS (
VALUES(strings, 0, JSON_ARRAY_LENGTH(strings) - 1, NULL)
UNION ALL
SELECT strings, i+1, len,
PRINTF(
'For want of a %s the %s was lost.',
JSON_EXTRACT(strings, PRINTF('$[%d]', i)),
JSON_EXTRACT(strings, PRINTF('$[%d]', i+1))
)
FROM to_pieces
WHERE i < len
)
SELECT group_concat(piece, CHAR(10))
FROM (
SELECT piece
FROM to_pieces
WHERE piece NOTNULL
UNION ALL
SELECT PRINTF(
'And all for the want of a %s.',
JSON_EXTRACT(strings, '$[0]')
)
)
)
WHERE result ISNULL
;
28 changes: 28 additions & 0 deletions exercises/practice/proverb/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# 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.

[e974b73e-7851-484f-8d6d-92e07fe742fc]
description = "zero pieces"

[2fcd5f5e-8b82-4e74-b51d-df28a5e0faa4]
description = "one piece"

[d9d0a8a1-d933-46e2-aa94-eecf679f4b0e]
description = "two pieces"

[c95ef757-5e94-4f0d-a6cb-d2083f5e5a83]
description = "three pieces"

[433fb91c-35a2-4d41-aeab-4de1e82b2126]
description = "full proverb"

[c1eefa5a-e8d9-41c7-91d4-99fab6d6b9f7]
description = "four pieces modernized"
10 changes: 10 additions & 0 deletions exercises/practice/proverb/create_fixture.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DROP TABLE IF EXISTS proverb;
CREATE TABLE proverb (
strings TEXT NOT NULL, -- json array containing the input words
result TEXT
);

.mode csv
.import ./data.csv proverb

UPDATE proverb SET result = NULL;
26 changes: 26 additions & 0 deletions exercises/practice/proverb/create_test_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
DROP TABLE IF EXISTS tests;
CREATE TABLE IF NOT EXISTS tests (
-- uuid and description are taken from the test.toml file
uuid TEXT PRIMARY KEY,
description TEXT NOT NULL,
-- The following section is needed by the online test-runner
status TEXT DEFAULT 'fail',
message TEXT,
output TEXT,
test_code TEXT,
task_id INTEGER DEFAULT NULL,
-- Here are columns for the actual tests
strings TEXT NOT NULL, -- json array
expected TEXT NOT NULL
);

INSERT INTO tests (uuid, description, strings, expected)
VALUES
('e974b73e-7851-484f-8d6d-92e07fe742fc', 'zero pieces', '[]', ''),
('2fcd5f5e-8b82-4e74-b51d-df28a5e0faa4', 'one piece', '["nail"]', 'And all for the want of a nail.'),
('d9d0a8a1-d933-46e2-aa94-eecf679f4b0e', 'two pieces', '["nail","shoe"]', 'For want of a nail the shoe was lost.\nAnd all for the want of a nail.'),
('c95ef757-5e94-4f0d-a6cb-d2083f5e5a83', 'three pieces', '["nail","shoe","horse"]', 'For want of a nail the shoe was lost.\nFor want of a shoe the horse was lost.\nAnd all for the want of a nail.'),
('433fb91c-35a2-4d41-aeab-4de1e82b2126', 'full proverb', '["nail","shoe","horse","rider","message","battle","kingdom"]', 'For want of a nail the shoe was lost.\nFor want of a shoe the horse was lost.\nFor want of a horse the rider was lost.\nFor want of a rider the message was lost.\nFor want of a message the battle was lost.\nFor want of a battle the kingdom was lost.\nAnd all for the want of a nail.'),
('c1eefa5a-e8d9-41c7-91d4-99fab6d6b9f7', 'four pieces modernized', '["pin","gun","soldier","battle"]', 'For want of a pin the gun was lost.\nFor want of a gun the soldier was lost.\nFor want of a soldier the battle was lost.\nAnd all for the want of a pin.');

UPDATE tests SET expected = REPLACE(expected, '\n', CHAR(10));
6 changes: 6 additions & 0 deletions exercises/practice/proverb/data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"[]",
"[""nail""]",
"[""nail"",""shoe""]",
"[""nail"",""shoe"",""horse""]",
"[""nail"",""shoe"",""horse"",""rider"",""message"",""battle"",""kingdom""]",
"[""pin"",""gun"",""soldier"",""battle""]",
7 changes: 7 additions & 0 deletions exercises/practice/proverb/proverb.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- Schema:
-- CREATE TABLE proverb (
-- strings TEXT NOT NULL, -- json array containing the input words
-- result TEXT
-- );
--
-- Task: update proverb table and set result column based on the strings.
40 changes: 40 additions & 0 deletions exercises/practice/proverb/proverb_test.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
-- Create database:
.read ./create_fixture.sql

-- Read user student solution and save any output as markdown in user_output.md:
.mode markdown
.output user_output.md
.read ./proverb.sql
.output

-- Create a clean testing environment:
.read ./create_test_table.sql

-- Comparison of user input and the tests updates the status for each test:
UPDATE tests
SET status = 'pass'
FROM (SELECT strings, result FROM proverb) AS actual
WHERE (actual.strings, actual.result) = (tests.strings, tests.expected);

-- Update message for failed tests to give helpful information:
UPDATE tests
SET message = (
'Result for "'
|| tests.strings
|| '"'
|| ' is <' || COALESCE(actual.result, 'NULL')
|| '> but should be <' || tests.expected || '>'
)
FROM (SELECT strings, result FROM proverb) AS actual
WHERE actual.strings = tests.strings AND tests.status = 'fail';

-- Save results to ./output.json (needed by the online test-runner)
.mode json
.once './output.json'
SELECT description, status, message, output, test_code, task_id
FROM tests;

-- Display test results in readable form for the student:
.mode table
SELECT description, status, message
FROM tests;