diff --git a/config.json b/config.json index e93818d..2db6e13 100644 --- a/config.json +++ b/config.json @@ -50,6 +50,14 @@ "prerequisites": [], "difficulty": 1 }, + { + "slug": "bottle-song", + "name": "Bottle Song", + "uuid": "a3961350-2053-4e08-bf5d-fe9b43cb753c", + "practices": [], + "prerequisites": [], + "difficulty": 2 + }, { "slug": "darts", "name": "Darts", diff --git a/exercises/practice/bottle-song/.docs/instructions.md b/exercises/practice/bottle-song/.docs/instructions.md new file mode 100644 index 0000000..febdfc8 --- /dev/null +++ b/exercises/practice/bottle-song/.docs/instructions.md @@ -0,0 +1,57 @@ +# Instructions + +Recite the lyrics to that popular children's repetitive song: Ten Green Bottles. + +Note that not all verses are identical. + +```text +Ten green bottles hanging on the wall, +Ten green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be nine green bottles hanging on the wall. + +Nine green bottles hanging on the wall, +Nine green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be eight green bottles hanging on the wall. + +Eight green bottles hanging on the wall, +Eight green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be seven green bottles hanging on the wall. + +Seven green bottles hanging on the wall, +Seven green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be six green bottles hanging on the wall. + +Six green bottles hanging on the wall, +Six green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be five green bottles hanging on the wall. + +Five green bottles hanging on the wall, +Five green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be four green bottles hanging on the wall. + +Four green bottles hanging on the wall, +Four green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be three green bottles hanging on the wall. + +Three green bottles hanging on the wall, +Three green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be two green bottles hanging on the wall. + +Two green bottles hanging on the wall, +Two green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There'll be one green bottle hanging on the wall. + +One green bottle hanging on the wall, +One green bottle hanging on the wall, +And if one green bottle should accidentally fall, +There'll be no green bottles hanging on the wall. +``` diff --git a/exercises/practice/bottle-song/.meta/config.json b/exercises/practice/bottle-song/.meta/config.json new file mode 100644 index 0000000..60055d1 --- /dev/null +++ b/exercises/practice/bottle-song/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "jimmytty" + ], + "files": { + "solution": [ + "bottle-song.sql" + ], + "test": [ + "bottle-song_test.sql" + ], + "example": [ + ".meta/example.sql" + ] + }, + "blurb": "Produce the lyrics to the popular children's repetitive song: Ten Green Bottles.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Ten_Green_Bottles" +} diff --git a/exercises/practice/bottle-song/.meta/example.sql b/exercises/practice/bottle-song/.meta/example.sql new file mode 100644 index 0000000..d4ad548 --- /dev/null +++ b/exercises/practice/bottle-song/.meta/example.sql @@ -0,0 +1,48 @@ +DROP TABLE IF EXISTS pairs; +CREATE TEMPORARY TABLE pairs ( + verse_number INTEGER NOT NULL, + start_number TEXT NOT NULL, + next_number TEXT NOT NULL +); +INSERT INTO pairs (verse_number, start_number, next_number) +VALUES (10, 'Ten' , 'Nine' ), + ( 9, 'Nine' , 'Eight'), + ( 8, 'Eight', 'Seven'), + ( 7, 'Seven', 'Six' ), + ( 6, 'Six' , 'Five' ), + ( 5, 'Five' , 'Four' ), + ( 4, 'Four' , 'Three'), + ( 3, 'Three', 'Two' ), + ( 2, 'Two' , 'One' ), + ( 1, 'One' , 'no' ); + +DROP TABLE IF EXISTS verses; +CREATE TABLE verses AS + SELECT verse_number, + PRINTF('%s green bottles hanging on the wall,' || CHAR(10), start_number) || + PRINTF('%s green bottles hanging on the wall,' || CHAR(10), start_number) || + 'And if one green bottle should accidentally fall,' || CHAR(10) || + PRINTF('There''ll be %s green bottles hanging on the wall.',LOWER(next_number)) AS verse + FROM pairs +; + +UPDATE verses + SET verse = REPLACE(verse, 'be one green bottles', 'be one green bottle') + WHERE verse_number = 2; +UPDATE verses + SET verse = REPLACE(verse, 'One green bottles', 'One green bottle') + WHERE verse_number = 1; + + +UPDATE "bottle-song" + SET result = ( + SELECT GROUP_CONCAT(verse, CHAR(10)||CHAR(10)) + FROM ( + SELECT verse + FROM verses + WHERE verse_number <= start_bottles + AND verse_number > start_bottles - take_down + ORDER BY verse_number DESC + ) + ) +; diff --git a/exercises/practice/bottle-song/.meta/tests.toml b/exercises/practice/bottle-song/.meta/tests.toml new file mode 100644 index 0000000..1f6e40a --- /dev/null +++ b/exercises/practice/bottle-song/.meta/tests.toml @@ -0,0 +1,31 @@ +# 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. + +[d4ccf8fc-01dc-48c0-a201-4fbeb30f2d03] +description = "verse -> single verse -> first generic verse" + +[0f0aded3-472a-4c64-b842-18d4f1f5f030] +description = "verse -> single verse -> last generic verse" + +[f61f3c97-131f-459e-b40a-7428f3ed99d9] +description = "verse -> single verse -> verse with 2 bottles" + +[05eadba9-5dbd-401e-a7e8-d17cc9baa8e0] +description = "verse -> single verse -> verse with 1 bottle" + +[a4a28170-83d6-4dc1-bd8b-319b6abb6a80] +description = "lyrics -> multiple verses -> first two verses" + +[3185d438-c5ac-4ce6-bcd3-02c9ff1ed8db] +description = "lyrics -> multiple verses -> last three verses" + +[28c1584a-0e51-4b65-9ae2-fbc0bf4bbb28] +description = "lyrics -> multiple verses -> all verses" diff --git a/exercises/practice/bottle-song/bottle-song.sql b/exercises/practice/bottle-song/bottle-song.sql new file mode 100644 index 0000000..22b804e --- /dev/null +++ b/exercises/practice/bottle-song/bottle-song.sql @@ -0,0 +1,8 @@ +-- Schema: +-- CREATE TABLE "bottle-song" ( +-- start_bottles INTEGER NOT NULL, +-- take_down INTEGER NOT NULL, +-- result TEXT +-- ); +-- Task: update bottle-song table and set the result based on the +-- start_bottles and take_down. diff --git a/exercises/practice/bottle-song/bottle-song_test.sql b/exercises/practice/bottle-song/bottle-song_test.sql new file mode 100644 index 0000000..997e7a7 --- /dev/null +++ b/exercises/practice/bottle-song/bottle-song_test.sql @@ -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 ./bottle-song.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 start_bottles, take_down, result FROM "bottle-song") AS actual +WHERE (actual.start_bottles, actual.take_down, actual.result) = (tests.start_bottles, tests.take_down, tests.expected); + +-- Update message for failed tests to give helpful information: +UPDATE tests +SET message = ( + 'Result for "' + || PRINTF('start_bottles=%d, take_down=%d', tests.start_bottles,tests.take_down) + || '"' + || ' is <' || COALESCE(actual.result, 'NULL') + || '> but should be <' || tests.expected || '>' +) +FROM (SELECT start_bottles, take_down, result FROM "bottle-song") AS actual +WHERE (actual.start_bottles, actual.take_down) = (tests.start_bottles, tests.take_down) 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; diff --git a/exercises/practice/bottle-song/create_fixture.sql b/exercises/practice/bottle-song/create_fixture.sql new file mode 100644 index 0000000..3fd5dab --- /dev/null +++ b/exercises/practice/bottle-song/create_fixture.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS "bottle-song"; +CREATE TABLE "bottle-song" ( + start_bottles INTEGER NOT NULL, + take_down INTEGER NOT NULL, + result TEXT +); + +.mode csv +.import ./data.csv "bottle-song" diff --git a/exercises/practice/bottle-song/create_test_table.sql b/exercises/practice/bottle-song/create_test_table.sql new file mode 100644 index 0000000..34ee774 --- /dev/null +++ b/exercises/practice/bottle-song/create_test_table.sql @@ -0,0 +1,107 @@ +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 + start_bottles INTEGER NOT NULL, + take_down INTEGER NOT NULL, + expected TEXT NOT NULL +); + +INSERT INTO tests (uuid, description, start_bottles, take_down, expected) +VALUES + ('d4ccf8fc-01dc-48c0-a201-4fbeb30f2d03','first generic verse',10,1,'Ten green bottles hanging on the wall, +Ten green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be nine green bottles hanging on the wall.'), + ('0f0aded3-472a-4c64-b842-18d4f1f5f030','last generic verse',3,1,'Three green bottles hanging on the wall, +Three green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be two green bottles hanging on the wall.'), + ('f61f3c97-131f-459e-b40a-7428f3ed99d9','verse with 2 bottles',2,1,'Two green bottles hanging on the wall, +Two green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be one green bottle hanging on the wall.'), + ('05eadba9-5dbd-401e-a7e8-d17cc9baa8e0','verse with 1 bottle',1,1,'One green bottle hanging on the wall, +One green bottle hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be no green bottles hanging on the wall.'), + ('a4a28170-83d6-4dc1-bd8b-319b6abb6a80','first two verses',10,2,'Ten green bottles hanging on the wall, +Ten green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be nine green bottles hanging on the wall. + +Nine green bottles hanging on the wall, +Nine green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be eight green bottles hanging on the wall.'), + ('3185d438-c5ac-4ce6-bcd3-02c9ff1ed8db','last three verses',3,3,'Three green bottles hanging on the wall, +Three green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be two green bottles hanging on the wall. + +Two green bottles hanging on the wall, +Two green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be one green bottle hanging on the wall. + +One green bottle hanging on the wall, +One green bottle hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be no green bottles hanging on the wall.'), + ('28c1584a-0e51-4b65-9ae2-fbc0bf4bbb28','all verses',10,10,'Ten green bottles hanging on the wall, +Ten green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be nine green bottles hanging on the wall. + +Nine green bottles hanging on the wall, +Nine green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be eight green bottles hanging on the wall. + +Eight green bottles hanging on the wall, +Eight green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be seven green bottles hanging on the wall. + +Seven green bottles hanging on the wall, +Seven green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be six green bottles hanging on the wall. + +Six green bottles hanging on the wall, +Six green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be five green bottles hanging on the wall. + +Five green bottles hanging on the wall, +Five green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be four green bottles hanging on the wall. + +Four green bottles hanging on the wall, +Four green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be three green bottles hanging on the wall. + +Three green bottles hanging on the wall, +Three green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be two green bottles hanging on the wall. + +Two green bottles hanging on the wall, +Two green bottles hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be one green bottle hanging on the wall. + +One green bottle hanging on the wall, +One green bottle hanging on the wall, +And if one green bottle should accidentally fall, +There''ll be no green bottles hanging on the wall.'); diff --git a/exercises/practice/bottle-song/data.csv b/exercises/practice/bottle-song/data.csv new file mode 100644 index 0000000..20714dd --- /dev/null +++ b/exercises/practice/bottle-song/data.csv @@ -0,0 +1,7 @@ +10,1,"" +3,1,"" +2,1,"" +1,1,"" +10,2,"" +3,3,"" +10,10,""