def output_queue_generator(self, input_list): """ Uses the shunting yard algorithm to tak a standard list of calculations and turn it intro a list of RPN, to be calculated :param input_list: a list of numbers, parentheses, operators and functions as its elements """ self.output_queue = Queue() operator_stack = Stack() for elem in input_list: if isinstance(elem, numbers.Number): self.output_queue.push(elem) elif isinstance(elem, Function): operator_stack.push(elem) elif elem == '(': operator_stack.push(elem) elif elem == ')': stack_elem = operator_stack.pop() while stack_elem != '(': self.output_queue.push(stack_elem) stack_elem = operator_stack.pop() elif isinstance(elem, Operator): if not operator_stack.is_empty(): top = operator_stack.peek() while (top is not None) and self.precedence_calculator(top, elem): self.output_queue.push(operator_stack.pop()) if not operator_stack.is_empty(): top = operator_stack.peek() else: top = None operator_stack.push(elem) while not operator_stack.is_empty(): item = operator_stack.pop() self.output_queue.push(item)
def __init__(self, debug=False): self.functions = { 'EXP': Function(np.exp), 'LOG': Function(np.log), 'SIN': Function(np.sin), 'COS': Function(np.cos), 'SQRT': Function(np.sqrt), 'ABS': Function(np.abs) } self.constants = {'PI': math.pi, 'TAU': math.tau, 'E': math.e} self.operators = { '+': Operator(np.add, strength=0), '~': Operator(np.subtract, strength=0), '/': Operator(np.divide, strength=1), '*': Operator(np.multiply, strength=1), } self.output_queue = Queue() self.debug = debug
class Prim: """Lazy implementation of Prim algorithm""" def __init__(self, graph): self.pq = MinQueue() #priority queue of edges self.mst = Queue() #MST edges self.marked = [False] * len(graph) #MST vertices self.visit(graph, 0) #assuming graph is connected while self.pq: edge = self.pq.del_min() #repeatedly delete min edge from pq v = edge.either() w = edge.other(v) if self.marked[v] and self.marked[w]: continue #ignore if both endpoints on tree self.mst.enqueue(edge) if not self.marked[v]: self.visit(graph, v) #add v to tree if not self.marked[w]: self.visit(graph, w) #add w to tree def visit(self, graph, v): """put vertex on the tree and its incident edges on priority queue""" self.marked[v] = True #add vertex to tree for edge in graph.adj(v): if not self.marked[edge.other(v)]: self.pq.insert(edge) #add w to pq if not in tree
class Kruskal: """Kruskal's algorithm for minimum spanning tree""" mst = Queue() #mst -- a queue of edges def __init__(self, graph): """Kruskal's algorithm computes MST in time proportional to Elog(E)""" pq = MinQueue() for edge in graph.edges(): #build prioirty queue ~ O(E) pq.insert(edge) uf = UnionFind(len(graph)) while pq and len(mst) < len(graph) - 1: edge = pq.del_min() #delete-min ~ O(log(E)) v = edge.either() w = edge.other(v) if not uf.connectged(v, w): #connected ~ O(log*(V)) uf.union(v, w) #union ~ O(log*(V)) mst.enqueue(edge)
def has_augpath(self, graph, s, t): """Breadth-first search""" self.edge_to = [False] * len(graph) self.marked = [False] * len(graph) q = Queue() q.enqueue(s) self.marked[s] = True while q: v = q.dequeue() for edge in graph.adj(v): w = edge.other(v) if edge.residual_capacity_to(w) > 0 and not self.marked[w]: #found path from s to w in the residual network? self.edge_to[w] = edge #save last edge on path to w self.marked[w] = True #mark w q.enqueue(w) #add w to queue return self.marked[t] #is t reachable from s in residual network?
class Calculator: """ Takes a string input in correct format and returns an answer. Parsing included. """ def __init__(self): self.functions = { 'EXP': Function(numpy.exp), 'LOG': Function(numpy.log), 'SIN': Function(numpy.sin), 'COS': Function(numpy.cos), 'SQRT': Function(numpy.sqrt), 'ABS': Function(numpy.abs) } self.operators = { 'PLUSS': Operator(numpy.add, strength=0), 'MINUS': Operator(numpy.subtract, strength=0), 'DELE': Operator(numpy.divide, strength=1), 'GANGE': Operator(numpy.multiply, strength=1), } # Parse text to fills this queue with RPN, # the evaluate_output_queue evaluates it to find answer self.output_queue = Queue() def calculate(self): """The running of the calculator""" print("Welcome to 'COOLCULATOR'.\n" + "Exit by pressing 'ENTER' without providing input\n" + "All operators are written in norwegian!\n" + "(E.g. '+' is written 'pluss')") equation = " " while equation != "": equation = input(">>> ") try: self.output_queue_generator(self.parse_string_to_list(equation)) answer = self.evaluate_output_queue() print(">>>", answer) except IndexError: pass def evaluate_output_queue(self): """Evaluates the RPN in the queue""" stack = Stack() while not self.output_queue.is_empty(): elem = self.output_queue.pop() if isinstance(elem, numbers.Number): stack.push(elem) elif isinstance(elem, Function): _input = stack.pop() stack.push(elem.execute(_input)) elif isinstance(elem, Operator): _input_1 = stack.pop() _input_2 = stack.pop() stack.push(elem.execute(_input_2, _input_1)) return stack.pop() def output_queue_generator(self, input_list): """ Uses the shunting yard algorithm to tak a standard list of calculations and turn it intro a list of RPN, to be calculated :param input_list: a list of numbers, parentheses, operators and functions as its elements """ self.output_queue = Queue() operator_stack = Stack() for elem in input_list: if isinstance(elem, numbers.Number): self.output_queue.push(elem) elif isinstance(elem, Function): operator_stack.push(elem) elif elem == '(': operator_stack.push(elem) elif elem == ')': stack_elem = operator_stack.pop() while stack_elem != '(': self.output_queue.push(stack_elem) stack_elem = operator_stack.pop() elif isinstance(elem, Operator): if not operator_stack.is_empty(): top = operator_stack.peek() while (top is not None) and self.precedence_calculator(top, elem): self.output_queue.push(operator_stack.pop()) if not operator_stack.is_empty(): top = operator_stack.peek() else: top = None operator_stack.push(elem) while not operator_stack.is_empty(): item = operator_stack.pop() self.output_queue.push(item) def parse_string_to_list(self, input_string): """ Parses string to be used in 'output_queue_generator' :param input_string: a user-written string to be calculated; assumed correct format :return: a string of numbers, functions and operators in a 'normal' syntax """ # Make the string uppercase with no spaces, # ready for regex; re methods input_string = input_string.replace(" ", "").upper() regex_list = ( '|'.join( self.functions.keys()), '|'.join( self.operators.keys()), r'\(', r'\)', r'\d+\.\d+', # Positive float r'-\d+\.\d+', # Negative float r'\d+', # Positive integer r'-\d+') # Negative integer regex = '|'.join(regex_list) # re.findall returns a list containing all matches matches = re.findall(regex, input_string) result = [] for match in matches: # print(match) if match in self.functions.keys(): result.append(self.functions[match]) elif match in self.operators.keys(): result.append(self.operators[match]) elif match in ('(', ')'): result.append(match) else: # It's a number or trash try: result.append(float(match)) except ValueError: pass return result @staticmethod def precedence_calculator(top, elem): """ :param top: top element of stack, can be function, operator, number :param elem: is a operator with a strength :return: if top has precedence over elem """ if isinstance(top, (numbers.Number, Function)) or top in ('(', ')'): return False if isinstance(top, Operator): return top.strength > elem.strength
def __iter__(self): """Inorder traversal (depth-first traversal)""" self.queue = Queue() self._inorder(self.root, self.queue) return self
class BSTree: """Symbol Table API""" def __init__(self): """Initialize an empty symbol table (BST implementation)""" self.root = None def __iter__(self): """Inorder traversal (depth-first traversal)""" self.queue = Queue() self._inorder(self.root, self.queue) return self def __len__(self): """""" if self.root is None: return 0 else: return self._size(self.root) def __next__(self): """Return next element when looping through BST""" if len(self.queue) == 0: del self.queue raise StopIteration return self.queue.dequeue() def __repr__(self): """How to visualize a BST???""" pass def _inorder(self, node, queue): """Depth-first inorder traverse the tree""" if node is None: return self._inorder(node.left, queue) queue.enqueue(node.key) self._inorder(node.right, queue) def _size(self, node): """Return the size of subtree rooted at node""" if node is None: return 0 else: return node.count def contains(self, key): """Return True if key exists""" node = self.get(key) if node is None: return False else: return True def put(self, key, val): """Put a key-value pair into the symbol table""" self.root = self._put(self.root, key, val) def _put(self, node, key, val): """Depending on how the keys coming in, the BST will look different""" if node is None: return TreeNode(key, val) if key < node.key: node.left = self._put(node.left, key, val) elif key > node.key: node.right = self._put(node.right, key, val) else: node.val = val node.count = 1 + self._size(node.left) + self._size(node.right) return node def get(self, key): """Return value paird with key""" node = self.root while node is not None: if key < node.key: node = node.left elif key > node.key: node = node.right else: return node.val return None def delete(self, key): """Delete key-value pair from the table Hibbard deletion * no children, * one children, * two children, """ self.root = self._delete(self.root, key) def _delete(self, node, key): """Hibbard deletion workhorse function""" #fixme: need delete for left-leaning red-black tree if node is None: #no children return None if key < node.key: node.left = self._delete(node.left, key) elif key > node.key: node.right = self._delete(node.right, key) else: #one children if node.right is None: return node.left if node.left is None: return node.right #two children temp = node node = self.min(node.right) node.right = self.delmin(temp.right) node.left = temp.left node.count = self._size(node.left) + self._size(node.right) + 1 return node def isempty(self): """Return True if table is empty""" return len(self) == 0 def min(self): """Return the node with minimum key""" node = self.root while node.left is not None: node = node.left return node.key def max(self): """Return the node with maximum key""" node = self.root while node.right is not None: node = node.right return node.key def floor(self, key): """Return the largest key on BST that is less than or equal to (<=) the given key """ node = self._floor(self.root, key) if node is None: return None return node.key def _floor(self, node, key): """floor workhorse function""" if node is None: return None if key == node.key: return node if key < node.key: return self._floor(node.left, key) temp = self._floor(node.right, key) if temp is not None: return temp else: return node def ceiling(self, k): """Return the smallest key on BST that is larger than or equal to (>=) the given key """ node = self._ceiling(self.root, key) if node is None: return None return node.key def _ceiling(self, node, key): """ceiling workhorse function""" if node is None: return None if key == node.key: return node if key > node.key: return self._ceiling(node.right, key) temp = self._ceiling(node.left, key) if temp is not None: return temp else: return node def rank(self, key): """Return the number of keys less than (<) the given key""" return self._rank(self.root, key) def _rank(self, node, key): """""" if node is None: return 0 if key < node.key: return self._rank(node.left, key) elif key > node.key: return 1 + self._size(node.left) + self._rank(node.right, key) else: return self._size(node.left) def delmin(self): """Delete the node with minimum key""" self.root = self._delmin(self.root) def _delmin(self, node): """delmin workhorse function""" if node.left is None: return node.right node.left = self._delmin(node.left) node.count = 1 + self._size(node.left) + self._size(self.right) return node def delmax(self): """Delete the node with maximum key""" self.root = self._delmax(self.root) def _delmax(self, node): """delmax workhorse function""" if node.right is None: return node.left node.right = self._delmax(node.right) node.count = 1 + self._size(node.left) + self._size(self.right) return node
class Calculator(): ''' The calculator takes a string in the form of an equation, parses it into operators, operands, functions and parentheses. It then converts from infix to reverse polish notation and evaluates the expression. ''' def __init__(self, debug=False): self.functions = { 'EXP': Function(np.exp), 'LOG': Function(np.log), 'SIN': Function(np.sin), 'COS': Function(np.cos), 'SQRT': Function(np.sqrt), 'ABS': Function(np.abs) } self.constants = {'PI': math.pi, 'TAU': math.tau, 'E': math.e} self.operators = { '+': Operator(np.add, strength=0), '~': Operator(np.subtract, strength=0), '/': Operator(np.divide, strength=1), '*': Operator(np.multiply, strength=1), } self.output_queue = Queue() self.debug = debug def calculate(self): ''' Calculate the value of the RPN-equation stored in output_queue. ''' stack = Stack() while not self.output_queue.is_empty(): elem = self.output_queue.pop() if isinstance(elem, numbers.Number): stack.push(elem) if isinstance(elem, Function): _input = stack.pop() stack.push(elem.execute(_input)) if isinstance(elem, Operator): _second = stack.pop() _first = stack.pop() stack.push(elem.execute(_first, _second)) return stack.pop() def generate_output_queue(self, input_list): ''' Converts a list of operators, functions, operands, constants and parentheses from infix notation to reverse polish notation using the shunting-yard algorithm ''' def operator_precedence(top, elem): ''' Function to determine wether to pop from op_stack ''' precedence = False precedence |= isinstance(top, Function) if isinstance(top, Operator): precedence |= top.strength >= elem.strength precedence &= top != '(' return precedence self.output_queue = Queue() op_stack = Stack() for elem in input_list: if isinstance(elem, numbers.Number): self.output_queue.push(elem) if isinstance(elem, Function): op_stack.push(elem) if isinstance(elem, Operator): if not op_stack.is_empty(): top = op_stack.peek() while top is not None and operator_precedence(top, elem): self.output_queue.push(op_stack.pop()) if not op_stack.is_empty(): top = op_stack.peek() else: top = None op_stack.push(elem) if elem == '(': op_stack.push(elem) if elem == ')': next_op = op_stack.pop() while next_op != '(': self.output_queue.push(next_op) next_op = op_stack.pop() while not op_stack.is_empty(): elem = op_stack.pop() self.output_queue.push(elem) if self.debug: print(f'\nParsed string: {input_list}') print(f'Output queue: {self.output_queue._items}\n') def parse_string_to_list(self, input_str): ''' Parse input_str into a list of operators, operands, parentheses, constants and functions, using regular expressions. Then substitute the functions and operators found with their corresponding wrapper object. Strings in the form of positive or negative integers/floats are converted to float. ''' re_parts = ( r'-?\d+\.\d+', # Floating point numbers r'-?\d+', # Integers r'\(|\)', # Parentheses r'\+|\~|\*|/|', # Operators '|'.join(self.functions.keys()), # Functions '|'.join(self.constants.keys()), # Constants ) regex = '|'.join(re_parts) # re.findall preserves the order of the matches matches = re.findall(regex, input_str.upper()) result = [] for match in matches: # Function if match in self.functions.keys(): result += [self.functions[match]] # Operator elif match in self.operators.keys(): result += [self.operators[match]] # Constants elif match in self.constants.keys(): result += [self.constants[match]] # Parentheses elif match in ('(', ')'): result += [match] # Probably a number else: try: result += [float(match)] except ValueError: pass return result