From 9dced7f517f3b39a5fef32fec8f4ad80cf5e46cb Mon Sep 17 00:00:00 2001 From: Ronaldo Ferreira de Lima Date: Fri, 8 Aug 2025 23:53:09 -0300 Subject: [PATCH 1/5] * add new practice exercise: bottle-song --- config.json | 8 ++ .../bottle-song/.docs/instructions.md | 57 ++++++++++ .../practice/bottle-song/.meta/config.json | 19 ++++ .../practice/bottle-song/.meta/example.sql | 52 +++++++++ .../practice/bottle-song/.meta/tests.toml | 31 +++++ .../practice/bottle-song/bottle-song.sql | 7 ++ .../practice/bottle-song/bottle-song_test.sql | 44 +++++++ .../practice/bottle-song/create_fixture.sql | 9 ++ .../bottle-song/create_test_table.sql | 107 ++++++++++++++++++ exercises/practice/bottle-song/data.csv | 7 ++ 10 files changed, 341 insertions(+) create mode 100644 exercises/practice/bottle-song/.docs/instructions.md create mode 100644 exercises/practice/bottle-song/.meta/config.json create mode 100644 exercises/practice/bottle-song/.meta/example.sql create mode 100644 exercises/practice/bottle-song/.meta/tests.toml create mode 100644 exercises/practice/bottle-song/bottle-song.sql create mode 100644 exercises/practice/bottle-song/bottle-song_test.sql create mode 100644 exercises/practice/bottle-song/create_fixture.sql create mode 100644 exercises/practice/bottle-song/create_test_table.sql create mode 100644 exercises/practice/bottle-song/data.csv diff --git a/config.json b/config.json index 18ec51d..3b6f6c8 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..da39ff1 --- /dev/null +++ b/exercises/practice/bottle-song/.meta/example.sql @@ -0,0 +1,52 @@ +DROP TABLE IF EXISTS pairs; +CREATE TEMPORARY TABLE pairs ( + n INTEGER NOT NULL, + a TEXT NOT NULL, + b TEXT NOT NULL +); +INSERT INTO pairs (n, a, b) +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 n, + FORMAT('%s green bottles hanging on the wall,' || CHAR(10), a) || + FORMAT('%s green bottles hanging on the wall,' || CHAR(10), a) || + 'And if one green bottle should accidentally fall,' || CHAR(10) || + FORMAT( + 'There''ll be %s green bottles hanging on the wall.', + LOWER(b) + ) AS verse + FROM pairs +; + +UPDATE verses + SET verse = REPLACE(verse, 'be one green bottles', 'be one green bottle') + WHERE n = 2; +UPDATE verses + SET verse = REPLACE(verse, 'One green bottles', 'One green bottle') + WHERE n = 1; + + +UPDATE "bottle-song" + SET result = ( + SELECT GROUP_CONCAT(verse, CHAR(10)||CHAR(10)) + FROM ( + SELECT verse + FROM verses + WHERE n <= start_bottles + AND n > start_bottles - take_down + ORDER BY n 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..e87e5df --- /dev/null +++ b/exercises/practice/bottle-song/bottle-song.sql @@ -0,0 +1,7 @@ +-- 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..55cde81 --- /dev/null +++ b/exercises/practice/bottle-song/bottle-song_test.sql @@ -0,0 +1,44 @@ +-- 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 "' + || FORMAT( + '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,"" From 0c372ffc3d35d7e4ffb596c80031fa7b92050309 Mon Sep 17 00:00:00 2001 From: Ronaldo Ferreira de Lima Date: Sat, 9 Aug 2025 00:08:28 -0300 Subject: [PATCH 2/5] * trying PRINTF() instead FORMAT() --- exercises/practice/bottle-song/.meta/example.sql | 6 +++--- exercises/practice/bottle-song/bottle-song_test.sql | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exercises/practice/bottle-song/.meta/example.sql b/exercises/practice/bottle-song/.meta/example.sql index da39ff1..fff5cc5 100644 --- a/exercises/practice/bottle-song/.meta/example.sql +++ b/exercises/practice/bottle-song/.meta/example.sql @@ -20,10 +20,10 @@ VALUES DROP TABLE IF EXISTS verses; CREATE TABLE verses AS SELECT n, - FORMAT('%s green bottles hanging on the wall,' || CHAR(10), a) || - FORMAT('%s green bottles hanging on the wall,' || CHAR(10), a) || + PRINTF('%s green bottles hanging on the wall,' || CHAR(10), a) || + PRINTF('%s green bottles hanging on the wall,' || CHAR(10), a) || 'And if one green bottle should accidentally fall,' || CHAR(10) || - FORMAT( + PRINTF( 'There''ll be %s green bottles hanging on the wall.', LOWER(b) ) AS verse diff --git a/exercises/practice/bottle-song/bottle-song_test.sql b/exercises/practice/bottle-song/bottle-song_test.sql index 55cde81..b3a5246 100644 --- a/exercises/practice/bottle-song/bottle-song_test.sql +++ b/exercises/practice/bottle-song/bottle-song_test.sql @@ -20,7 +20,7 @@ WHERE (actual.start_bottles, actual.take_down, actual.result) = (tests.start_bot UPDATE tests SET message = ( 'Result for "' - || FORMAT( + || PRINTF( 'start_bottles=%d, take_down=%d', tests.start_bottles, tests.take_down From 3c6412e0c2e9d17638e2245f955b492f45675ed1 Mon Sep 17 00:00:00 2001 From: Ronaldo Ferreira de Lima Date: Sat, 9 Aug 2025 09:06:09 -0300 Subject: [PATCH 3/5] * adjusting code style --- .../practice/bottle-song/.meta/example.sql | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/exercises/practice/bottle-song/.meta/example.sql b/exercises/practice/bottle-song/.meta/example.sql index fff5cc5..d4ad548 100644 --- a/exercises/practice/bottle-song/.meta/example.sql +++ b/exercises/practice/bottle-song/.meta/example.sql @@ -1,41 +1,37 @@ DROP TABLE IF EXISTS pairs; CREATE TEMPORARY TABLE pairs ( - n INTEGER NOT NULL, - a TEXT NOT NULL, - b TEXT NOT NULL + verse_number INTEGER NOT NULL, + start_number TEXT NOT NULL, + next_number TEXT NOT NULL ); -INSERT INTO pairs (n, a, b) -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' ); +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 n, - PRINTF('%s green bottles hanging on the wall,' || CHAR(10), a) || - PRINTF('%s green bottles hanging on the wall,' || CHAR(10), a) || + 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(b) - ) AS verse + 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 n = 2; + WHERE verse_number = 2; UPDATE verses SET verse = REPLACE(verse, 'One green bottles', 'One green bottle') - WHERE n = 1; + WHERE verse_number = 1; UPDATE "bottle-song" @@ -44,9 +40,9 @@ UPDATE "bottle-song" FROM ( SELECT verse FROM verses - WHERE n <= start_bottles - AND n > start_bottles - take_down - ORDER BY n DESC + WHERE verse_number <= start_bottles + AND verse_number > start_bottles - take_down + ORDER BY verse_number DESC ) ) ; From be8bff807f1e5582a22116ebd012b8e37fb7b015 Mon Sep 17 00:00:00 2001 From: Ronaldo Ferreira de Lima Date: Sat, 9 Aug 2025 09:07:49 -0300 Subject: [PATCH 4/5] Update exercises/practice/bottle-song/bottle-song.sql Co-authored-by: Isaac Good --- exercises/practice/bottle-song/bottle-song.sql | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/exercises/practice/bottle-song/bottle-song.sql b/exercises/practice/bottle-song/bottle-song.sql index e87e5df..22b804e 100644 --- a/exercises/practice/bottle-song/bottle-song.sql +++ b/exercises/practice/bottle-song/bottle-song.sql @@ -1,7 +1,8 @@ --- Schema: CREATE TABLE "bottle-song" ( --- start_bottles INTEGER NOT NULL, --- take_down INTEGER NOT NULL, --- result TEXT --- ); +-- 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. +-- start_bottles and take_down. From 535750c64e372dfae8f287523c3928ae3ae2d393 Mon Sep 17 00:00:00 2001 From: Ronaldo Ferreira de Lima Date: Sat, 9 Aug 2025 09:09:02 -0300 Subject: [PATCH 5/5] * indentation --- exercises/practice/bottle-song/bottle-song_test.sql | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/exercises/practice/bottle-song/bottle-song_test.sql b/exercises/practice/bottle-song/bottle-song_test.sql index b3a5246..997e7a7 100644 --- a/exercises/practice/bottle-song/bottle-song_test.sql +++ b/exercises/practice/bottle-song/bottle-song_test.sql @@ -20,11 +20,7 @@ WHERE (actual.start_bottles, actual.take_down, actual.result) = (tests.start_bot UPDATE tests SET message = ( 'Result for "' - || PRINTF( - 'start_bottles=%d, take_down=%d', - tests.start_bottles, - tests.take_down - ) + || PRINTF('start_bottles=%d, take_down=%d', tests.start_bottles,tests.take_down) || '"' || ' is <' || COALESCE(actual.result, 'NULL') || '> but should be <' || tests.expected || '>'