forked from exercism/elm
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4e6a2d3
commit fdded4b
Showing
6 changed files
with
371 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# Wordy | ||
|
||
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?") | ||
|
||
## Bonus — Exponentials | ||
|
||
If you'd like, handle exponentials. | ||
|
||
> What is 2 raised to the 5th power? | ||
32 | ||
|
||
## Hints | ||
|
||
This is a perfect opportunity to learn `elm/parser` ([docs](https://package.elm-lang.org/packages/elm/parser/latest/))! | ||
|
||
## Elm Installation | ||
|
||
Refer to the [Installing Elm](https://exercism.io/tracks/elm/installation) page | ||
for information about installing elm. | ||
|
||
## Writing the Code | ||
|
||
The code you have to write is located inside the `src/` directory of the exercise. | ||
Elm automatically installs packages dependencies the first time you run the tests | ||
so we can start by running the tests from the exercise directory with: | ||
|
||
```bash | ||
$ elm-test | ||
``` | ||
|
||
To automatically run tests again when you save changes: | ||
|
||
```bash | ||
$ elm-test --watch | ||
``` | ||
|
||
As you work your way through the tests suite in the file `tests/Tests.elm`, | ||
be sure to remove the `skip <|` | ||
calls from each test until you get them all passing! | ||
|
||
## Source | ||
|
||
Inspired by one of the generated questions in the Extreme Startup game. [https://github.com/rchatley/extreme_startup](https://github.com/rchatley/extreme_startup) | ||
|
||
## Submitting Incomplete Solutions | ||
|
||
It is possible to submit an incomplete solution so you can see how others have | ||
completed the exercise. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"type": "application", | ||
"source-directories": [ | ||
"src" | ||
], | ||
"elm-version": "0.19.1", | ||
"dependencies": { | ||
"direct": { | ||
"elm/core": "1.0.0", | ||
"elm/parser": "1.1.0" | ||
}, | ||
"indirect": {} | ||
}, | ||
"test-dependencies": { | ||
"direct": { | ||
"elm-explorations/test": "1.0.0", | ||
"rtfeldman/elm-iso8601-date-strings": "1.1.3" | ||
}, | ||
"indirect": { | ||
"elm/random": "1.0.0", | ||
"elm/json": "1.1.3" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module Wordy exposing (answer) | ||
|
||
|
||
answer : String -> Maybe Int | ||
answer problem = | ||
Debug.todo "Please implement this function" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
module Wordy exposing (answer) | ||
|
||
import Parser as P exposing ((|.), (|=), Parser, Trailing(..)) | ||
|
||
|
||
{-| An `Operation` is a single mathematical operation. It may contain a nested, preceding operation to the left. | ||
-} | ||
type Operation | ||
= Display Int | ||
| Add Number Int | ||
| Multiply Number Int | ||
| Divide Number Int | ||
|
||
|
||
{-| A `Number` may be a literal integer, or the result of a preceding computation. | ||
-} | ||
type Number | ||
= Number Int | ||
| Computation Operation | ||
|
||
|
||
{-| Parses a string and solves any problems correctly specified therein or returns `Nothing` in the event of a parse error. | ||
-} | ||
answer : String -> Maybe Int | ||
answer problem = | ||
P.run parser problem | ||
|> Result.toMaybe | ||
|> Maybe.map solveProblem | ||
|
||
|
||
{-| Solves an `Operation` (possibly including nested operations) for a numerical result. | ||
-} | ||
solveProblem : Operation -> Int | ||
solveProblem operation = | ||
let | ||
toNum num = | ||
case num of | ||
Number i -> | ||
i | ||
|
||
Computation p -> | ||
solveProblem p | ||
in | ||
case operation of | ||
Display i -> | ||
i | ||
|
||
Add i1 i2 -> | ||
toNum i1 + i2 | ||
|
||
Multiply i1 i2 -> | ||
toNum i1 * i2 | ||
|
||
Divide i1 i2 -> | ||
toNum i1 // i2 | ||
|
||
|
||
{-| Parses math problems of the form `"What is <x> [chain of operations]?"`, where `<x>` is an integer and `[chain of operations]` is of the form: `"operation1 n1 operation2 n2 operation3 n3"`, where `n`s are integer and `operation`s are selected from the following list: | ||
- `"plus"` -- Addition | ||
- `"minus"` -- Subtraction | ||
- `"multiplied by"` -- Multiplication | ||
- `"divided by"` -- Division | ||
-} | ||
parser : Parser Operation | ||
parser = | ||
let | ||
packOperations : Int -> List (Number -> Operation) -> Operation | ||
packOperations d l = | ||
case l of | ||
[] -> | ||
Display d | ||
|
||
f :: fs -> | ||
List.foldl (\next prev -> next (Computation prev)) (f (Number d)) fs | ||
|
||
operation : String -> (Number -> Int -> Operation) -> Parser (Number -> Operation) | ||
operation keyword f = | ||
P.succeed (\i -> \n -> f n i) | ||
|. P.keyword keyword | ||
|= int | ||
|
||
plus = | ||
operation "plus" Add | ||
|
||
minus = | ||
operation "minus" (\d1 d2 -> Add d1 (negate d2)) | ||
|
||
multiply = | ||
operation "multiplied by" Multiply | ||
|
||
divide = | ||
operation "divided by" Divide | ||
in | ||
P.succeed packOperations | ||
|. P.spaces | ||
|. P.keyword "What is" | ||
|= int | ||
|= P.sequence | ||
{ start = "" | ||
, separator = "" | ||
, end = "?" | ||
, spaces = P.spaces | ||
, item = P.oneOf [ plus, minus, multiply, divide ] | ||
, trailing = Optional | ||
} | ||
|. P.spaces | ||
|. P.end | ||
|
||
|
||
{-| Parses an integer of the form `"117"` or `"-8"`. | ||
-} | ||
int : Parser Int | ||
int = | ||
P.succeed identity | ||
|. P.spaces | ||
|= P.oneOf | ||
[ P.succeed negate | ||
|. P.symbol "-" | ||
|= P.int | ||
, P.int | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
module Tests exposing (tests) | ||
|
||
import Expect | ||
import Test exposing (..) | ||
import Wordy exposing (answer) | ||
|
||
|
||
tests : Test | ||
tests = | ||
describe "Wordy" | ||
[ test "just a number" <| | ||
\() -> | ||
Expect.equal (Just 5) <| answer "What is 5?" | ||
, skip <| | ||
test "addition" <| | ||
\() -> | ||
Expect.equal (Just 2) <| answer "What is 1 plus 1?" | ||
, skip <| | ||
test "more addition" <| | ||
\() -> | ||
Expect.equal (Just 55) <| answer "What is 53 plus 2?" | ||
, skip <| | ||
test "addition with negative numbers" <| | ||
\() -> | ||
Expect.equal (Just -11) <| answer "What is -1 plus -10?" | ||
, skip <| | ||
test "large addition" <| | ||
\() -> | ||
Expect.equal (Just 45801) <| answer "What is 123 plus 45678?" | ||
, skip <| | ||
test "subtraction" <| | ||
\() -> | ||
Expect.equal (Just 16) <| answer "What is 4 minus -12?" | ||
, skip <| | ||
test "multiplication" <| | ||
\() -> | ||
Expect.equal (Just -75) <| answer "What is -3 multiplied by 25?" | ||
, skip <| | ||
test "division" <| | ||
\() -> | ||
Expect.equal (Just -11) <| answer "What is 33 divided by -3?" | ||
, skip <| | ||
test "multiple additions" <| | ||
\() -> | ||
Expect.equal (Just 3) <| answer "What is 1 plus 1 plus 1?" | ||
, skip <| | ||
test "addition and subtraction" <| | ||
\() -> | ||
Expect.equal (Just 8) <| answer "What is 1 plus 5 minus -2?" | ||
, skip <| | ||
test "multiple subtraction" <| | ||
\() -> | ||
Expect.equal (Just 3) <| answer "What is 20 minus 4 minus 13?" | ||
, skip <| | ||
test "subtraction then addition" <| | ||
\() -> | ||
Expect.equal (Just 14) <| answer "What is 17 minus 6 plus 3?" | ||
, skip <| | ||
test "multiple multiplication" <| | ||
\() -> | ||
Expect.equal (Just -12) <| answer "What is 2 multiplied by -2 multiplied by 3?" | ||
, skip <| | ||
test "addition and multiplication" <| | ||
\() -> | ||
Expect.equal (Just -8) <| answer "What is -3 plus 7 multiplied by -2?" | ||
, skip <| | ||
test "multiple division" <| | ||
\() -> | ||
Expect.equal (Just 2) <| answer "What is -12 divided by 2 divided by -3?" | ||
, skip <| | ||
test "unknown operation" <| | ||
\() -> | ||
Expect.equal Nothing <| answer "What is 52 cubed?" | ||
, skip <| | ||
test "Non math question" <| | ||
\() -> | ||
Expect.equal Nothing <| answer "Who is the President of the United States?" | ||
, skip <| | ||
test "reject problem missing an operand" <| | ||
\() -> | ||
Expect.equal Nothing <| answer "What is 1 plus?" | ||
, skip <| | ||
test "reject problem with no operands or operators" <| | ||
\() -> | ||
Expect.equal Nothing <| answer "What is?" | ||
, skip <| | ||
test "reject two operations in a row" <| | ||
\() -> | ||
Expect.equal Nothing <| answer "What is 1 plus plus 2?" | ||
, skip <| | ||
test "reject two numbers in a row" <| | ||
\() -> | ||
Expect.equal Nothing <| answer "What is 1 plus 2 1?" | ||
, skip <| | ||
test "reject postfix notation" <| | ||
\() -> | ||
Expect.equal Nothing <| answer "What is 1 2 plus?" | ||
, skip <| | ||
test "reject prefix notation" <| | ||
\() -> | ||
Expect.equal Nothing <| answer "What is plus 1 2?" | ||
] |