 # uzilan's solution

## to Wordy in the Java Track

Published at May 26 2019 · 0 comments
Instructions
Test suite
Solution

#### Note:

This exercise has changed since this solution was written.

Parse and evaluate simple math word problems returning the answer as an integer.

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)

## Bonus — Exponentials

If you'd like, handle exponentials.

What is 2 raised to the 5th power?

32

# Running the tests

You can run all the tests for an exercise by entering

``````\$ gradle test
``````

## Source

Inspired by one of the generated questions in the Extreme Startup game. https://github.com/rchatley/extreme_startup

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### WordProblemSolverTest.java

``````import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Before;
import org.junit.rules.ExpectedException;

import static org.junit.Assert.assertEquals;

public class WordProblemSolverTest {

@Rule
public ExpectedException expectedException = ExpectedException.none();

WordProblemSolver solver;

@Before
public void setup() {
solver = new WordProblemSolver();
}

@Test
assertEquals(2, solver.solve("What is 1 plus 1?"));
}

@Ignore("Remove to run test")
@Test
assertEquals(55, solver.solve("What is 53 plus 2?"));
}

@Ignore("Remove to run test")
@Test
assertEquals(-11, solver.solve("What is -1 plus -10?"));
}

@Ignore("Remove to run test")
@Test
assertEquals(45801, solver.solve("What is 123 plus 45678?"));
}

@Ignore("Remove to run test")
@Test
public void testSingleSubtraction() {
assertEquals(16, solver.solve("What is 4 minus -12?"));
}

@Ignore("Remove to run test")
@Test
public void testSingleMultiplication() {
assertEquals(-75, solver.solve("What is -3 multiplied by 25?"));
}

@Ignore("Remove to run test")
@Test
public void testSingleDivision() {
assertEquals(-11, solver.solve("What is 33 divided by -3?"));
}

@Ignore("Remove to run test")
@Test
assertEquals(3, solver.solve("What is 1 plus 1 plus 1?"));
}

@Ignore("Remove to run test")
@Test
assertEquals(8, solver.solve("What is 1 plus 5 minus -2?"));
}

@Ignore("Remove to run test")
@Test
public void testMultipleSubtractions() {
assertEquals(3, solver.solve("What is 20 minus 4 minus 13?"));
}

@Ignore("Remove to run test")
@Test
assertEquals(14, solver.solve("What is 17 minus 6 plus 3?"));
}

@Ignore("Remove to run test")
@Test
public void testMultipleMultiplications() {
assertEquals(-12, solver.solve("What is 2 multiplied by -2 multiplied by 3?"));
}

@Ignore("Remove to run test")
@Test
assertEquals(-8, solver.solve("What is -3 plus 7 multiplied by -2?"));
}

@Ignore("Remove to run test")
@Test
public void testMultipleDivisions() {
assertEquals(2, solver.solve("What is -12 divided by 2 divided by -3?"));
}

@Ignore("Remove to run test")
@Test
public void testUnknownOperation() {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("I'm sorry, I don't understand the question!");

solver.solve("What is 52 cubed?");
}

@Ignore("Remove to run test")
@Test
public void testInvalidQuestionFormat() {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("I'm sorry, I don't understand the question!");

// See https://en.wikipedia.org/wiki/President_of_the_United_States if you really need to know!
solver.solve("Who is the President of the United States?");
}

}``````
``````import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.BiFunction;
import java.util.regex.Pattern;

import static java.lang.Integer.parseInt;

public class WordProblemSolver {

private static final Pattern PATTERN =
Pattern.compile("What is -?\\d+ [(plus|minus|multiplied by|divided by) -?\\d+]+\\?");

public int solve(final String input) {
if (!PATTERN.matcher(input).matches()) {
throw new IllegalArgumentException("I'm sorry, I don't understand the question!");
}

final var expression = input.substring(8, input.length() - 1);
final var iter = new ThingIterator(expression);
var x = iter.next().number;

while (iter.hasNext()) {
final var op = iter.next().op;
final var y = iter.next().number;
x = op.apply(x, y);
}

return x;
}

static class Thing {
final Integer number;
final BiFunction<Integer, Integer, Integer> op;

Thing(final int number) {
this.number = number;
this.op = null;
}

Thing(final BiFunction<Integer, Integer, Integer> op) {
this.number = null;
this.op = op;
}
}

class ThingIterator implements Iterator<Thing> {

private int position = 0;
private String input;

ThingIterator(final String input) {
this.input = input;
}

@Override
public boolean hasNext() {
return getNextSpace() != -1;
}

@Override
public Thing next() {
final var s = hasNext()
? input.substring(position, getNextSpace())
: input.substring(position);

try {
final var thing = new Thing(parseInt(s));
position += s.length() + 1;
return thing;
} catch (NumberFormatException e) {
return parseOperation(s);
}
}

private Thing parseOperation(final String operation) {
switch (operation) {
case "plus":
position += "plus ".length();
return new Thing(Integer::sum);
case "minus":
position += "minus ".length();
return new Thing((x, y) -> x - y);
case "multiplied":
position += "multiplied by ".length();
return new Thing((x, y) -> x * y);
case "divided":
position += "divided by ".length();
return new Thing((x, y) -> x / y);
default:
throw new NoSuchElementException();
}
}

private int getNextSpace() {
return input.indexOf(' ', position);
}
}
}``````