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
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
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)
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()
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
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
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
def convert(n): if n in self.__constants__: return self.__constants__[n] converter = NumberService() return converter.parse(n)
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)
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")
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")
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 )
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 )