From 6fd404bb712fa586ea20463fd3c383034d9a5cfe Mon Sep 17 00:00:00 2001 From: Eric Willigers Date: Mon, 1 Jan 2024 13:14:57 +1100 Subject: [PATCH] feat: add wordy exercise resolves #97 --- config.json | 8 + .../practice/wordy/.docs/instructions.md | 59 +++++++ exercises/practice/wordy/.meta/config.json | 19 +++ exercises/practice/wordy/.meta/example.v | 59 +++++++ exercises/practice/wordy/.meta/tests.toml | 72 +++++++++ exercises/practice/wordy/run_test.v | 148 ++++++++++++++++++ exercises/practice/wordy/wordy.v | 4 + 7 files changed, 369 insertions(+) create mode 100644 exercises/practice/wordy/.docs/instructions.md create mode 100644 exercises/practice/wordy/.meta/config.json create mode 100644 exercises/practice/wordy/.meta/example.v create mode 100644 exercises/practice/wordy/.meta/tests.toml create mode 100644 exercises/practice/wordy/run_test.v create mode 100644 exercises/practice/wordy/wordy.v diff --git a/config.json b/config.json index 15743ab..8bb3248 100644 --- a/config.json +++ b/config.json @@ -185,6 +185,14 @@ "prerequisites": [], "difficulty": 6 }, + { + "slug": "wordy", + "name": "Wordy", + "uuid": "a8449f36-4860-4934-9b32-8ce38faac5de", + "practices": [], + "prerequisites": [], + "difficulty": 6 + }, { "uuid": "c0a26fda-7ce7-43f0-8da1-cb5b5d5e434f", "slug": "isbn-verifier", diff --git a/exercises/practice/wordy/.docs/instructions.md b/exercises/practice/wordy/.docs/instructions.md new file mode 100644 index 0000000..aafb9ee --- /dev/null +++ b/exercises/practice/wordy/.docs/instructions.md @@ -0,0 +1,59 @@ +# Instructions + +Parse and evaluate simple math word problems returning the answer as an integer. + +## Iteration 0 — Numbers + +Problems with no operations simply evaluate to the number given. + +> What is 5? + +Evaluates to 5. + +## Iteration 1 — Addition + +Add two numbers together. + +> What is 5 plus 13? + +Evaluates to 18. + +Handle large numbers and negative numbers. + +## Iteration 2 — Subtraction, Multiplication and Division + +Now, perform the other three operations. + +> What is 7 minus 5? + +2 + +> What is 6 multiplied by 4? + +24 + +> What is 25 divided by 5? + +5 + +## Iteration 3 — Multiple Operations + +Handle a set of operations, in sequence. + +Since these are verbal word problems, evaluate the expression from left-to-right, _ignoring the typical order of operations._ + +> What is 5 plus 13 plus 6? + +24 + +> What is 3 plus 2 multiplied by 3? + +15 (i.e. not 9) + +## Iteration 4 — Errors + +The parser should reject: + +- Unsupported operations ("What is 52 cubed?") +- Non-math questions ("Who is the President of the United States") +- Word problems with invalid syntax ("What is 1 plus plus 2?") diff --git a/exercises/practice/wordy/.meta/config.json b/exercises/practice/wordy/.meta/config.json new file mode 100644 index 0000000..17c8ca0 --- /dev/null +++ b/exercises/practice/wordy/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "wordy.v" + ], + "test": [ + "run_test.v" + ], + "example": [ + ".meta/example.v" + ] + }, + "blurb": "Parse and evaluate simple math word problems returning the answer as an integer.", + "source": "Inspired by one of the generated questions in the Extreme Startup game.", + "source_url": "https://github.com/rchatley/extreme_startup" +} diff --git a/exercises/practice/wordy/.meta/example.v b/exercises/practice/wordy/.meta/example.v new file mode 100644 index 0000000..f570e48 --- /dev/null +++ b/exercises/practice/wordy/.meta/example.v @@ -0,0 +1,59 @@ +module main + +import strconv + +fn add(a int, b int) int { + return a + b +} + +fn subtract(a int, b int) int { + return a - b +} + +fn multiply(a int, b int) int { + return a * b +} + +fn divide(a int, b int) int { + return a / b +} + +fn answer(question string) ?int { + if question.index_u8(u8(`?`)) + 1 != question.len { + return none + } + + words := question#[0..-1].split(' ') + if words.len < 3 || words[0] != 'What' || words[1] != 'is' { + return none + } + mut index := 2 + + mut a := 0 + mut operation := add + for index != words.len && index + 2 != words.len { + b := strconv.atoi(words[index]) or { return none } + a = operation(a, b) + index++ + if index == words.len { + return a + } + + operation = match words[index] { + 'plus' { add } + 'minus' { subtract } + 'multiplied' { multiply } + 'divided' { divide } + else { return none } + } + index++ + + if operation == multiply || operation == divide { + if words[index] != 'by' { + return none + } + index++ + } + } + return none +} diff --git a/exercises/practice/wordy/.meta/tests.toml b/exercises/practice/wordy/.meta/tests.toml new file mode 100644 index 0000000..912d576 --- /dev/null +++ b/exercises/practice/wordy/.meta/tests.toml @@ -0,0 +1,72 @@ +# This is an auto-generated file. Regular comments will be removed when this +# file is regenerated. Regenerating will not touch any manually added keys, +# so comments can be added in a "comment" key. + +[88bf4b28-0de3-4883-93c7-db1b14aa806e] +description = "just a number" + +[bb8c655c-cf42-4dfc-90e0-152fcfd8d4e0] +description = "addition" + +[79e49e06-c5ae-40aa-a352-7a3a01f70015] +description = "more addition" + +[b345dbe0-f733-44e1-863c-5ae3568f3803] +description = "addition with negative numbers" + +[cd070f39-c4cc-45c4-97fb-1be5e5846f87] +description = "large addition" + +[0d86474a-cd93-4649-a4fa-f6109a011191] +description = "subtraction" + +[30bc8395-5500-4712-a0cf-1d788a529be5] +description = "multiplication" + +[34c36b08-8605-4217-bb57-9a01472c427f] +description = "division" + +[da6d2ce4-fb94-4d26-8f5f-b078adad0596] +description = "multiple additions" + +[7fd74c50-9911-4597-be09-8de7f2fea2bb] +description = "addition and subtraction" + +[b120ffd5-bad6-4e22-81c8-5512e8faf905] +description = "multiple subtraction" + +[4f4a5749-ef0c-4f60-841f-abcfaf05d2ae] +description = "subtraction then addition" + +[312d908c-f68f-42c9-aa75-961623cc033f] +description = "multiple multiplication" + +[38e33587-8940-4cc1-bc28-bfd7e3966276] +description = "addition and multiplication" + +[3c854f97-9311-46e8-b574-92b60d17d394] +description = "multiple division" + +[3ad3e433-8af7-41ec-aa9b-97b42ab49357] +description = "unknown operation" + +[8a7e85a8-9e7b-4d46-868f-6d759f4648f8] +description = "Non math question" + +[42d78b5f-dbd7-4cdb-8b30-00f794bb24cf] +description = "reject problem missing an operand" + +[c2c3cbfc-1a72-42f2-b597-246e617e66f5] +description = "reject problem with no operands or operators" + +[4b3df66d-6ed5-4c95-a0a1-d38891fbdab6] +description = "reject two operations in a row" + +[6abd7a50-75b4-4665-aa33-2030fd08bab1] +description = "reject two numbers in a row" + +[10a56c22-e0aa-405f-b1d2-c642d9c4c9de] +description = "reject postfix notation" + +[0035bc63-ac43-4bb5-ad6d-e8651b7d954e] +description = "reject prefix notation" diff --git a/exercises/practice/wordy/run_test.v b/exercises/practice/wordy/run_test.v new file mode 100644 index 0000000..9035e43 --- /dev/null +++ b/exercises/practice/wordy/run_test.v @@ -0,0 +1,148 @@ +module main + +fn test_just_a_number() { + question := 'What is 5?' + assert answer(question)! == 5 +} + +fn test_addition() { + question := 'What is 1 plus 1?' + assert answer(question)! == 2 +} + +fn test_more_addition() { + question := 'What is 53 plus 2?' + assert answer(question)! == 55 +} + +fn test_addition_with_negative_numbers() { + question := 'What is -1 plus -10?' + assert answer(question)! == -11 +} + +fn test_large_addition() { + question := 'What is 123 plus 45678?' + assert answer(question)! == 45801 +} + +fn test_subtraction() { + question := 'What is 4 minus -12?' + assert answer(question)! == 16 +} + +fn test_multiplication() { + question := 'What is -3 multiplied by 25?' + assert answer(question)! == -75 +} + +fn test_division() { + question := 'What is 33 divided by -3?' + assert answer(question)! == -11 +} + +fn test_multiple_additions() { + question := 'What is 1 plus 1 plus 1?' + assert answer(question)! == 3 +} + +fn test_addition_and_subtraction() { + question := 'What is 1 plus 5 minus -2?' + assert answer(question)! == 8 +} + +fn test_multiple_subtraction() { + question := 'What is 20 minus 4 minus 13?' + assert answer(question)! == 3 +} + +fn test_subtraction_then_addition() { + question := 'What is 17 minus 6 plus 3?' + assert answer(question)! == 14 +} + +fn test_multiple_multiplication() { + question := 'What is 2 multiplied by -2 multiplied by 3?' + assert answer(question)! == -12 +} + +fn test_addition_and_multiplication() { + question := 'What is -3 plus 7 multiplied by -2?' + assert answer(question)! == -8 +} + +fn test_multiple_division() { + question := 'What is -12 divided by 2 divided by -3?' + assert answer(question)! == 2 +} + +fn test_unknown_operation() { + question := 'What is 52 cubed?' + if res := answer(question) { + assert false, 'unknown operation should be rejected' + } else { + assert true + } +} + +fn test_non_math_question() { + question := 'Who is the President of the United States?' + if res := answer(question) { + assert false, 'Non math question should be rejected' + } else { + assert true + } +} + +fn test_reject_problem_missing_an_operand() { + question := 'What is 1 plus?' + if res := answer(question) { + assert false, 'problem missing an operand should be rejected' + } else { + assert true + } +} + +fn test_reject_problem_with_no_operands_or_operators() { + question := 'What is?' + if res := answer(question) { + assert false, 'problem with no operands or operators should be rejected' + } else { + assert true + } +} + +fn test_reject_two_operations_in_a_row() { + question := 'What is 1 plus plus 2?' + if res := answer(question) { + assert false, 'two operations in a row should be rejected' + } else { + assert true + } +} + +fn test_reject_two_numbers_in_a_row() { + question := 'What is 1 plus 2 1?' + if res := answer(question) { + assert false, 'two numbers in a row should be rejected' + } else { + assert true + } +} + +fn test_reject_postfix_notation() { + question := 'What is 1 2 plus?' + if res := answer(question) { + assert false, 'postfix notation should be rejected' + } else { + assert true + } +} + +fn test_reject_prefix_notation() { + question := 'What is plus 1 2?' + if res := answer(question) { + assert false, 'prefix notation should be rejected' + } else { + assert true + } +} diff --git a/exercises/practice/wordy/wordy.v b/exercises/practice/wordy/wordy.v new file mode 100644 index 0000000..a923bba --- /dev/null +++ b/exercises/practice/wordy/wordy.v @@ -0,0 +1,4 @@ +module main + +fn answer(question string) ?int { +}