Skip to content

Commit 775e36b

Browse files
authored
Add practice exercise: wordy (#200)
1 parent 902c1c5 commit 775e36b

File tree

10 files changed

+442
-0
lines changed

10 files changed

+442
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,14 @@
578578
"prerequisites": [],
579579
"difficulty": 8
580580
},
581+
{
582+
"slug": "wordy",
583+
"name": "Wordy",
584+
"uuid": "b013d306-2212-44b6-abfb-5523a1b54c65",
585+
"practices": [],
586+
"prerequisites": [],
587+
"difficulty": 8
588+
},
581589
{
582590
"slug": "yacht",
583591
"name": "Yacht",
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Instructions
2+
3+
Parse and evaluate simple math word problems returning the answer as an integer.
4+
5+
## Iteration 0 — Numbers
6+
7+
Problems with no operations simply evaluate to the number given.
8+
9+
> What is 5?
10+
11+
Evaluates to 5.
12+
13+
## Iteration 1 — Addition
14+
15+
Add two numbers together.
16+
17+
> What is 5 plus 13?
18+
19+
Evaluates to 18.
20+
21+
Handle large numbers and negative numbers.
22+
23+
## Iteration 2 — Subtraction, Multiplication and Division
24+
25+
Now, perform the other three operations.
26+
27+
> What is 7 minus 5?
28+
29+
2
30+
31+
> What is 6 multiplied by 4?
32+
33+
24
34+
35+
> What is 25 divided by 5?
36+
37+
5
38+
39+
## Iteration 3 — Multiple Operations
40+
41+
Handle a set of operations, in sequence.
42+
43+
Since these are verbal word problems, evaluate the expression from left-to-right, _ignoring the typical order of operations._
44+
45+
> What is 5 plus 13 plus 6?
46+
47+
24
48+
49+
> What is 3 plus 2 multiplied by 3?
50+
51+
15 (i.e. not 9)
52+
53+
## Iteration 4 — Errors
54+
55+
The parser should reject:
56+
57+
- Unsupported operations ("What is 52 cubed?")
58+
- Non-math questions ("Who is the President of the United States")
59+
- Word problems with invalid syntax ("What is 1 plus plus 2?")
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"jimmytty"
4+
],
5+
"files": {
6+
"solution": [
7+
"wordy.sql"
8+
],
9+
"test": [
10+
"wordy_test.sql"
11+
],
12+
"example": [
13+
".meta/example.sql"
14+
]
15+
},
16+
"blurb": "Parse and evaluate simple math word problems returning the answer as an integer.",
17+
"source": "Inspired by one of the generated questions in the Extreme Startup game.",
18+
"source_url": "https://github.com/rchatley/extreme_startup"
19+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
DROP TABLE IF EXISTS dict;
2+
CREATE TEMPORARY TABLE dict (
3+
key TEXT NOT NULL,
4+
value TEXT NOT NULL
5+
);
6+
INSERT INTO dict (key, value)
7+
VALUES ('What is' , '='),
8+
('plus' , '+'),
9+
('minus' , '-'),
10+
('multiplied by', '*'),
11+
('divided by' , '/'),
12+
('?' , '?');
13+
14+
DROP TABLE IF EXISTS tmp;
15+
CREATE TEMPORARY TABLE tmp (
16+
question TEXT NOT NULL,
17+
normalized TEXT
18+
);
19+
INSERT INTO tmp
20+
SELECT question, (
21+
WITH RECURSIVE normalizer (string, tokens, idx) AS (
22+
VALUES (
23+
REPLACE(wordy.question, '?', ' ?'),
24+
(SELECT JSON_GROUP_ARRAY(JSON(array))
25+
FROM (SELECT JSON_ARRAY(key, value) AS ARRAY FROM dict)),
26+
0
27+
)
28+
UNION ALL
29+
SELECT
30+
REPLACE(
31+
string,
32+
JSON_EXTRACT(tokens, PRINTF('$[%d][0]', idx)),
33+
JSON_EXTRACT(tokens, PRINTF('$[%d][1]', idx))
34+
),
35+
tokens,
36+
idx + 1
37+
FROM normalizer
38+
WHERE idx < JSON_ARRAY_LENGTH(tokens)
39+
)
40+
SELECT string
41+
FROM normalizer
42+
WHERE idx = (SELECT MAX(idx) FROM normalizer)
43+
)
44+
FROM wordy
45+
;
46+
47+
ALTER TABLE tmp ADD COLUMN tokens TEXT;
48+
WITH to_tokens (question, tokens) AS (
49+
SELECT question,
50+
(WITH RECURSIVE tokenizer (string, token) AS (
51+
VALUES (tmp.normalized || ' ', NULL)
52+
UNION ALL
53+
SELECT
54+
SUBSTR(string, INSTR(string, ' ') + 1),
55+
SUBSTR(string, 1, INSTR(string, ' ') - 1)
56+
FROM tokenizer
57+
WHERE string <> ''
58+
LIMIT 10
59+
)
60+
SELECT JSON_GROUP_ARRAY(token) tokens
61+
FROM tokenizer
62+
WHERE token NOTNULL
63+
)
64+
FROM tmp
65+
)
66+
UPDATE tmp
67+
SET tokens = to_tokens.tokens
68+
FROM to_tokens
69+
WHERE tmp.question = to_tokens.question
70+
;
71+
72+
UPDATE wordy
73+
SET error = 'unknown operation'
74+
FROM tmp
75+
WHERE wordy.question = tmp.question
76+
AND ( JSON_EXTRACT(tokens, '$[0]') <> '='
77+
OR JSON_EXTRACT(tokens, '$[#]') <> '?'
78+
OR (SELECT 1
79+
FROM JSON_EACH(tokens) j
80+
WHERE j.value NOT IN (SELECT value FROM dict)
81+
AND NOT(REGEXP('^-?[0-9]+$', j.VALUE))))
82+
AND error ISNULL
83+
;
84+
85+
UPDATE wordy
86+
SET error = 'syntax error'
87+
FROM tmp
88+
WHERE wordy.question = tmp.question
89+
AND REGEXP('^= -?[0-9]+( [-+*/] -?[0-9]+)* \?$', tmp.normalized) != 1
90+
AND wordy.error ISNULL
91+
;
92+
93+
UPDATE wordy
94+
SET result = (
95+
WITH RECURSIVE calc (expr) AS (
96+
VALUES (JSON_REMOVE(tmp.tokens, '$[#-1]', '$[0]'))
97+
UNION ALL
98+
SELECT JSON_SET(
99+
JSON_REMOVE(expr, '$[0]', '$[0]'),
100+
'$[0]',
101+
CASE JSON_EXTRACT(expr, '$[1]')
102+
WHEN '+'
103+
THEN JSON_EXTRACT(expr, '$[0]') + JSON_EXTRACT(expr, '$[2]')
104+
WHEN '-'
105+
THEN JSON_EXTRACT(expr, '$[0]') - JSON_EXTRACT(expr, '$[2]')
106+
WHEN '*'
107+
THEN JSON_EXTRACT(expr, '$[0]') * JSON_EXTRACT(expr, '$[2]')
108+
WHEN '/'
109+
THEN JSON_EXTRACT(expr, '$[0]') / JSON_EXTRACT(expr, '$[2]')
110+
END
111+
)
112+
FROM calc
113+
WHERE JSON_ARRAY_LENGTH(expr) >= 3
114+
)
115+
SELECT JSON_EXTRACT(expr, '$[0]')
116+
FROM calc
117+
WHERE JSON_ARRAY_LENGTH(expr) = 1
118+
)
119+
FROM tmp
120+
WHERE wordy.question = tmp.question
121+
AND error ISNULL
122+
;
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[88bf4b28-0de3-4883-93c7-db1b14aa806e]
13+
description = "just a number"
14+
15+
[18983214-1dfc-4ebd-ac77-c110dde699ce]
16+
description = "just a zero"
17+
18+
[607c08ee-2241-4288-916d-dae5455c87e6]
19+
description = "just a negative number"
20+
21+
[bb8c655c-cf42-4dfc-90e0-152fcfd8d4e0]
22+
description = "addition"
23+
24+
[bb9f2082-171c-46ad-ad4e-c3f72087c1b5]
25+
description = "addition with a left hand zero"
26+
27+
[6fa05f17-405a-4742-80ae-5d1a8edb0d5d]
28+
description = "addition with a right hand zero"
29+
30+
[79e49e06-c5ae-40aa-a352-7a3a01f70015]
31+
description = "more addition"
32+
33+
[b345dbe0-f733-44e1-863c-5ae3568f3803]
34+
description = "addition with negative numbers"
35+
36+
[cd070f39-c4cc-45c4-97fb-1be5e5846f87]
37+
description = "large addition"
38+
39+
[0d86474a-cd93-4649-a4fa-f6109a011191]
40+
description = "subtraction"
41+
42+
[30bc8395-5500-4712-a0cf-1d788a529be5]
43+
description = "multiplication"
44+
45+
[34c36b08-8605-4217-bb57-9a01472c427f]
46+
description = "division"
47+
48+
[da6d2ce4-fb94-4d26-8f5f-b078adad0596]
49+
description = "multiple additions"
50+
51+
[7fd74c50-9911-4597-be09-8de7f2fea2bb]
52+
description = "addition and subtraction"
53+
54+
[b120ffd5-bad6-4e22-81c8-5512e8faf905]
55+
description = "multiple subtraction"
56+
57+
[4f4a5749-ef0c-4f60-841f-abcfaf05d2ae]
58+
description = "subtraction then addition"
59+
60+
[312d908c-f68f-42c9-aa75-961623cc033f]
61+
description = "multiple multiplication"
62+
63+
[38e33587-8940-4cc1-bc28-bfd7e3966276]
64+
description = "addition and multiplication"
65+
66+
[3c854f97-9311-46e8-b574-92b60d17d394]
67+
description = "multiple division"
68+
69+
[3ad3e433-8af7-41ec-aa9b-97b42ab49357]
70+
description = "unknown operation"
71+
72+
[8a7e85a8-9e7b-4d46-868f-6d759f4648f8]
73+
description = "Non math question"
74+
75+
[42d78b5f-dbd7-4cdb-8b30-00f794bb24cf]
76+
description = "reject problem missing an operand"
77+
78+
[c2c3cbfc-1a72-42f2-b597-246e617e66f5]
79+
description = "reject problem with no operands or operators"
80+
81+
[4b3df66d-6ed5-4c95-a0a1-d38891fbdab6]
82+
description = "reject two operations in a row"
83+
84+
[6abd7a50-75b4-4665-aa33-2030fd08bab1]
85+
description = "reject two numbers in a row"
86+
87+
[10a56c22-e0aa-405f-b1d2-c642d9c4c9de]
88+
description = "reject postfix notation"
89+
90+
[0035bc63-ac43-4bb5-ad6d-e8651b7d954e]
91+
description = "reject prefix notation"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
DROP TABLE IF EXISTS wordy;
2+
CREATE TABLE wordy (
3+
question TEXT NOT NULL,
4+
result INTEGER ,
5+
error TEXT
6+
);
7+
8+
.mode csv
9+
.import ./data.csv wordy
10+
11+
UPDATE wordy SET result = NULL, error = NULL;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
DROP TABLE IF EXISTS tests;
2+
CREATE TABLE IF NOT EXISTS tests (
3+
-- uuid and description are taken from the test.toml file
4+
uuid TEXT PRIMARY KEY,
5+
description TEXT NOT NULL,
6+
-- The following section is needed by the online test-runner
7+
status TEXT DEFAULT 'fail',
8+
message TEXT,
9+
output TEXT,
10+
test_code TEXT,
11+
task_id INTEGER DEFAULT NULL,
12+
-- Here are columns for the actual tests
13+
question TEXT NOT NULL,
14+
expected_result INTEGER,
15+
expected_error TEXT
16+
);
17+
18+
INSERT INTO tests (uuid, description, question, expected_result, expected_error)
19+
VALUES
20+
('88bf4b28-0de3-4883-93c7-db1b14aa806e', 'just a number', 'What is 5?', 5, NULL),
21+
('18983214-1dfc-4ebd-ac77-c110dde699ce', 'just a zero', 'What is 0?', 0, NULL),
22+
('607c08ee-2241-4288-916d-dae5455c87e6', 'just a negative number', 'What is -123?', -123, NULL),
23+
('bb8c655c-cf42-4dfc-90e0-152fcfd8d4e0', 'addition', 'What is 1 plus 1?', 2, NULL),
24+
('bb9f2082-171c-46ad-ad4e-c3f72087c1b5', 'addition with a left hand zero', 'What is 0 plus 2?', 2, NULL),
25+
('6fa05f17-405a-4742-80ae-5d1a8edb0d5d', 'addition with a right hand zero', 'What is 3 plus 0?', 3, NULL),
26+
('79e49e06-c5ae-40aa-a352-7a3a01f70015', 'more addition', 'What is 53 plus 2?', 55, NULL),
27+
('b345dbe0-f733-44e1-863c-5ae3568f3803', 'addition with negative numbers', 'What is -1 plus -10?', -11, NULL),
28+
('cd070f39-c4cc-45c4-97fb-1be5e5846f87', 'large addition', 'What is 123 plus 45678?', 45801, NULL),
29+
('0d86474a-cd93-4649-a4fa-f6109a011191', 'subtraction', 'What is 4 minus -12?', 16, NULL),
30+
('30bc8395-5500-4712-a0cf-1d788a529be5', 'multiplication', 'What is -3 multiplied by 25?', -75, NULL),
31+
('34c36b08-8605-4217-bb57-9a01472c427f', 'division', 'What is 33 divided by -3?', -11, NULL),
32+
('da6d2ce4-fb94-4d26-8f5f-b078adad0596', 'multiple additions', 'What is 1 plus 1 plus 1?', 3, NULL),
33+
('7fd74c50-9911-4597-be09-8de7f2fea2bb', 'addition and subtraction', 'What is 1 plus 5 minus -2?', 8, NULL),
34+
('b120ffd5-bad6-4e22-81c8-5512e8faf905', 'multiple subtraction', 'What is 20 minus 4 minus 13?', 3, NULL),
35+
('4f4a5749-ef0c-4f60-841f-abcfaf05d2ae', 'subtraction then addition', 'What is 17 minus 6 plus 3?', 14, NULL),
36+
('312d908c-f68f-42c9-aa75-961623cc033f', 'multiple multiplication', 'What is 2 multiplied by -2 multiplied by 3?', -12, NULL),
37+
('38e33587-8940-4cc1-bc28-bfd7e3966276', 'addition and multiplication', 'What is -3 plus 7 multiplied by -2?', -8, NULL),
38+
('3c854f97-9311-46e8-b574-92b60d17d394', 'multiple division', 'What is -12 divided by 2 divided by -3?', 2, NULL),
39+
('3ad3e433-8af7-41ec-aa9b-97b42ab49357', 'unknown operation', 'What is 52 cubed?', NULL, 'unknown operation'),
40+
('8a7e85a8-9e7b-4d46-868f-6d759f4648f8', 'Non math question', 'Who is the President of the United States?', NULL, 'unknown operation'),
41+
('42d78b5f-dbd7-4cdb-8b30-00f794bb24cf', 'reject problem missing an operand', 'What is 1 plus?', NULL, 'syntax error'),
42+
('c2c3cbfc-1a72-42f2-b597-246e617e66f5', 'reject problem with no operands or operators', 'What is?', NULL, 'syntax error'),
43+
('4b3df66d-6ed5-4c95-a0a1-d38891fbdab6', 'reject two operations in a row', 'What is 1 plus plus 2?', NULL, 'syntax error'),
44+
('6abd7a50-75b4-4665-aa33-2030fd08bab1', 'reject two numbers in a row', 'What is 1 plus 2 1?', NULL, 'syntax error'),
45+
('10a56c22-e0aa-405f-b1d2-c642d9c4c9de', 'reject postfix notation', 'What is 1 2 plus?', NULL, 'syntax error'),
46+
('0035bc63-ac43-4bb5-ad6d-e8651b7d954e', 'reject prefix notation', 'What is plus 1 2?', NULL, 'syntax error');
47+

