Ejemplo n.º 1
0
        def handleExponents(input):
            m = re.search(r'\bsquare (\w+)', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\bsquare (\w+)', r'\g<1>^2', input)

            m = re.search(r'\bsquared (\w+)', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\bsquared (\w+)', r'\g<1>^2', input)

            m = re.search(r'\b(\w+) squared', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\b(\w+) squared', r'\g<1>^2', input)

            m = re.search(r'\bsq (\w+)', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\bsq (\w+)', r'\g<1>^2', input)

            m = re.search(r'\b(\w+) cubed', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\b(\w+) cubed', r'\g<1>^3', input)

            m = re.search(r'\bcubic (\w+)', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\bcubic (\w+)', r'\g<1>^3', input)

            service = NumberService()
            m = re.search(r'\b(\w+) to the (\w+)( power)?', input)
            if m and self.isValidUnit(m.group(1)):
                if m.group(2) in service.__ordinals__:
                    exp = service.parseMagnitude(m.group(2))
                    input = re.sub(r'\b(\w+) to the (\w+)( power)?',
                                   r'\g<1>^' + str(exp), input)

            return input
Ejemplo n.º 2
0
        def handleExponents(input):
            m = re.search(r'\bsquare (\w+)', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\bsquare (\w+)', r'\g<1>^2', input)

            m = re.search(r'\bsquared (\w+)', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\bsquared (\w+)', r'\g<1>^2', input)

            m = re.search(r'\b(\w+) squared', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\b(\w+) squared', r'\g<1>^2', input)

            m = re.search(r'\bsq (\w+)', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\bsq (\w+)', r'\g<1>^2', input)

            m = re.search(r'\b(\w+) cubed', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\b(\w+) cubed', r'\g<1>^3', input)

            m = re.search(r'\bcubic (\w+)', input)
            if m and self.isValidUnit(m.group(1)):
                input = re.sub(r'\bcubic (\w+)', r'\g<1>^3', input)

            service = NumberService()
            m = re.search(r'\b(\w+) to the (\w+)( power)?', input)
            if m and self.isValidUnit(m.group(1)):
                if m.group(2) in service.__ordinals__:
                    exp = service.parseMagnitude(m.group(2))
                    input = re.sub(r'\b(\w+) to the (\w+)( power)?',
                                   r'\g<1>^' + str(exp), input)

            return input
Ejemplo n.º 3
0
            def findConstantMultiplications(input):
                split = input.split(' ')
                revision = ""

                converter = NumberService()
                for i, w in enumerate(split):
                    if i > 0 and w in MathService.__constants__:
                        if converter.isValid(split[i - 1]):
                            revision += " times"
                    if not revision:
                        revision = w
                    else:
                        revision += " " + w

                return revision
Ejemplo n.º 4
0
def parseEquation(self, input):
    """Solves the equation specified by the input string. This is a convenience
    method which would only be used if you'd rather not initialize a
    NumberService object.

    Args:
        input (str): An equation, specified in words, containing some
            combination of numbers, binary, and unary operations.

    Returns:
        The floating-point result of carrying out the computation.
    """

    service = NumberService()
    return service.parseEquation(input)
Ejemplo n.º 5
0
 def __init__(self):
     # map abstract arithmetic constructs to operators from 'operator'
     # module
     self.supported_ops = {
         ast.Add: op.add,
         ast.Sub: op.sub,
         ast.Mult: op.mul,
         ast.Div: op.truediv,
         ast.Pow: op.pow,
         ast.BitXor: op.xor,
         ast.USub: op.neg
     }
     # map english expression to operator object
     self.single_word_ops = {
         'plus': op.add,
         'minus': op.sub,
         'times': op.mul,
         'xor': op.xor,
         'XOR': op.xor,
         'to': op.pow,
     }
     self.double_word_ops = {
         'divided by': op.div,
         'raised to': op.pow,
     }
     # map operator object to string form
     self.op_to_str = {
         op.add: '+',
         op.sub: '-',
         op.mul: '*',
         op.div: '/',
         op.pow: '**',
         op.xor: '^',
     }
     self.number_service = NumberService()
Ejemplo n.º 6
0
            def numericalPrefix(dayMatch):
                # Grab 'three' of 'three weeks from'
                prefix = input.split(dayMatch.group(1))[0].strip().split(' ')
                prefix.reverse()
                prefix = filter(lambda s: s != 'and', prefix)

                # Generate best guess number
                service = NumberService()
                num = prefix[0]
                if service.isValid(num):
                    for n in prefix[1:]:
                        inc = n + " " + num
                        if service.isValid(inc):
                            num = inc
                        else:
                            break
                    return service.parse(num)
                return 1
Ejemplo n.º 7
0
    def parseUnits(self, input):
        """Carries out a conversion (represented as a string) and returns the
        result as a human-readable string.

        Args:
            input (str): Text representing a unit conversion, which should
                include a magnitude, a description of the initial units,
                and a description of the target units to which the quantity
                should be converted.

        Returns:
            A quantities object representing the converted quantity and its new
            units.
        """
        quantity = self.convert(input)
        units = ' '.join(str(quantity.units).split(' ')[1:])
        return NumberService.parseMagnitude(quantity.item()) + " " + units
Ejemplo n.º 8
0
    def parseUnits(self, input):
        """Carries out a conversion (represented as a string) and returns the
        result as a human-readable string.

        Args:
            input (str): Text representing a unit conversion, which should
                include a magnitude, a description of the initial units,
                and a description of the target units to which the quantity
                should be converted.

        Returns:
            A quantities object representing the converted quantity and its new
            units.
        """
        quantity = self.convert(input)
        units = ' '.join(str(quantity.units).split(' ')[1:])
        return NumberService.parseMagnitude(quantity.item()) + " " + units
Ejemplo n.º 9
0
    def convert(self, input):
        """Converts a string representation of some quantity of units into a
        quantities object.

        Args:
            input (str): A textual representation of some quantity of units,
                e.g., "fifty kilograms".

        Returns:
            A quantities object representing the described quantity and its
            units.
        """
        input = self._preprocess(input)

        n = NumberService().longestNumber(input)
        units = self.extractUnits(input)

        # Convert to quantity object, attempt conversion
        quantity = pq.Quantity(float(n), units[0])
        quantity.units = units[1]

        return quantity
Ejemplo n.º 10
0
            def convert(n):
                if n in self.__constants__:
                    return self.__constants__[n]

                converter = NumberService()
                return converter.parse(n)
Ejemplo n.º 11
0
        def handleMatch(time):
            relative = False

            if not time:
                return None

            # Default times: 10am, 3pm, 8pm
            elif time.group(1) == 'morning':
                h = 10
                m = 0
            elif time.group(1) == 'afternoon':
                h = 15
                m = 0
            elif time.group(1) == 'evening' or time.group(1) == 'tonight' or time.group(1) == 'eve':
                h = 20
                m = 0
            elif time.group(4) and time.group(5):
                # match relative times, e.g. in 5 hours
                h, m = 0, 0

                # Extract hours difference
                converter = NumberService()
                try:
                    diff = converter.parse(time.group(4))
                except:
                    return None

                if time.group(5) == 'hours':
                    h += diff
                else:
                    m += diff

                # Extract minutes difference
                if time.group(6):
                    converter = NumberService()
                    try:
                        diff = converter.parse(time.group(7))
                    except:
                        return None

                    if time.group(8) == 'hours':
                        h += diff
                    else:
                        m += diff

                relative = True
            elif time.group(9) and time.group(10):
                # match hour only time, e.g. 4 pm
                h = int(time.group(9))
                m = 0

                if time.group(10) == 'pm':
                    h += 12

            elif time.group(11) and time.group(12):
                # match phrases like "at 3?"
                h = int(time.group(12))
                m = 0

            else:
                # Convert from "HH:MM pm" format
                t = time.group(2)

                if ':' in t:
                    h, m = int(t.split(':')[0]), int(t.split(':')[1])
                else:
                    h, m = int(t.split('.')[0]), int(t.split('.')[1])

                try:
                    if time.group(3) == 'pm':
                        h = (h % 12) + 12
                except IndexError:
                    pass

            if relative:
                return self.now + datetime.timedelta(hours=h, minutes=m)

            # here we assume that time before 10 is meant to be pm
            # unless time includes 'am' or is in format 08:00 (starts with 0)
            elif h < 10 and time.group(3) != 'am' and time.group(1)[0] != '0':
                h = (h % 12) + 12
                return "%02d:%02d" % (h, m)
            else:
                return "%02d:%02d" % (h, m)
Ejemplo n.º 12
0
    def parse_basic_formula(self, input):
        lacks_operator = True
        running_number = ""
        expression = []  # store expression as list of operators and operands
        remaining_operator_words = 0  # number of words left from last operator
        xor_operator = False  # if there is an XOR somewhere in the expression

        for s_i, string in enumerate(input.split(" ")):
            # print string

            # moved forward through input split, so if there is a running
            # operator string, decrement remaining words
            if remaining_operator_words > 0:
                remaining_operator_words -= 1

            # only process if we're not still consuming a string operator
            if remaining_operator_words is 0:
                # if a single word expression is found, append the running
                # number to the expression and then the operator
                if string in self.single_word_ops:
                    expression.append(running_number.strip())
                    expression.append(self.single_word_ops.get(string, None))
                    if string == 'xor' or string == 'XOR':
                        xor_operator = True
                    running_number = ""
                    lacks_operator = False
                    remaining_operator_words = 1
                # if a double word expression is found, append the running
                # number to the expression and then the operator
                elif (s_i + 1 < len(input.split(" ")) and
                      string + " " + input.split(" ")[s_i + 1] in
                      self.double_word_ops):
                    expression.append(running_number.strip())
                    expression.append(self.double_word_ops.get(
                        string + " " + input.split(" ")[s_i + 1], None))
                    running_number = ""
                    lacks_operator = False
                    remaining_operator_words = 2
                # substring is not an operator, number is still running
                else:
                    running_number += string + " "

        # append last remaining running number if any
        if len(running_number) > 0:
            expression.append(running_number.strip())

        # if the expression seems valid with at least one operator, convert
        # its operands and operators to reduced number/primitive form
        if not lacks_operator:
            print "expression list: " + str(expression)
            expr_to_eval = ""
            ns = NumberService()
            for substr in expression:
                if type(substr) == str:
                    if not xor_operator:
                        expr_to_eval += str(float(ns.parse_english(substr))) + " "
                    # XOR requires integers, not floats
                    else:
                        expr_to_eval += str(int(ns.parse_english(substr))) + " "
                # map operator.function to its sign form
                else:
                    print "operator"
                    expr_to_eval += str(self.op_to_str.get(substr, None)) + " "
            print "expression to evaluate: " + expr_to_eval
            return self._eval_str_expr(expr_to_eval)
        else:
            raise Exception("You did not include an operator")
Ejemplo n.º 13
0
    def parse_basic_formula(self, input):
        lacks_operator = True
        running_number = ""
        expression = []  # store expression as list of operators and operands
        remaining_operator_words = 0  # number of words left from last operator
        xor_operator = False  # if there is an XOR somewhere in the expression

        for s_i, string in enumerate(input.split(" ")):
            # print string

            # moved forward through input split, so if there is a running
            # operator string, decrement remaining words
            if remaining_operator_words > 0:
                remaining_operator_words -= 1

            # only process if we're not still consuming a string operator
            if remaining_operator_words is 0:
                # if a single word expression is found, append the running
                # number to the expression and then the operator
                if string in self.single_word_ops:
                    expression.append(running_number.strip())
                    expression.append(self.single_word_ops.get(string, None))
                    if string == 'xor' or string == 'XOR':
                        xor_operator = True
                    running_number = ""
                    lacks_operator = False
                    remaining_operator_words = 1
                # if a double word expression is found, append the running
                # number to the expression and then the operator
                elif (s_i + 1 < len(input.split(" "))
                      and string + " " + input.split(" ")[s_i + 1]
                      in self.double_word_ops):
                    expression.append(running_number.strip())
                    expression.append(
                        self.double_word_ops.get(
                            string + " " + input.split(" ")[s_i + 1], None))
                    running_number = ""
                    lacks_operator = False
                    remaining_operator_words = 2
                # substring is not an operator, number is still running
                else:
                    running_number += string + " "

        # append last remaining running number if any
        if len(running_number) > 0:
            expression.append(running_number.strip())

        # if the expression seems valid with at least one operator, convert
        # its operands and operators to reduced number/primitive form
        if not lacks_operator:
            print "expression list: " + str(expression)
            expr_to_eval = ""
            ns = NumberService()
            for substr in expression:
                if type(substr) == str:
                    if not xor_operator:
                        expr_to_eval += str(float(
                            ns.parse_english(substr))) + " "
                    # XOR requires integers, not floats
                    else:
                        expr_to_eval += str(int(
                            ns.parse_english(substr))) + " "
                # map operator.function to its sign form
                else:
                    print "operator"
                    expr_to_eval += str(self.op_to_str.get(substr, None)) + " "
            print "expression to evaluate: " + expr_to_eval
            return self._eval_str_expr(expr_to_eval)
        else:
            raise Exception("You did not include an operator")
Ejemplo n.º 14
0
        def handleMatch(time):
            relative = False

            if not time:
                return None

            # Default times: 8am, 12pm, 7pm
            elif time.group(1) == 'morning':
                h = 8
                m = 0
            elif time.group(1) == 'afternoon':
                h = 12
                m = 0
            elif time.group(1) == 'evening':
                h = 19
                m = 0
            elif time.group(4) and time.group(5):
                h, m = 0, 0

                # Extract hours difference
                converter = NumberService()
                try:
                    diff = converter.parse(time.group(4))
                except:
                    return None

                if time.group(5) == 'hours':
                    h += diff
                else:
                    m += diff

                # Extract minutes difference
                if time.group(6):
                    converter = NumberService()
                    try:
                        diff = converter.parse(time.group(7))
                    except:
                        return None

                    if time.group(8) == 'hours':
                        h += diff
                    else:
                        m += diff

                relative = True
            else:
                # Convert from "HH:MM pm" format
                t = time.group(2)
                h, m = int(t.split(':')[0]) % 12, int(t.split(':')[1])

                try:
                    if time.group(3) == 'pm':
                        h += 12
                except IndexError:
                    pass

            if relative:
                return self.now + datetime.timedelta(hours=h, minutes=m)
            else:
                return datetime.datetime(
                    self.now.year, self.now.month, self.now.day, h, m
                )
Ejemplo n.º 15
0
        def handleMatch(time):
            relative = False

            if not time:
                return None

            # Default times: 8am, 12pm, 7pm
            elif time.group(1) == 'morning':
                h = 8
                m = 0
            elif time.group(1) == 'afternoon':
                h = 12
                m = 0
            elif time.group(1) == 'evening':
                h = 19
                m = 0
            elif time.group(4) and time.group(5):
                # match relative times, e.g. in 5 hours
                h, m = 0, 0

                # Extract hours difference
                converter = NumberService()
                try:
                    diff = converter.parse(time.group(4))
                except:
                    return None

                if time.group(5) == 'hours':
                    h += diff
                else:
                    m += diff

                # Extract minutes difference
                if time.group(6):
                    converter = NumberService()
                    try:
                        diff = converter.parse(time.group(7))
                    except:
                        return None

                    if time.group(8) == 'hours':
                        h += diff
                    else:
                        m += diff

                relative = True
            elif time.group(9) and time.group(10):
                # match hour only time, e.g. 4 pm
                h = int(time.group(9))
                m = 0

                if time.group(10) == 'pm':
                    h += 12

            elif time.group(11) and time.group(12):
                # match phrases like "at 3?"
                h = int(time.group(12))
                m = 0

            else:
                # Convert from "HH:MM pm" format
                t = time.group(2)
                h, m = int(t.split(':')[0]), int(t.split(':')[1])

                try:
                    if time.group(3) == 'pm':
                        h = (h % 12) + 12
                except IndexError:
                    pass

            if relative:
                return self.now + datetime.timedelta(hours=h, minutes=m)
            else:
                return datetime.datetime(
                    self.now.year, self.now.month, self.now.day, h, m
                )