From d08b5914e10f25dece0cd2760d64738144d65b44 Mon Sep 17 00:00:00 2001 From: Ronaldo Ferreira de Lima Date: Wed, 17 Sep 2025 00:34:10 -0300 Subject: [PATCH 1/2] * add practice exercise: bowling --- config.json | 8 + .../bowling/.docs/instructions.append.md | 7 + .../practice/bowling/.docs/instructions.md | 56 ++++++ exercises/practice/bowling/.meta/config.json | 19 ++ exercises/practice/bowling/.meta/example.sql | 165 ++++++++++++++++++ exercises/practice/bowling/.meta/tests.toml | 103 +++++++++++ exercises/practice/bowling/bowling.sql | 10 ++ exercises/practice/bowling/bowling_test.sql | 74 ++++++++ exercises/practice/bowling/create_fixture.sql | 13 ++ .../practice/bowling/create_test_table.sql | 58 ++++++ exercises/practice/bowling/data.csv | 31 ++++ 11 files changed, 544 insertions(+) create mode 100644 exercises/practice/bowling/.docs/instructions.append.md create mode 100644 exercises/practice/bowling/.docs/instructions.md create mode 100644 exercises/practice/bowling/.meta/config.json create mode 100644 exercises/practice/bowling/.meta/example.sql create mode 100644 exercises/practice/bowling/.meta/tests.toml create mode 100644 exercises/practice/bowling/bowling.sql create mode 100644 exercises/practice/bowling/bowling_test.sql create mode 100644 exercises/practice/bowling/create_fixture.sql create mode 100644 exercises/practice/bowling/create_test_table.sql create mode 100644 exercises/practice/bowling/data.csv diff --git a/config.json b/config.json index de03fee8..4d1b143c 100644 --- a/config.json +++ b/config.json @@ -370,6 +370,14 @@ "prerequisites": [], "difficulty": 8 }, + { + "slug": "bowling", + "name": "Bowling", + "uuid": "ef97039a-4f03-42dc-a44c-9dbc4fb8f03b", + "practices": [], + "prerequisites": [], + "difficulty": 8 + }, { "slug": "collatz-conjecture", "name": "Collatz Conjecture", diff --git a/exercises/practice/bowling/.docs/instructions.append.md b/exercises/practice/bowling/.docs/instructions.append.md new file mode 100644 index 00000000..27d1e44d --- /dev/null +++ b/exercises/practice/bowling/.docs/instructions.append.md @@ -0,0 +1,7 @@ +# SQLite-specific instructions + +## JSON documentation + +[JSON Functions And Operators][json-docs] + +[json-docs]: https://www.sqlite.org/json1.html diff --git a/exercises/practice/bowling/.docs/instructions.md b/exercises/practice/bowling/.docs/instructions.md new file mode 100644 index 00000000..60ccad1b --- /dev/null +++ b/exercises/practice/bowling/.docs/instructions.md @@ -0,0 +1,56 @@ +# Instructions + +Score a bowling game. + +Bowling is a game where players roll a heavy ball to knock down pins arranged in a triangle. +Write code to keep track of the score of a game of bowling. + +## Scoring Bowling + +The game consists of 10 frames. +A frame is composed of one or two ball throws with 10 pins standing at frame initialization. +There are three cases for the tabulation of a frame. + +- An open frame is where a score of less than 10 is recorded for the frame. + In this case the score for the frame is the number of pins knocked down. + +- A spare is where all ten pins are knocked down by the second throw. + The total value of a spare is 10 plus the number of pins knocked down in their next throw. + +- A strike is where all ten pins are knocked down by the first throw. + The total value of a strike is 10 plus the number of pins knocked down in the next two throws. + If a strike is immediately followed by a second strike, then the value of the first strike cannot be determined until the ball is thrown one more time. + +Here is a three frame example: + +| Frame 1 | Frame 2 | Frame 3 | +| :--------: | :--------: | :--------------: | +| X (strike) | 5/ (spare) | 9 0 (open frame) | + +Frame 1 is (10 + 5 + 5) = 20 + +Frame 2 is (5 + 5 + 9) = 19 + +Frame 3 is (9 + 0) = 9 + +This means the current running total is 48. + +The tenth frame in the game is a special case. +If someone throws a spare or a strike then they get one or two fill balls respectively. +Fill balls exist to calculate the total of the 10th frame. +Scoring a strike or spare on the fill ball does not give the player more fill balls. +The total value of the 10th frame is the total number of pins knocked down. + +For a tenth frame of X1/ (strike and a spare), the total value is 20. + +For a tenth frame of XXX (three strikes), the total value is 30. + +## Requirements + +Write code to keep track of the score of a game of bowling. +It should support two operations: + +- `roll(pins : int)` is called each time the player rolls a ball. + The argument is the number of pins knocked down. +- `score() : int` is called only at the very end of the game. + It returns the total score for that game. diff --git a/exercises/practice/bowling/.meta/config.json b/exercises/practice/bowling/.meta/config.json new file mode 100644 index 00000000..10bcdd04 --- /dev/null +++ b/exercises/practice/bowling/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "jimmytty" + ], + "files": { + "solution": [ + "bowling.sql" + ], + "test": [ + "bowling_test.sql" + ], + "example": [ + ".meta/example.sql" + ] + }, + "blurb": "Score a bowling game.", + "source": "The Bowling Game Kata from UncleBob", + "source_url": "https://web.archive.org/web/20221001111000/http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata" +} diff --git a/exercises/practice/bowling/.meta/example.sql b/exercises/practice/bowling/.meta/example.sql new file mode 100644 index 00000000..bdc5443d --- /dev/null +++ b/exercises/practice/bowling/.meta/example.sql @@ -0,0 +1,165 @@ +UPDATE bowling + SET error = 'Negative roll is invalid' + WHERE (SELECT 1 + FROM JSON_EACH( + IIF(property = 'roll', + JSON_INSERT(previous_rolls, '$[#]', roll), + previous_rolls + ) + ) + WHERE value < 0 + ) + AND error ISNULL +; + +UPDATE bowling + SET error = 'Pin count exceeds pins on the lane' + WHERE (SELECT 1 + FROM JSON_EACH( + IIF(property = 'roll', + JSON_INSERT(previous_rolls, '$[#]', roll), + previous_rolls + ) + ) + WHERE value > 10 + ) + AND error ISNULL +; + +DROP TABLE IF EXISTS tmp; +CREATE TEMPORARY TABLE tmp ( + rolls TEXT PRIMARY KEY, + frames TEXT NOT NULL +); + +WITH cte (prevrolls) AS ( + SELECT IIF(property = 'roll', + JSON_INSERT(previous_rolls, '$[#]', roll), + previous_rolls + ) + FROM bowling + WHERE error ISNULL +) +INSERT INTO tmp (rolls, frames) +SELECT prevrolls, + (WITH RECURSIVE framer (rolls, frame, frame_id) AS ( + VALUES (prevrolls, '[]', 0) + UNION ALL + SELECT CASE + WHEN JSON_EXTRACT(rolls, '$[0]') = 10 + THEN JSON_REMOVE(rolls, '$[0]') + ELSE JSON_REMOVE(rolls, '$[0]', '$[0]') + END, + CASE + WHEN JSON_EXTRACT(rolls, '$[0]') = 10 THEN + CASE + WHEN frame_id + 1 < 10 + THEN JSON_EXTRACT(rolls, '$[0]', '$[1]', '$[2]') + ELSE JSON_EXTRACT(rolls, '$[0]') + END + WHEN JSON_EXTRACT(rolls, '$[0]') + + JSON_EXTRACT(rolls, '$[1]') = 10 THEN + CASE + WHEN frame_id + 1 < 10 + THEN JSON_EXTRACT(rolls, '$[0]', '$[1]', '$[2]') + ELSE JSON_EXTRACT(rolls, '$[0]', '$[1]') + END + WHEN JSON_EXTRACT(rolls, '$[0]') + + JSON_EXTRACT(rolls, '$[1]') > 10 + THEN JSON_OBJECT('error', 'Pin count exceeds pins on the lane') + ELSE JSON_EXTRACT(rolls, '$[0]', '$[1]') + END, + frame_id + 1 + END + FROM framer + WHERE JSON_TYPE(frame) != 'object' + AND JSON_ARRAY_LENGTH(rolls) > 0 + ) + SELECT JSON_GROUP_ARRAY(JSON(frame)) frames + FROM framer + WHERE frame_id > 0 + ) AS frames + FROM cte +; + +WITH cte (rolls, error) AS ( + SELECT rolls, JSON_EXTRACT(j.value, '$.error') + FROM tmp, JSON_EACH(frames) j + WHERE type = 'object' +) +UPDATE bowling + SET error = cte.error + FROM cte + WHERE IIF(property = 'roll', + JSON_INSERT(previous_rolls, '$[#]', roll), + previous_rolls + ) = cte.rolls + AND bowling.error ISNULL +; + +UPDATE bowling + SET error = 'Score cannot be taken until the end of the game' + FROM tmp + WHERE IIF(property = 'roll', + JSON_INSERT(previous_rolls, '$[#]', roll), + previous_rolls + ) = tmp.rolls + AND property = 'score' + AND bowling.error ISNULL + AND (JSON_ARRAY_LENGTH(frames) < 10 + OR ( + JSON_EXTRACT(frames, '$[9]') = 10 + AND JSON_ARRAY_LENGTH(frames) < 11 + OR (JSON_EXTRACT(frames, '$[9]', '$[10]') = JSON_ARRAY(10, 10) + AND JSON_ARRAY_LENGTH(frames) < 12) + OR (JSON_EXTRACT(frames, '$[9][0]') + + JSON_EXTRACT(frames, '$[9][1]') = 10 + AND JSON_ARRAY_LENGTH(frames) < 11))) +; + +UPDATE bowling + SET error = 'Cannot roll after game is over' + FROM tmp + WHERE IIF(property = 'roll', + JSON_INSERT(previous_rolls, '$[#]', roll), + previous_rolls + ) = tmp.rolls + AND property = 'roll' + AND bowling.error ISNULL + AND JSON_ARRAY_LENGTH(frames) > 10 + AND ( + (JSON_EXTRACT(frames, '$[9]') != 10 + AND (SELECT SUM(VALUE) + FROM JSON_EACH(JSON_EXTRACT(frames, '$[9]'))) != 10 + ) + OR ( + JSON_EXTRACT(frames, '$[9]') != 10 + AND (SELECT SUM(VALUE) + FROM JSON_EACH(JSON_EXTRACT(frames, '$[9]'))) = 10 + AND JSON_EXTRACT(frames, '$[10][1]') NOTNULL + ) + OR ( + JSON_EXTRACT(frames, '$[9]') = 10 + AND (SELECT SUM(VALUE) + FROM JSON_EACH(JSON_EXTRACT(frames, '$[10]')) + ) < 10 + AND JSON_EXTRACT(frames, '$[11]') NOTNULL + ) + ) +; + +WITH cte (rolls, score) AS ( + SELECT rolls, + (SELECT SUM((SELECT SUM(jb.value) FROM JSON_EACH(ja.value) jb)) + FROM JSON_EACH(frames) ja) + FROM tmp +) +UPDATE bowling + SET result = score + FROM cte + WHERE IIF(property = 'roll', + JSON_INSERT(previous_rolls, '$[#]', roll), + previous_rolls + ) = cte.rolls + AND bowling.error ISNULL +; diff --git a/exercises/practice/bowling/.meta/tests.toml b/exercises/practice/bowling/.meta/tests.toml new file mode 100644 index 00000000..19042607 --- /dev/null +++ b/exercises/practice/bowling/.meta/tests.toml @@ -0,0 +1,103 @@ +# 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. + +[656ae006-25c2-438c-a549-f338e7ec7441] +description = "should be able to score a game with all zeros" + +[f85dcc56-cd6b-4875-81b3-e50921e3597b] +description = "should be able to score a game with no strikes or spares" + +[d1f56305-3ac2-4fe0-8645-0b37e3073e20] +description = "a spare followed by zeros is worth ten points" + +[0b8c8bb7-764a-4287-801a-f9e9012f8be4] +description = "points scored in the roll after a spare are counted twice" + +[4d54d502-1565-4691-84cd-f29a09c65bea] +description = "consecutive spares each get a one roll bonus" + +[e5c9cf3d-abbe-4b74-ad48-34051b2b08c0] +description = "a spare in the last frame gets a one roll bonus that is counted once" + +[75269642-2b34-4b72-95a4-9be28ab16902] +description = "a strike earns ten points in a frame with a single roll" + +[037f978c-5d01-4e49-bdeb-9e20a2e6f9a6] +description = "points scored in the two rolls after a strike are counted twice as a bonus" + +[1635e82b-14ec-4cd1-bce4-4ea14bd13a49] +description = "consecutive strikes each get the two roll bonus" + +[e483e8b6-cb4b-4959-b310-e3982030d766] +description = "a strike in the last frame gets a two roll bonus that is counted once" + +[9d5c87db-84bc-4e01-8e95-53350c8af1f8] +description = "rolling a spare with the two roll bonus does not get a bonus roll" + +[576faac1-7cff-4029-ad72-c16bcada79b5] +description = "strikes with the two roll bonus do not get bonus rolls" + +[efb426ec-7e15-42e6-9b96-b4fca3ec2359] +description = "last two strikes followed by only last bonus with non strike points" + +[72e24404-b6c6-46af-b188-875514c0377b] +description = "a strike with the one roll bonus after a spare in the last frame does not get a bonus" + +[62ee4c72-8ee8-4250-b794-234f1fec17b1] +description = "all strikes is a perfect game" + +[1245216b-19c6-422c-b34b-6e4012d7459f] +description = "rolls cannot score negative points" + +[5fcbd206-782c-4faa-8f3a-be5c538ba841] +description = "a roll cannot score more than 10 points" + +[fb023c31-d842-422d-ad7e-79ce1db23c21] +description = "two rolls in a frame cannot score more than 10 points" + +[6082d689-d677-4214-80d7-99940189381b] +description = "bonus roll after a strike in the last frame cannot score more than 10 points" + +[e9565fe6-510a-4675-ba6b-733a56767a45] +description = "two bonus rolls after a strike in the last frame cannot score more than 10 points" + +[2f6acf99-448e-4282-8103-0b9c7df99c3d] +description = "two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike" + +[6380495a-8bc4-4cdb-a59f-5f0212dbed01] +description = "the second bonus rolls after a strike in the last frame cannot be a strike if the first one is not a strike" + +[2b2976ea-446c-47a3-9817-42777f09fe7e] +description = "second bonus roll after a strike in the last frame cannot score more than 10 points" + +[29220245-ac8d-463d-bc19-98a94cfada8a] +description = "an unstarted game cannot be scored" + +[4473dc5d-1f86-486f-bf79-426a52ddc955] +description = "an incomplete game cannot be scored" + +[2ccb8980-1b37-4988-b7d1-e5701c317df3] +description = "cannot roll if game already has ten frames" + +[4864f09b-9df3-4b65-9924-c595ed236f1b] +description = "bonus rolls for a strike in the last frame must be rolled before score can be calculated" + +[537f4e37-4b51-4d1c-97e2-986eb37b2ac1] +description = "both bonus rolls for a strike in the last frame must be rolled before score can be calculated" + +[8134e8c1-4201-4197-bf9f-1431afcde4b9] +description = "bonus roll for a spare in the last frame must be rolled before score can be calculated" + +[9d4a9a55-134a-4bad-bae8-3babf84bd570] +description = "cannot roll after bonus roll for spare" + +[d3e02652-a799-4ae3-b53b-68582cc604be] +description = "cannot roll after bonus rolls for strike" diff --git a/exercises/practice/bowling/bowling.sql b/exercises/practice/bowling/bowling.sql new file mode 100644 index 00000000..e082abbf --- /dev/null +++ b/exercises/practice/bowling/bowling.sql @@ -0,0 +1,10 @@ +-- Schema: +-- CREATE TABLE bowling ( +-- property TEXT NOT NULL, +-- previous_rolls TEXT NOT NULL, -- json aray +-- roll INTEGER , +-- result INTEGER , +-- error TEXT +-- ); +-- +-- Task: update the bowling table and result the result or the error columns based on the property, the previous_rolls and the roll. diff --git a/exercises/practice/bowling/bowling_test.sql b/exercises/practice/bowling/bowling_test.sql new file mode 100644 index 00000000..d752bf9c --- /dev/null +++ b/exercises/practice/bowling/bowling_test.sql @@ -0,0 +1,74 @@ +-- 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 ./bowling.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 property, previous_rolls, roll, result, error + FROM bowling + ) AS actual + WHERE (actual.property, actual.previous_rolls, COALESCE(actual.roll, '')) = + ( tests.property, tests.previous_rolls, COALESCE( tests.roll, '')) + AND (actual.result = tests.expected_result + OR (actual.result ISNULL AND tests.expected_result ISNULL)) + AND (actual.error = tests.expected_error + OR (actual.error ISNULL AND tests.expected_error ISNULL)) +; + +-- Update message for failed tests to give helpful information: +UPDATE tests + SET message = ( + 'Result for "' || + PRINTF('property=%s, previous_rolls=%s', + actual.property, actual.previous_rolls) || + IIF(actual.property = 'roll', + PRINTF(', roll=%s', actual.roll), + '' + )|| + '"' || ' is <' || + PRINTF('result=%s and error=%s', + COALESCE(actual.result, 'NULL'), + COALESCE(actual.error, 'NULL')) || + '> but should be <' || + PRINTF('result=%s and error=%s', + COALESCE(tests.expected_result, 'NULL'), + COALESCE(tests.expected_error, 'NULL')) || + '>' + ) + FROM (SELECT property, previous_rolls, roll, result, error + FROM bowling + ) AS actual + WHERE (actual.property, actual.previous_rolls, COALESCE(actual.roll, '')) = + ( tests.property, tests.previous_rolls, COALESCE( tests.roll, '')) + 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/bowling/create_fixture.sql b/exercises/practice/bowling/create_fixture.sql new file mode 100644 index 00000000..b3eae4b6 --- /dev/null +++ b/exercises/practice/bowling/create_fixture.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS bowling; +CREATE TABLE bowling ( + property TEXT NOT NULL, + previous_rolls TEXT NOT NULL, -- json aray + roll INTEGER , + result INTEGER , + error TEXT +); + +.mode csv +.import ./data.csv bowling + +UPDATE bowling SET result = NULL, error = NULL; diff --git a/exercises/practice/bowling/create_test_table.sql b/exercises/practice/bowling/create_test_table.sql new file mode 100644 index 00000000..9f979321 --- /dev/null +++ b/exercises/practice/bowling/create_test_table.sql @@ -0,0 +1,58 @@ +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 + property TEXT NOT NULL, + previous_rolls TEXT NOT NULL, -- json array + roll INTEGER, + expected_result TEXT, + expected_error TEXT +); + +INSERT INTO tests (uuid, + description, + property, + previous_rolls, + roll, + expected_result, + expected_error) +VALUES +('656ae006-25c2-438c-a549-f338e7ec7441', 'should be able to score a game with all zeros', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 0, NULL), +('f85dcc56-cd6b-4875-81b3-e50921e3597b', 'should be able to score a game with no strikes or spares', 'score', '[3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6]', NULL, 90, NULL), +('d1f56305-3ac2-4fe0-8645-0b37e3073e20', 'a spare followed by zeros is worth ten points', 'score', '[6,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 10, NULL), +('0b8c8bb7-764a-4287-801a-f9e9012f8be4', 'points scored in the roll after a spare are counted twice', 'score', '[6,4,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 16, NULL), +('4d54d502-1565-4691-84cd-f29a09c65bea', 'consecutive spares each get a one roll bonus', 'score', '[5,5,3,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 31, NULL), +('e5c9cf3d-abbe-4b74-ad48-34051b2b08c0', 'a spare in the last frame gets a one roll bonus that is counted once', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,7]', NULL, 17, NULL), +('75269642-2b34-4b72-95a4-9be28ab16902', 'a strike earns ten points in a frame with a single roll', 'score', '[10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 10, NULL), +('037f978c-5d01-4e49-bdeb-9e20a2e6f9a6', 'points scored in the two rolls after a strike are counted twice as a bonus', 'score', '[10,5,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 26, NULL), +('1635e82b-14ec-4cd1-bce4-4ea14bd13a49', 'consecutive strikes each get the two roll bonus', 'score', '[10,10,10,5,3,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 81, NULL), +('e483e8b6-cb4b-4959-b310-e3982030d766', 'a strike in the last frame gets a two roll bonus that is counted once', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,1]', NULL, 18, NULL), +('9d5c87db-84bc-4e01-8e95-53350c8af1f8', 'rolling a spare with the two roll bonus does not get a bonus roll', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,3]', NULL, 20, NULL), +('576faac1-7cff-4029-ad72-c16bcada79b5', 'strikes with the two roll bonus do not get bonus rolls', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,10]', NULL, 30, NULL), +('efb426ec-7e15-42e6-9b96-b4fca3ec2359', 'last two strikes followed by only last bonus with non strike points', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,0,1]', NULL, 31, NULL), +('72e24404-b6c6-46af-b188-875514c0377b', 'a strike with the one roll bonus after a spare in the last frame does not get a bonus', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,10]', NULL, 20, NULL), +('62ee4c72-8ee8-4250-b794-234f1fec17b1', 'all strikes is a perfect game', 'score', '[10,10,10,10,10,10,10,10,10,10,10,10]', NULL, 300, NULL), +('1245216b-19c6-422c-b34b-6e4012d7459f', 'rolls cannot score negative points', 'roll', '[]', -1, NULL, 'Negative roll is invalid'), +('5fcbd206-782c-4faa-8f3a-be5c538ba841', 'a roll cannot score more than 10 points', 'roll', '[]', 11, NULL, 'Pin count exceeds pins on the lane'), +('fb023c31-d842-422d-ad7e-79ce1db23c21', 'two rolls in a frame cannot score more than 10 points', 'roll', '[5]', 6, NULL, 'Pin count exceeds pins on the lane'), +('6082d689-d677-4214-80d7-99940189381b', 'bonus roll after a strike in the last frame cannot score more than 10 points', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]', 11, NULL, 'Pin count exceeds pins on the lane'), +('e9565fe6-510a-4675-ba6b-733a56767a45', 'two bonus rolls after a strike in the last frame cannot score more than 10 points', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5]', 6, NULL, 'Pin count exceeds pins on the lane'), +('2f6acf99-448e-4282-8103-0b9c7df99c3d', 'two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,6]', NULL, 26, NULL), +('6380495a-8bc4-4cdb-a59f-5f0212dbed01', 'the second bonus rolls after a strike in the last frame cannot be a strike if the first one is not a strike', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6]', 10, NULL, 'Pin count exceeds pins on the lane'), +('2b2976ea-446c-47a3-9817-42777f09fe7e', 'second bonus roll after a strike in the last frame cannot score more than 10 points', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]', 11, NULL, 'Pin count exceeds pins on the lane'), +('29220245-ac8d-463d-bc19-98a94cfada8a', 'an unstarted game cannot be scored', 'score', '[]', NULL, NULL, 'Score cannot be taken until the end of the game'), +('4473dc5d-1f86-486f-bf79-426a52ddc955', 'an incomplete game cannot be scored', 'score', '[0,0]', NULL, NULL, 'Score cannot be taken until the end of the game'), +('2ccb8980-1b37-4988-b7d1-e5701c317df3', 'cannot roll if game already has ten frames', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', 0, NULL, 'Cannot roll after game is over'), +('4864f09b-9df3-4b65-9924-c595ed236f1b', 'bonus rolls for a strike in the last frame must be rolled before score can be calculated', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]', NULL, NULL, 'Score cannot be taken until the end of the game'), +('537f4e37-4b51-4d1c-97e2-986eb37b2ac1', 'both bonus rolls for a strike in the last frame must be rolled before score can be calculated', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]', NULL, NULL, 'Score cannot be taken until the end of the game'), +('8134e8c1-4201-4197-bf9f-1431afcde4b9', 'bonus roll for a spare in the last frame must be rolled before score can be calculated', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3]', NULL, NULL, 'Score cannot be taken until the end of the game'), +('9d4a9a55-134a-4bad-bae8-3babf84bd570', 'cannot roll after bonus roll for spare', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,2]', 2, NULL, 'Cannot roll after game is over'), +('d3e02652-a799-4ae3-b53b-68582cc604be', 'cannot roll after bonus rolls for strike', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,3,2]', 2, NULL, 'Cannot roll after game is over'); diff --git a/exercises/practice/bowling/data.csv b/exercises/practice/bowling/data.csv new file mode 100644 index 00000000..54607351 --- /dev/null +++ b/exercises/practice/bowling/data.csv @@ -0,0 +1,31 @@ +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +score,"[3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6]",,, +score,"[6,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +score,"[6,4,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +score,"[5,5,3,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,7]",,, +score,"[10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +score,"[10,5,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +score,"[10,10,10,5,3,0,0,0,0,0,0,0,0,0,0,0,0]",,, +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,1]",,, +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,3]",,, +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,10]",,, +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,0,1]",,, +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,10]",,, +score,"[10,10,10,10,10,10,10,10,10,10,10,10]",,, +roll,[],-1,, +roll,[],11,, +roll,[5],6,, +roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]",11,, +roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5]",6,, +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,6]",,, +roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6]",10,, +roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]",11,, +score,[],,, +score,"[0,0]",,, +roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",0,, +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]",,, +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]",,, +score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3]",,, +roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,2]",2,, +roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,3,2]",2,, From 1d869c77ae3511e0de77bf31c63b7c29fcfb481f Mon Sep 17 00:00:00 2001 From: Ronaldo Ferreira de Lima Date: Wed, 24 Sep 2025 22:02:19 -0300 Subject: [PATCH 2/2] * removing property column --- exercises/practice/bowling/.meta/example.sql | 21 +++--- exercises/practice/bowling/bowling.sql | 3 +- exercises/practice/bowling/bowling_test.sql | 17 +++-- exercises/practice/bowling/create_fixture.sql | 2 +- .../practice/bowling/create_test_table.sql | 64 +++++++++---------- exercises/practice/bowling/data.csv | 62 +++++++++--------- 6 files changed, 82 insertions(+), 87 deletions(-) diff --git a/exercises/practice/bowling/.meta/example.sql b/exercises/practice/bowling/.meta/example.sql index bdc5443d..ab47174c 100644 --- a/exercises/practice/bowling/.meta/example.sql +++ b/exercises/practice/bowling/.meta/example.sql @@ -2,7 +2,7 @@ UPDATE bowling SET error = 'Negative roll is invalid' WHERE (SELECT 1 FROM JSON_EACH( - IIF(property = 'roll', + IIF(roll NOTNULL, JSON_INSERT(previous_rolls, '$[#]', roll), previous_rolls ) @@ -16,7 +16,7 @@ UPDATE bowling SET error = 'Pin count exceeds pins on the lane' WHERE (SELECT 1 FROM JSON_EACH( - IIF(property = 'roll', + IIF(roll NOTNULL, JSON_INSERT(previous_rolls, '$[#]', roll), previous_rolls ) @@ -33,7 +33,7 @@ CREATE TEMPORARY TABLE tmp ( ); WITH cte (prevrolls) AS ( - SELECT IIF(property = 'roll', + SELECT IIF(roll NOTNULL, JSON_INSERT(previous_rolls, '$[#]', roll), previous_rolls ) @@ -90,7 +90,7 @@ WITH cte (rolls, error) AS ( UPDATE bowling SET error = cte.error FROM cte - WHERE IIF(property = 'roll', + WHERE IIF(roll NOTNULL, JSON_INSERT(previous_rolls, '$[#]', roll), previous_rolls ) = cte.rolls @@ -100,11 +100,11 @@ UPDATE bowling UPDATE bowling SET error = 'Score cannot be taken until the end of the game' FROM tmp - WHERE IIF(property = 'roll', + WHERE IIF(roll NOTNULL, JSON_INSERT(previous_rolls, '$[#]', roll), previous_rolls ) = tmp.rolls - AND property = 'score' + AND roll ISNULL AND bowling.error ISNULL AND (JSON_ARRAY_LENGTH(frames) < 10 OR ( @@ -120,11 +120,10 @@ UPDATE bowling UPDATE bowling SET error = 'Cannot roll after game is over' FROM tmp - WHERE IIF(property = 'roll', - JSON_INSERT(previous_rolls, '$[#]', roll), - previous_rolls + WHERE IIF(roll NOTNULL, + JSON_INSERT(previous_rolls, '$[#]', roll), + previous_rolls ) = tmp.rolls - AND property = 'roll' AND bowling.error ISNULL AND JSON_ARRAY_LENGTH(frames) > 10 AND ( @@ -157,7 +156,7 @@ WITH cte (rolls, score) AS ( UPDATE bowling SET result = score FROM cte - WHERE IIF(property = 'roll', + WHERE IIF(roll NOTNULL, JSON_INSERT(previous_rolls, '$[#]', roll), previous_rolls ) = cte.rolls diff --git a/exercises/practice/bowling/bowling.sql b/exercises/practice/bowling/bowling.sql index e082abbf..3a1118fa 100644 --- a/exercises/practice/bowling/bowling.sql +++ b/exercises/practice/bowling/bowling.sql @@ -1,10 +1,9 @@ -- Schema: -- CREATE TABLE bowling ( --- property TEXT NOT NULL, -- previous_rolls TEXT NOT NULL, -- json aray -- roll INTEGER , -- result INTEGER , -- error TEXT -- ); -- --- Task: update the bowling table and result the result or the error columns based on the property, the previous_rolls and the roll. +-- Task: update the bowling table and set the result or the error columns based on the previous_rolls and the roll. diff --git a/exercises/practice/bowling/bowling_test.sql b/exercises/practice/bowling/bowling_test.sql index d752bf9c..236237f2 100644 --- a/exercises/practice/bowling/bowling_test.sql +++ b/exercises/practice/bowling/bowling_test.sql @@ -13,11 +13,11 @@ -- Comparison of user input and the tests updates the status for each test: UPDATE tests SET status = 'pass' - FROM (SELECT property, previous_rolls, roll, result, error + FROM (SELECT previous_rolls, roll, result, error FROM bowling ) AS actual - WHERE (actual.property, actual.previous_rolls, COALESCE(actual.roll, '')) = - ( tests.property, tests.previous_rolls, COALESCE( tests.roll, '')) + WHERE (actual.previous_rolls, COALESCE(actual.roll, '')) = + ( tests.previous_rolls, COALESCE( tests.roll, '')) AND (actual.result = tests.expected_result OR (actual.result ISNULL AND tests.expected_result ISNULL)) AND (actual.error = tests.expected_error @@ -28,9 +28,8 @@ UPDATE tests UPDATE tests SET message = ( 'Result for "' || - PRINTF('property=%s, previous_rolls=%s', - actual.property, actual.previous_rolls) || - IIF(actual.property = 'roll', + PRINTF('previous_rolls=%s', actual.previous_rolls) || + IIF(actual.roll NOTNULL, PRINTF(', roll=%s', actual.roll), '' )|| @@ -44,11 +43,11 @@ UPDATE tests COALESCE(tests.expected_error, 'NULL')) || '>' ) - FROM (SELECT property, previous_rolls, roll, result, error + FROM (SELECT previous_rolls, roll, result, error FROM bowling ) AS actual - WHERE (actual.property, actual.previous_rolls, COALESCE(actual.roll, '')) = - ( tests.property, tests.previous_rolls, COALESCE( tests.roll, '')) + WHERE (actual.previous_rolls, COALESCE(actual.roll, '')) = + ( tests.previous_rolls, COALESCE( tests.roll, '')) AND tests.status = 'fail'; -- Save results to ./output.json (needed by the online test-runner) diff --git a/exercises/practice/bowling/create_fixture.sql b/exercises/practice/bowling/create_fixture.sql index b3eae4b6..ba2abc63 100644 --- a/exercises/practice/bowling/create_fixture.sql +++ b/exercises/practice/bowling/create_fixture.sql @@ -1,6 +1,5 @@ DROP TABLE IF EXISTS bowling; CREATE TABLE bowling ( - property TEXT NOT NULL, previous_rolls TEXT NOT NULL, -- json aray roll INTEGER , result INTEGER , @@ -11,3 +10,4 @@ CREATE TABLE bowling ( .import ./data.csv bowling UPDATE bowling SET result = NULL, error = NULL; +UPDATE bowling SET roll = NULL WHERE roll = ''; diff --git a/exercises/practice/bowling/create_test_table.sql b/exercises/practice/bowling/create_test_table.sql index 9f979321..fa6cd9ea 100644 --- a/exercises/practice/bowling/create_test_table.sql +++ b/exercises/practice/bowling/create_test_table.sql @@ -10,7 +10,6 @@ CREATE TABLE IF NOT EXISTS tests ( test_code TEXT, task_id INTEGER DEFAULT NULL, -- Here are columns for the actual tests - property TEXT NOT NULL, previous_rolls TEXT NOT NULL, -- json array roll INTEGER, expected_result TEXT, @@ -19,40 +18,39 @@ CREATE TABLE IF NOT EXISTS tests ( INSERT INTO tests (uuid, description, - property, previous_rolls, roll, expected_result, expected_error) VALUES -('656ae006-25c2-438c-a549-f338e7ec7441', 'should be able to score a game with all zeros', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 0, NULL), -('f85dcc56-cd6b-4875-81b3-e50921e3597b', 'should be able to score a game with no strikes or spares', 'score', '[3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6]', NULL, 90, NULL), -('d1f56305-3ac2-4fe0-8645-0b37e3073e20', 'a spare followed by zeros is worth ten points', 'score', '[6,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 10, NULL), -('0b8c8bb7-764a-4287-801a-f9e9012f8be4', 'points scored in the roll after a spare are counted twice', 'score', '[6,4,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 16, NULL), -('4d54d502-1565-4691-84cd-f29a09c65bea', 'consecutive spares each get a one roll bonus', 'score', '[5,5,3,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 31, NULL), -('e5c9cf3d-abbe-4b74-ad48-34051b2b08c0', 'a spare in the last frame gets a one roll bonus that is counted once', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,7]', NULL, 17, NULL), -('75269642-2b34-4b72-95a4-9be28ab16902', 'a strike earns ten points in a frame with a single roll', 'score', '[10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 10, NULL), -('037f978c-5d01-4e49-bdeb-9e20a2e6f9a6', 'points scored in the two rolls after a strike are counted twice as a bonus', 'score', '[10,5,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 26, NULL), -('1635e82b-14ec-4cd1-bce4-4ea14bd13a49', 'consecutive strikes each get the two roll bonus', 'score', '[10,10,10,5,3,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 81, NULL), -('e483e8b6-cb4b-4959-b310-e3982030d766', 'a strike in the last frame gets a two roll bonus that is counted once', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,1]', NULL, 18, NULL), -('9d5c87db-84bc-4e01-8e95-53350c8af1f8', 'rolling a spare with the two roll bonus does not get a bonus roll', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,3]', NULL, 20, NULL), -('576faac1-7cff-4029-ad72-c16bcada79b5', 'strikes with the two roll bonus do not get bonus rolls', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,10]', NULL, 30, NULL), -('efb426ec-7e15-42e6-9b96-b4fca3ec2359', 'last two strikes followed by only last bonus with non strike points', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,0,1]', NULL, 31, NULL), -('72e24404-b6c6-46af-b188-875514c0377b', 'a strike with the one roll bonus after a spare in the last frame does not get a bonus', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,10]', NULL, 20, NULL), -('62ee4c72-8ee8-4250-b794-234f1fec17b1', 'all strikes is a perfect game', 'score', '[10,10,10,10,10,10,10,10,10,10,10,10]', NULL, 300, NULL), -('1245216b-19c6-422c-b34b-6e4012d7459f', 'rolls cannot score negative points', 'roll', '[]', -1, NULL, 'Negative roll is invalid'), -('5fcbd206-782c-4faa-8f3a-be5c538ba841', 'a roll cannot score more than 10 points', 'roll', '[]', 11, NULL, 'Pin count exceeds pins on the lane'), -('fb023c31-d842-422d-ad7e-79ce1db23c21', 'two rolls in a frame cannot score more than 10 points', 'roll', '[5]', 6, NULL, 'Pin count exceeds pins on the lane'), -('6082d689-d677-4214-80d7-99940189381b', 'bonus roll after a strike in the last frame cannot score more than 10 points', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]', 11, NULL, 'Pin count exceeds pins on the lane'), -('e9565fe6-510a-4675-ba6b-733a56767a45', 'two bonus rolls after a strike in the last frame cannot score more than 10 points', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5]', 6, NULL, 'Pin count exceeds pins on the lane'), -('2f6acf99-448e-4282-8103-0b9c7df99c3d', 'two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,6]', NULL, 26, NULL), -('6380495a-8bc4-4cdb-a59f-5f0212dbed01', 'the second bonus rolls after a strike in the last frame cannot be a strike if the first one is not a strike', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6]', 10, NULL, 'Pin count exceeds pins on the lane'), -('2b2976ea-446c-47a3-9817-42777f09fe7e', 'second bonus roll after a strike in the last frame cannot score more than 10 points', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]', 11, NULL, 'Pin count exceeds pins on the lane'), -('29220245-ac8d-463d-bc19-98a94cfada8a', 'an unstarted game cannot be scored', 'score', '[]', NULL, NULL, 'Score cannot be taken until the end of the game'), -('4473dc5d-1f86-486f-bf79-426a52ddc955', 'an incomplete game cannot be scored', 'score', '[0,0]', NULL, NULL, 'Score cannot be taken until the end of the game'), -('2ccb8980-1b37-4988-b7d1-e5701c317df3', 'cannot roll if game already has ten frames', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', 0, NULL, 'Cannot roll after game is over'), -('4864f09b-9df3-4b65-9924-c595ed236f1b', 'bonus rolls for a strike in the last frame must be rolled before score can be calculated', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]', NULL, NULL, 'Score cannot be taken until the end of the game'), -('537f4e37-4b51-4d1c-97e2-986eb37b2ac1', 'both bonus rolls for a strike in the last frame must be rolled before score can be calculated', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]', NULL, NULL, 'Score cannot be taken until the end of the game'), -('8134e8c1-4201-4197-bf9f-1431afcde4b9', 'bonus roll for a spare in the last frame must be rolled before score can be calculated', 'score', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3]', NULL, NULL, 'Score cannot be taken until the end of the game'), -('9d4a9a55-134a-4bad-bae8-3babf84bd570', 'cannot roll after bonus roll for spare', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,2]', 2, NULL, 'Cannot roll after game is over'), -('d3e02652-a799-4ae3-b53b-68582cc604be', 'cannot roll after bonus rolls for strike', 'roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,3,2]', 2, NULL, 'Cannot roll after game is over'); +('656ae006-25c2-438c-a549-f338e7ec7441', 'should be able to score a game with all zeros', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 0, NULL), +('f85dcc56-cd6b-4875-81b3-e50921e3597b', 'should be able to score a game with no strikes or spares', '[3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6]', NULL, 90, NULL), +('d1f56305-3ac2-4fe0-8645-0b37e3073e20', 'a spare followed by zeros is worth ten points', '[6,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 10, NULL), +('0b8c8bb7-764a-4287-801a-f9e9012f8be4', 'points scored in the roll after a spare are counted twice', '[6,4,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 16, NULL), +('4d54d502-1565-4691-84cd-f29a09c65bea', 'consecutive spares each get a one roll bonus', '[5,5,3,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 31, NULL), +('e5c9cf3d-abbe-4b74-ad48-34051b2b08c0', 'a spare in the last frame gets a one roll bonus that is counted once', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,7]', NULL, 17, NULL), +('75269642-2b34-4b72-95a4-9be28ab16902', 'a strike earns ten points in a frame with a single roll', '[10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 10, NULL), +('037f978c-5d01-4e49-bdeb-9e20a2e6f9a6', 'points scored in the two rolls after a strike are counted twice as a bonus', '[10,5,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 26, NULL), +('1635e82b-14ec-4cd1-bce4-4ea14bd13a49', 'consecutive strikes each get the two roll bonus', '[10,10,10,5,3,0,0,0,0,0,0,0,0,0,0,0,0]', NULL, 81, NULL), +('e483e8b6-cb4b-4959-b310-e3982030d766', 'a strike in the last frame gets a two roll bonus that is counted once', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,1]', NULL, 18, NULL), +('9d5c87db-84bc-4e01-8e95-53350c8af1f8', 'rolling a spare with the two roll bonus does not get a bonus roll', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,3]', NULL, 20, NULL), +('576faac1-7cff-4029-ad72-c16bcada79b5', 'strikes with the two roll bonus do not get bonus rolls', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,10]', NULL, 30, NULL), +('efb426ec-7e15-42e6-9b96-b4fca3ec2359', 'last two strikes followed by only last bonus with non strike points', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,0,1]', NULL, 31, NULL), +('72e24404-b6c6-46af-b188-875514c0377b', 'a strike with the one roll bonus after a spare in the last frame does not get a bonus', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,10]', NULL, 20, NULL), +('62ee4c72-8ee8-4250-b794-234f1fec17b1', 'all strikes is a perfect game', '[10,10,10,10,10,10,10,10,10,10,10,10]', NULL, 300, NULL), +('1245216b-19c6-422c-b34b-6e4012d7459f', 'rolls cannot score negative points', '[]', -1, NULL, 'Negative roll is invalid'), +('5fcbd206-782c-4faa-8f3a-be5c538ba841', 'a roll cannot score more than 10 points', '[]', 11, NULL, 'Pin count exceeds pins on the lane'), +('fb023c31-d842-422d-ad7e-79ce1db23c21', 'two rolls in a frame cannot score more than 10 points', '[5]', 6, NULL, 'Pin count exceeds pins on the lane'), +('6082d689-d677-4214-80d7-99940189381b', 'bonus roll after a strike in the last frame cannot score more than 10 points', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]', 11, NULL, 'Pin count exceeds pins on the lane'), +('e9565fe6-510a-4675-ba6b-733a56767a45', 'two bonus rolls after a strike in the last frame cannot score more than 10 points', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5]', 6, NULL, 'Pin count exceeds pins on the lane'), +('2f6acf99-448e-4282-8103-0b9c7df99c3d', 'two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,6]', NULL, 26, NULL), +('6380495a-8bc4-4cdb-a59f-5f0212dbed01', 'the second bonus rolls after a strike in the last frame cannot be a strike if the first one is not a strike', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6]', 10, NULL, 'Pin count exceeds pins on the lane'), +('2b2976ea-446c-47a3-9817-42777f09fe7e', 'second bonus roll after a strike in the last frame cannot score more than 10 points', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]', 11, NULL, 'Pin count exceeds pins on the lane'), +('29220245-ac8d-463d-bc19-98a94cfada8a', 'an unstarted game cannot be scored', '[]', NULL, NULL, 'Score cannot be taken until the end of the game'), +('4473dc5d-1f86-486f-bf79-426a52ddc955', 'an incomplete game cannot be scored', '[0,0]', NULL, NULL, 'Score cannot be taken until the end of the game'), +('2ccb8980-1b37-4988-b7d1-e5701c317df3', 'cannot roll if game already has ten frames', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]', 0, NULL, 'Cannot roll after game is over'), +('4864f09b-9df3-4b65-9924-c595ed236f1b', 'bonus rolls for a strike in the last frame must be rolled before score can be calculated', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]', NULL, NULL, 'Score cannot be taken until the end of the game'), +('537f4e37-4b51-4d1c-97e2-986eb37b2ac1', 'both bonus rolls for a strike in the last frame must be rolled before score can be calculated', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]', NULL, NULL, 'Score cannot be taken until the end of the game'), +('8134e8c1-4201-4197-bf9f-1431afcde4b9', 'bonus roll for a spare in the last frame must be rolled before score can be calculated', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3]', NULL, NULL, 'Score cannot be taken until the end of the game'), +('9d4a9a55-134a-4bad-bae8-3babf84bd570', 'cannot roll after bonus roll for spare', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,2]', 2, NULL, 'Cannot roll after game is over'), +('d3e02652-a799-4ae3-b53b-68582cc604be', 'cannot roll after bonus rolls for strike', '[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,3,2]', 2, NULL, 'Cannot roll after game is over'); diff --git a/exercises/practice/bowling/data.csv b/exercises/practice/bowling/data.csv index 54607351..e140b848 100644 --- a/exercises/practice/bowling/data.csv +++ b/exercises/practice/bowling/data.csv @@ -1,31 +1,31 @@ -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, -score,"[3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6]",,, -score,"[6,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, -score,"[6,4,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, -score,"[5,5,3,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,7]",,, -score,"[10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, -score,"[10,5,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, -score,"[10,10,10,5,3,0,0,0,0,0,0,0,0,0,0,0,0]",,, -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,1]",,, -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,3]",,, -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,10]",,, -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,0,1]",,, -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,10]",,, -score,"[10,10,10,10,10,10,10,10,10,10,10,10]",,, -roll,[],-1,, -roll,[],11,, -roll,[5],6,, -roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]",11,, -roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5]",6,, -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,6]",,, -roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6]",10,, -roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]",11,, -score,[],,, -score,"[0,0]",,, -roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",0,, -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]",,, -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]",,, -score,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3]",,, -roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,2]",2,, -roll,"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,3,2]",2,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +"[3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6,3,6]",,, +"[6,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +"[6,4,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +"[5,5,3,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,7]",,, +"[10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +"[10,5,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",,, +"[10,10,10,5,3,0,0,0,0,0,0,0,0,0,0,0,0]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,1]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,3]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,10]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,0,1]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,10]",,, +"[10,10,10,10,10,10,10,10,10,10,10,10]",,, +[],-1,, +[],11,, +[5],6,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]",11,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5]",6,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10,6]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6]",10,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]",11,, +[],,, +"[0,0]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",0,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,10]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3]",,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,2]",2,, +"[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,3,2]",2,,