exercises/practice/wordy/data.csv

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"What is 5?",,
2+
"What is 0?",,
3+
"What is -123?",,
4+
"What is 1 plus 1?",,
5+
"What is 0 plus 2?",,
6+
"What is 3 plus 0?",,
7+
"What is 53 plus 2?",,
8+
"What is -1 plus -10?",,
9+
"What is 123 plus 45678?",,
10+
"What is 4 minus -12?",,
11+
"What is -3 multiplied by 25?",,
12+
"What is 33 divided by -3?",,
13+
"What is 1 plus 1 plus 1?",,
14+
"What is 1 plus 5 minus -2?",,
15+
"What is 20 minus 4 minus 13?",,
16+
"What is 17 minus 6 plus 3?",,
17+
"What is 2 multiplied by -2 multiplied by 3?",,
18+
"What is -3 plus 7 multiplied by -2?",,
19+
"What is -12 divided by 2 divided by -3?",,
20+
"What is 52 cubed?",,
21+
"Who is the President of the United States?",,
22+
"What is 1 plus?",,
23+
"What is?",,
24+
"What is 1 plus plus 2?",,
25+
"What is 1 plus 2 1?",,
26+
"What is 1 2 plus?",,
27+
"What is plus 1 2?",,

0 commit comments

Comments
 (0)