wordy.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import re
import operator


WHAT_IS = re.compile(r"What is (?P<first>-?\d+) (?P<calc>.+)\?$")


OPS = {
    'plus':          operator.add,
    'minus':         operator.sub,
    'multiplied by': operator.mul,
    'divided by':    operator.floordiv,
}

CALCULATION = re.compile(r'''
    \s?
    (?P<op>{ops})         # valid operation
    \s
    (?P<operand>-?\d+)    # operand
'''.format(
    ops='|'.join(OPS.keys()).replace(' ', '\\ ')
), re.VERBOSE)


def process(op_string, operand1):
    """
    Process an op string (e.g. "plus 2") against a given value

    This is recursive, so can be called with e.g. ("plus 2 minus 1")

    :param op_string: Op string to be processed
    :param operand1: Starting value for the op string to act on

    """
    if op_string:
        m = CALCULATION.match(op_string)
        if m:
            op_name = m.group('op')
            operand2 = int(m.group('operand'))
            # Perform the operation
            result = OPS[op_name](operand1, operand2)

            # Process the rest of the string against new result
            return process(op_string[len(m.group()):], result)

        raise ValueError("Invalid operation string")
    else:
        # No more calculations to do
        return operand1


def calculate(question):
    m = WHAT_IS.match(question)
    if m:
        value = int(m.group('first'))
        calc = m.group('calc')
        return process(calc, value)

    raise ValueError

Comments


You're not logged in right now. Please login via GitHub to comment