diff --git a/config.json b/config.json index de03fee..de639cf 100644 --- a/config.json +++ b/config.json @@ -274,6 +274,14 @@ "prerequisites": [], "difficulty": 5 }, + { + "slug": "queen-attack", + "name": "Queen Attack", + "uuid": "f452c4fd-9ee7-49d6-b373-bc250445b4c8", + "practices": [], + "prerequisites": [], + "difficulty": 5 + }, { "slug": "resistor-color-trio", "name": "Resistor Color Trio", diff --git a/exercises/practice/queen-attack/.docs/instructions.md b/exercises/practice/queen-attack/.docs/instructions.md new file mode 100644 index 0000000..97f22a0 --- /dev/null +++ b/exercises/practice/queen-attack/.docs/instructions.md @@ -0,0 +1,21 @@ +# Instructions + +Given the position of two queens on a chess board, indicate whether or not they are positioned so that they can attack each other. + +In the game of chess, a queen can attack pieces which are on the same row, column, or diagonal. + +A chessboard can be represented by an 8 by 8 array. + +So if you are told the white queen is at `c5` (zero-indexed at column 2, row 3) and the black queen at `f2` (zero-indexed at column 5, row 6), then you know that the set-up is like so: + +![A chess board with two queens. Arrows emanating from the queen at c5 indicate possible directions of capture along file, rank and diagonal.](https://assets.exercism.org/images/exercises/queen-attack/queen-capture.svg) + +You are also able to answer whether the queens can attack each other. +In this case, that answer would be yes, they can, because both pieces share a diagonal. + +## Credit + +The chessboard image was made by [habere-et-dispertire][habere-et-dispertire] using LaTeX and the [chessboard package][chessboard-package] by Ulrike Fischer. + +[habere-et-dispertire]: https://exercism.org/profiles/habere-et-dispertire +[chessboard-package]: https://github.com/u-fischer/chessboard diff --git a/exercises/practice/queen-attack/.meta/config.json b/exercises/practice/queen-attack/.meta/config.json new file mode 100644 index 0000000..3415c46 --- /dev/null +++ b/exercises/practice/queen-attack/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "jimmytty" + ], + "files": { + "solution": [ + "queen-attack.sql" + ], + "test": [ + "queen-attack_test.sql" + ], + "example": [ + ".meta/example.sql" + ] + }, + "blurb": "Given the position of two queens on a chess board, indicate whether or not they are positioned so that they can attack each other.", + "source": "J Dalbey's Programming Practice problems", + "source_url": "https://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html" +} diff --git a/exercises/practice/queen-attack/.meta/example.sql b/exercises/practice/queen-attack/.meta/example.sql new file mode 100644 index 0000000..6472c82 --- /dev/null +++ b/exercises/practice/queen-attack/.meta/example.sql @@ -0,0 +1,55 @@ +UPDATE "queen-attack" + SET error = + CASE + WHEN white_row < 0 OR black_row < 0 THEN 'row not positive' + WHEN white_row > 7 OR black_row > 7 THEN 'row not on board' + WHEN white_col < 0 OR black_col < 0 THEN 'column not positive' + WHEN white_col > 7 OR black_col > 7 THEN 'column not on board' + END +; + +UPDATE "queen-attack" + SET result = ( + WITH + seq AS (SELECT value FROM GENERATE_SERIES(0, 7)), + positions (row, col) AS ( + SELECT white_row, value FROM seq + UNION + SELECT value, white_col FROM seq + UNION + SELECT white_row - value AS r, white_col - value AS c + FROM seq + WHERE r >= 0 AND c >= 0 + UNION + SELECT white_row + value AS r, white_col + value AS c + FROM seq + WHERE r <= 7 AND c <= 7 + UNION + SELECT white_row - value AS r, white_col - value AS c + FROM seq + WHERE r >= 0 AND c >= 0 + UNION + SELECT white_row + value AS r, white_col + value AS c + FROM seq + WHERE r <= 7 AND c <= 7 + UNION + SELECT white_row + value AS r, white_col - value AS c + FROM seq + WHERE r <= 7 AND c >= 0 + UNION + SELECT white_row - value AS r, white_col + value AS c + FROM seq + WHERE r >= 0 AND c <= 7 + ) + SELECT + COALESCE( + (SELECT TRUE + FROM positions + WHERE row = black_row + AND col = black_col + ), + FALSE + ) + ) + WHERE error ISNULL +; diff --git a/exercises/practice/queen-attack/.meta/tests.toml b/exercises/practice/queen-attack/.meta/tests.toml new file mode 100644 index 0000000..e062412 --- /dev/null +++ b/exercises/practice/queen-attack/.meta/tests.toml @@ -0,0 +1,49 @@ +# 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. + +[3ac4f735-d36c-44c4-a3e2-316f79704203] +description = "Test creation of Queens with valid and invalid positions -> queen with a valid position" + +[4e812d5d-b974-4e38-9a6b-8e0492bfa7be] +description = "Test creation of Queens with valid and invalid positions -> queen must have positive row" + +[f07b7536-b66b-4f08-beb9-4d70d891d5c8] +description = "Test creation of Queens with valid and invalid positions -> queen must have row on board" + +[15a10794-36d9-4907-ae6b-e5a0d4c54ebe] +description = "Test creation of Queens with valid and invalid positions -> queen must have positive column" + +[6907762d-0e8a-4c38-87fb-12f2f65f0ce4] +description = "Test creation of Queens with valid and invalid positions -> queen must have column on board" + +[33ae4113-d237-42ee-bac1-e1e699c0c007] +description = "Test the ability of one queen to attack another -> cannot attack" + +[eaa65540-ea7c-4152-8c21-003c7a68c914] +description = "Test the ability of one queen to attack another -> can attack on same row" + +[bae6f609-2c0e-4154-af71-af82b7c31cea] +description = "Test the ability of one queen to attack another -> can attack on same column" + +[0e1b4139-b90d-4562-bd58-dfa04f1746c7] +description = "Test the ability of one queen to attack another -> can attack on first diagonal" + +[ff9b7ed4-e4b6-401b-8d16-bc894d6d3dcd] +description = "Test the ability of one queen to attack another -> can attack on second diagonal" + +[0a71e605-6e28-4cc2-aa47-d20a2e71037a] +description = "Test the ability of one queen to attack another -> can attack on third diagonal" + +[0790b588-ae73-4f1f-a968-dd0b34f45f86] +description = "Test the ability of one queen to attack another -> can attack on fourth diagonal" + +[543f8fd4-2597-4aad-8d77-cbdab63619f8] +description = "Test the ability of one queen to attack another -> cannot attack if falling diagonals are only the same when reflected across the longest falling diagonal" diff --git a/exercises/practice/queen-attack/create_fixture.sql b/exercises/practice/queen-attack/create_fixture.sql new file mode 100644 index 0000000..dfc7cb6 --- /dev/null +++ b/exercises/practice/queen-attack/create_fixture.sql @@ -0,0 +1,14 @@ +DROP TABLE IF EXISTS "queen-attack"; +CREATE TABLE "queen-attack" ( + white_row INTEGER NOT NULL, + white_col INTEGER NOT NULL, + black_row INTEGER NOT NULL, + black_col INTEGER NOT NULL, + result BOOLEAN , + error TEXT +); + +.mode csv +.import ./data.csv "queen-attack" + +UPDATE "queen-attack" SET result = NULL, error = NULL; diff --git a/exercises/practice/queen-attack/create_test_table.sql b/exercises/practice/queen-attack/create_test_table.sql new file mode 100644 index 0000000..52c0342 --- /dev/null +++ b/exercises/practice/queen-attack/create_test_table.sql @@ -0,0 +1,44 @@ +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 + white_row INTEGER NOT NULL, + white_col INTEGER NOT NULL, + black_row INTEGER NOT NULL, + black_col INTEGER NOT NULL, + expected_result BOOLEAN, + expected_error TEXT +); + +INSERT INTO tests ( + uuid , + description , + white_row , + white_col , + black_row , + black_col , + expected_result, + expected_error +) +VALUES +('3ac4f735-d36c-44c4-a3e2-316f79704203', 'queen with a valid position', 2, 2, 2, 2, 1, NULL), +('4e812d5d-b974-4e38-9a6b-8e0492bfa7be', 'queen must have positive row', -2, 2, -2, 2, NULL, 'row not positive'), +('f07b7536-b66b-4f08-beb9-4d70d891d5c8', 'queen must have row on board', 8, 4, 8, 4, NULL, 'row not on board'), +('15a10794-36d9-4907-ae6b-e5a0d4c54ebe', 'queen must have positive column', 2, -2, 2, -2, NULL, 'column not positive'), +('6907762d-0e8a-4c38-87fb-12f2f65f0ce4', 'queen must have column on board', 4, 8, 4, 8, NULL, 'column not on board'), +('33ae4113-d237-42ee-bac1-e1e699c0c007', 'cannot attack', 2, 4, 6, 6, 0, NULL), +('eaa65540-ea7c-4152-8c21-003c7a68c914', 'can attack on same row', 2, 4, 2, 6, 1, NULL), +('bae6f609-2c0e-4154-af71-af82b7c31cea', 'can attack on same column', 4, 5, 2, 5, 1, NULL), +('0e1b4139-b90d-4562-bd58-dfa04f1746c7', 'can attack on first diagonal', 2, 2, 0, 4, 1, NULL), +('ff9b7ed4-e4b6-401b-8d16-bc894d6d3dcd', 'can attack on second diagonal', 2, 2, 3, 1, 1, NULL), +('0a71e605-6e28-4cc2-aa47-d20a2e71037a', 'can attack on third diagonal', 2, 2, 1, 1, 1, NULL), +('0790b588-ae73-4f1f-a968-dd0b34f45f86', 'can attack on fourth diagonal', 1, 7, 0, 6, 1, NULL), +('543f8fd4-2597-4aad-8d77-cbdab63619f8', 'cannot attack if falling diagonals are only the same when reflected across the longest falling diagonal', 4, 1, 2, 5, 0, NULL); diff --git a/exercises/practice/queen-attack/data.csv b/exercises/practice/queen-attack/data.csv new file mode 100644 index 0000000..6a62578 --- /dev/null +++ b/exercises/practice/queen-attack/data.csv @@ -0,0 +1,13 @@ +2,2,2,2,, +-2,2,-2,2,, +8,4,8,4,, +2,-2,2,-2,, +4,8,4,8,, +2,4,6,6,, +2,4,2,6,, +4,5,2,5,, +2,2,0,4,, +2,2,3,1,, +2,2,1,1,, +1,7,0,6,, +4,1,2,5,, diff --git a/exercises/practice/queen-attack/queen-attack.sql b/exercises/practice/queen-attack/queen-attack.sql new file mode 100644 index 0000000..92eff59 --- /dev/null +++ b/exercises/practice/queen-attack/queen-attack.sql @@ -0,0 +1,11 @@ +-- Schema: +-- CREATE TABLE "queen-attack" ( +-- white_row INTEGER NOT NULL, +-- white_col INTEGER NOT NULL, +-- black_row INTEGER NOT NULL, +-- black_col INTEGER NOT NULL, +-- result BOOLEAN , +-- error TEXT +-- ); +-- +-- Task: update the "queen-attack" table and set the result or the error columns based on the white and black queens positions. diff --git a/exercises/practice/queen-attack/queen-attack_test.sql b/exercises/practice/queen-attack/queen-attack_test.sql new file mode 100644 index 0000000..edef891 --- /dev/null +++ b/exercises/practice/queen-attack/queen-attack_test.sql @@ -0,0 +1,69 @@ +-- 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 ./queen-attack.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 white_row, white_col, black_row, black_col, result, error + FROM "queen-attack") AS actual + WHERE (actual.white_row, actual.white_col, actual.black_row, actual.black_col) + = ( tests.white_row, tests.white_col, tests.black_row, tests.black_col) + 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('white(row,col)=(%d,%d), black(row,col)=(%d,%d)', + actual.white_row, actual.white_col, + actual.black_row, actual.black_col) + || '"' || ' 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 white_row, white_col, black_row, black_col, result, error + FROM "queen-attack") AS actual + WHERE (actual.white_row, actual.white_col, actual.black_row, actual.black_col) + = ( tests.white_row, tests.white_col, tests.black_row, tests.black_col) + 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;