def version_2(test): (given, expected) = test original_stack = Stack() sorted_stack = Stack() for g in given: original_stack.push(g) # starts here num_eltos = original_stack.size for i in range(num_eltos): pivot = original_stack.pop() num_swaps = 0 while (not sorted_stack.is_empty()) and (pivot < sorted_stack.peek()): original_stack.push(sorted_stack.pop()) num_swaps += 1 sorted_stack.push(pivot) for _ in range(num_swaps): sorted_stack.push(original_stack.pop()) # sorts in reverse order (smallest on top) while not sorted_stack.is_empty(): original_stack.push(sorted_stack.pop()) given_str = ''.join(original_stack.to_array()) # doesn't count in the O(.) calculation return given_str == expected
class MyQueue: def __init__(self): self.front = Stack() self.end = Stack() def size(self): return self.front.size() + self.end.size() def enqueue(self, val): self.end.push(val) def dequeue(self): if self.front.is_empty() and not self.move(): raise Exception("queue is empty") return self.front.pop() def peek(self): if self.front.is_empty() and not self.move(): raise Exception("queue is empty") return self.front.peek() # time: O(n), however, the average is O(1) def move(self): moved = False while not self.end.is_empty(): moved = True self.front.push(self.end.pop()) return moved def print_q(self): print self.front print self.end
def dft(self, starting_vertex: T) -> None: """ Print each vertex in depth-first order beginning from starting_vertex. """ # keep track of visited vertices visited = set() # create a stack class stack = Stack() # push the starting vertex onto the stack stack.push(starting_vertex) # while stack is not empty while stack.size(): # pop from the stack current_vertex = stack.pop() # if current vertex has not been visited if current_vertex not in visited: # add it to visited visited.add(current_vertex) # print the current vertex print(current_vertex) # for every neighbors of current_vertex for vertex in self.vertices[current_vertex]: # push it onto the stack stack.push(vertex)
def dfs(self, starting_vertex, destination_vertex): """ Return a list containing a path from starting_vertex to destination_vertex in depth-first order. """ # make a stack stack = Stack() # make a visited set visited = set() # push the PATH to that node stack.push([starting_vertex]) # while the stack isn't empty while stack.size(): # pop the PATH path = stack.pop() # the last thing in the path is our current item node = path[-1] # if node is not visited: if node not in visited: # CHECK if it is the target if node == destination_vertex: return path visited.add(node) for neighbor in self.vertices[node]: #copy the path PATH_COPY = path.copy() # add neighbor to the path PATH_COPY.append(neighbor) # enqueue the PATH_COPY stack.push(PATH_COPY) return None
def depth_first(self, xy1, xy2): """Execute a depth first search.""" tile_col1, tile_row1 = self.the_map.xy_to_cr(xy1[0], xy1[1]) tile_col2, tile_row2 = self.the_map.xy_to_cr(xy2[0], xy2[1]) successor_to_parent_map = {} start_state = (tile_col1, tile_row1) successor_to_parent_map[( start_state, None)] = None # (Successor, Action) -> (Parent, Action) open_list = Stack() open_list.push((start_state, None)) closed = [] while not open_list.isEmpty(): current_state, action_to_current_state = open_list.pop() if current_state == (tile_col2, tile_row2): return self.__get_action_path( (current_state, action_to_current_state), successor_to_parent_map) if current_state not in closed: for successor_state, action, step_cost in self.__get_successors( current_state): open_list.push((successor_state, action)) if successor_state not in closed: successor_to_parent_map[(successor_state, action)] = ( current_state, action_to_current_state) closed.append(current_state) return []
def path_to(self, v): if not self.has_path_to(v): return None edges = Stack() e = self.edgeTo[v] while e is not None: edges.push(e) e = self.edgeTo[e.From()] return edges
def traverse(world, traversal_path): # iterating through all rooms as unknown def is_unknown(graph): for k in graph: if '?' in graph[k].values(): return True return False def find_new_move(visited, current_room): curr_room = current_room.id room_exits = visited[curr_room] for direction in room_exits: if room_exits[ direction] == '?' and current_room.get_room_in_direction( direction).id not in visited: return direction return None def find_new_room(traversal_path, visited, curr_room, stack, reverse): while True: next_move = stack.pop() traversal_path.append(next_move) next_room = curr_room.get_room_in_direction(next_move) if '?' in visited[next_room.id].values(): return next_room.id curr_room = next_room stack = Stack() curr = 0 visited = {0: {}} curr_room = world.rooms[curr] reverse = {'n': 's', 'e': 'w', 's': 'n', 'w': 'e'} for direction in curr_room.get_exits(): visited[curr_room.id][direction] = '?' while len(visited) < len(world.rooms) and is_unknown(visited): curr_room = world.rooms[curr] if curr_room not in visited: visited[curr_room.id] = {} for direction in curr_room.get_exits(): visited[curr_room.id][direction] = '?' next_move = find_new_move(visited, curr_room) if not next_move: curr = find_new_room(traversal_path, visited, curr_room, stack, reverse) else: traversal_path.append(next_move) next_room = curr_room.get_room_in_direction(next_move) visited[curr][next_move] = next_room.id if next_room.id not in visited: visited[next_room.id] = {} for direction in next_room.get_exits(): visited[next_room.id][direction] = '?' visited[next_room.id][reverse[next_move]] = curr_room.id stack.push(reverse[next_move]) curr = next_room.id
def trace_cycle(self, v, w): stack = Stack() x = v while x != w: stack.push(x) x = self.edge_to[x] stack.push(w) stack.push(v) return stack
def earliest_ancestor(ancestors, starting_node, visited=None, path=None): # initialize path = [starting_node] # path = [starting_node] # get parents - only care about parent not starting node i.e: node[1] # loop to check for number of connections # if no connections return -1 print('ancestors:', ancestors) print('starting_node:', starting_node) graph = Graph() stack = Stack() path = [starting_node] stack.push(path) graph = {} for key, value in ancestors: # print('k,v:',key, value) if value not in graph: # print('aa',value) graph[value] = set() if key not in graph: print('aa', value) graph[key] = set() graph[value].add(key) print('graph:', graph) if len(graph[starting_node]) == 0: return -1 visited = set() paths = list() print('paths:', paths) while stack.size() > 0: current_path = stack.pop() print('current_path:', current_path) current_node = current_path[-1] print('current_node:', current_node) if current_node not in visited: visited.add(current_node) print('visited', visited) for parent in graph[current_node]: if parent not in visited: new_path = list(current_path) new_path.append(parent) print('new_path:', new_path) stack.push(new_path) if len(graph[current_node]) == 0: paths.append(current_path) print('paths:', paths) sorted_paths = sorted(paths, reverse=True) # key=lambda x: len(x)) print('*****', sorted_paths[-1][-1]) return sorted_paths[-1][-1]
def path_to(self, v): if not self.has_path_to(v): return [] path = Stack() x = v while x != self.s: path.push(x) x = self.edge_to[x] path.push(self.s) return path
def dfs_recursive(self, starting_vertex: T, destination_vertex: T) -> PathType: """ Return a list containing a path from starting_vertex to destination_vertex in depth-first order. This should be done using recursion. """ # would hold the found path to destination_vertex correct_path = [] # holds the visited vertices visited = set() # initialize the stack class stack = Stack() # push the starting_vertex as a list stack.push([starting_vertex]) # the inner recursive function def inner_dfs_recursive(starting_vertex, destination_vertex): # pops off a path from the stack path = stack.pop() # picks the last vertex from the path current_vert = path[-1] # base case of current_vert is the destination_vertex if current_vert == destination_vertex: # assess the nonlocal correct_path nonlocal correct_path # point correct_path to the path correct_path = path # return from the recursive function return # for neighbors of current_vert for vertex in self.vertices[current_vert]: # if vertex has not been visited if vertex not in visited: # add it to visited visited visited.add(vertex) # create a copy of path new_path = list(path) # append the vert to the new path new_path.append(vertex) # push the new path onto the stack stack.push(new_path) # recursively call inner_dfs_recursive with vertex as the starting_vertex inner_dfs_recursive(vertex, destination_vertex) # call the recursive function inner_dfs_recursive(starting_vertex, destination_vertex) # return the path return correct_path
def playing(player): traversal_path = [] visited_dict = {} visited_set = set() path = Stack() oposite_directions = {"s": "n", "n": "s", "e": "w", "w": "e"} while len(visited_set) < len(room_graph): current = player.current_room visited_set.add(current) # path.push(current.id) # traversal_path.append(current) # if current.id not in visited_set: # print(current.id) # visited_set.add(current.id) visited_dict[current.id] = {} # if len(current.get_exits()) == 1: # direction = current.get_exits() # path.pop() # previous_room = path.stack[-1] # visited_dict[current.id][direction] = previous_room # player.travel(previous_room) unvisited = Queue() for direction in current.get_exits(): if current.get_room_in_direction(direction) not in visited_set: # visited_dict[current.id][direction] = False # unvisited.enqueue(direction) unvisited.enqueue(direction) if unvisited.size() > 0: # direction = unvisited.dequeue() direction = unvisited.dequeue() path.push(direction) traversal_path.append(direction) player.travel(direction) else: # for direction in visited_dict[current.id]: # if visited_dict[current.id][direction] == False: # visited_dict[current.id][direction] = player.current_room.get_room_in_direction(direction) # player.travel(direction) previous_room = path.pop() traversal_path.append(oposite_directions[previous_room]) player.travel(oposite_directions[previous_room]) return traversal_path
def evaluate(self, vars): stack = Stack() queue = Queue() for elem in self._rpn: factory = OperatorFactory() operator = factory.newOperator(elem, stack, vars) if self.verbose == True: print elem, operator.evaluate() stack.push(operator.evaluate()) if self.verbose == True: print stack.s() return stack.popAll()
def evaluate(self, vars): stack = Stack() queue = Queue() for elem in self._rpn: factory = OperatorFactory() operator = factory.newOperator(elem, stack, vars) if self.verbose == True: print elem, operator.evaluate() stack.push(operator.evaluate()) if self.verbose == True: print stack.s() return stack.popAll()
def sort_stack(stack): s1 = stack s2 = Stack(s1.size) while(s1.is_empty() != True): temp = s1.pop() while(s2.is_empty() != True and s2.peek() > temp): s1.push(s2.pop()) s2.push(temp) return s2
def sort_stack(stack): buf = Stack() while not stack.is_empty(): cur = stack.pop() cnt = 0 while not buf.is_empty() and cur < buf.peek(): stack.push(buf.pop()) cnt += 1 buf.push(cur) for i in xrange(cnt): buf.push(stack.pop()) while not buf.is_empty(): stack.push(buf.pop())
def push(self, value): if self.cur_stack_index < 0: self.stacks.append(Stack()) self.cur_stack_index = 0 cur_stack = self.stacks[self.cur_stack_index] if cur_stack.size == self.threshold: cur_stack = Stack() self.stacks.append(cur_stack) self.cur_stack_index += 1 cur_stack.push(value)
class MyQueue: def __init__(self): self.s1 = Stack() self.s2 = Stack() def enqueue(self, item): self.s1.push(item) def dequeue(self): if self.s2.top is None: while self.s1.top is not None: self.s2.push(self.s1.pop()) return self.s2.pop()
def version_1(test): forward_stack = Stack() backward_stack = Stack() for t in test: forward_stack.push(t) while not forward_stack.is_empty(): backward_stack.push(forward_stack.pop()) result = ''.join(backward_stack.to_array()) return test == result
def randomSteps(env, steps, dqn): t0 = time.time() env.reset() i = 0 frame_stack = Stack(4) initial_no_op = np.random.randint(4, NO_OP_MAX) for _ in range(0, steps): if i < initial_no_op: # WE PERFORM A RANDOM NUMBER OF NO_OP ACTIONS action = NO_OP_CODE state, reward, done, info = env.step(action) greyObservation = rgb2gray(state) state = downSample(greyObservation) frame_stack.push(state) i += 1 else: state = np.stack(frame_stack.items, axis=2).reshape( (IMAGE_SIZE, IMAGE_SIZE, NUM_CHANNELS)) action = np.random.randint(0, len(ACTIONS)) actionH = np.zeros(len(ACTIONS)) actionH[action] = 1 next_state, reward, game_over, info = env.step(action) greyObservation = rgb2gray(next_state) next_state = downSample(greyObservation) frame_stack.push(next_state) next_state = np.stack(frame_stack.items, axis=2).reshape( (IMAGE_SIZE, IMAGE_SIZE, NUM_CHANNELS)) dqn.storeExperience(state, actionH, reward, next_state, game_over) if done: #print("Episode finished after {} timesteps".format(_ + 1)) env.reset() i = 0 frame_stack = [] t1 = time.time() print( "Fullfilling replay memory operation took:", t1 - t0, ) randomSteps()
class QueueViaStacks(): def __init__(self): self.in_stack = Stack(5) self.out_stack = Stack(5) def enqueue(self, item): self.in_stack.push(item) def dequeue(self): if self.out_stack.size == 0: while self.in_stack.size: self.out_stack.push(self.in_stack.pop()) if self.out_stack.is_empty is True: raise IndexError("Can't dequeue from empty queue") return self.out_stack.pop()
def get_convex_hull_by_graham_scan(angle_sorted_list): temp_stack = Stack() temp_stack.push(angle_sorted_list[0]) temp_stack.push(angle_sorted_list[1]) for p in angle_sorted_list[2:] + angle_sorted_list[:1]: while True: top = temp_stack.peek() second_top = temp_stack.peek_peek() b = (p[0] - top[0], p[1] - top[1]) a = (top[0] - second_top[0], top[1] - second_top[1]) if a[0] * b[1] - a[1] * b[0] < 0: temp_stack.pop() else: break temp_stack.push(p) temp_stack.pop() return temp_stack.items
class DepthFirstOrder: def __init__(self, G): self.marked = [False for _ in range(G.V)] self.pre = Queue() # push v to queue before recursion self.post = Queue() # ... after recursion self.reverse_post = Stack() # push v to stack after recursion for w in range(G.V): if not self.marked[w]: self.dfs(G, w) def dfs(self, G, v): self.pre.enqueue(v) self.marked[v] = True for w in G.adj[v]: if not self.marked[w]: self.dfs(G, w) self.post.enqueue(v) self.reverse_post.push(v)
def dft(self, starting_vertex): """ Print each vertex in depth-first order beginning from starting_vertex. """ # make a stack s = Stack() # push on your starting node s.push([starting_vertex]) # make a set to track if it was visited visited = set() # while stack not empty while s.size() > 0: # pop off what is on top. current_node = s.pop() # if we have no visited the vertex before if current_node not in visited: # run function/print # print(current_node) # mark as visited # visited.add(current_node) # get its neighbors # neighbors = self.get_neighbors(current_node) # for each of the neighbors self.vertices[room.id] = {} for neighbor in room.get_exits(): self.vertices[room.id][room.get_room_in_direction( possible_direction).id] = neighbor visited.add(room) exits = room.get_exits() while len(exits) > 0: # select first neighbors on list direct = exits[0] # beej: create neighbor object path = list(current_node) # add possibles directions to move path.append(room.get_room_in_direction(direct)) # add to stack s.push(path) # remove to contine exits.remove(direct) return self.vertices
class StackWithMin2(Stack): def __init__(self): super(StackWithMin2, self).__init__() self.stack = Stack() def pop(self): item = super(StackWithMin2, self).pop() if item == self.min(): self.stack.pop() return item def push(self, item): if item <= self.min(): self.stack.push(item) super(StackWithMin2, self).push(item) def min(self): if self.stack.top is not None: return self.stack.top.val else: return 1e10
def parse_object(tokens): s = Stack() tokens_count = len(tokens) n = 0 while n < tokens_count: elem = tokens[n] n += 1 if elem == ']': l = [] while s.top() != '[': top = s.pop() l.insert(0, top) s.pop() s.push(l) continue if elem == '}': l = [] while s.top() != '{': top = s.pop() l.insert(0, top) s.pop() if len(l) > 0 and not len(l) % 3 == 0 and not l.count(':') == len(l) / 3: raise ValueError d = {l[i]: l[i + 2] for i in range(0, len(l), 3)} s.push(d) continue s.push(elem) return s.top()
def evaluate(express): ops = Stack() vals = Stack() for s in express.split(): if s in "+,-,*,/,sqrt".split(','): ops.push(s) elif s == '(': pass elif s == ')': op = ops.pop() v = vals.pop() if op == '+': v += vals.pop() elif op == '-': v -= vals.pop() elif op == '*': v *= vals.pop() elif op == '/': v /= vals.pop() elif op == 'sqrt': v = v**0.5 vals.push(v) else: vals.push(float(s)) return vals.pop()
def dfs(self, starting_vertex: T, destination_vertex: T) -> PathType: """ Return a list containing a path from starting_vertex to destination_vertex in depth-first order. """ # create the stack class stack = Stack() # would keep track of visited vertices visited = set() # push the starting vertex as a list of vert stack.push([starting_vertex]) # while stack is not empty while stack.size(): # pop a path from the stack path = stack.pop() # get the last vertex from the stack current_vert = path[-1] # if current_vert is the destination_vertex if current_vert == destination_vertex: # return path return path # if current_vert is not in visited: if current_vert not in visited: # add it to visited visited.add(current_vert) # for every neighbors of of current_vert for vertex in self.vertices[current_vert]: # create a copy of the path new_path = list(path) # append the current vertex new_path.append(vertex) # push the new path onto the stack stack.push(new_path)
def depth_limited(problem, limit): """Depth Limited Search""" frontier = Stack() start_node = Node(problem['start']) frontier.push(start_node) closed_set = set() while not frontier.isEmpty(): node = frontier.pop() closed_set.add(node.value) if goal_test(problem, node): path = node.get_path() cost = cal_path_cost(problem['graph'], path) return path, cost, frontier.count if node.depth == limit: pass else: # Expansion adj = problem['graph'].adj(node.value) for child_value in quicksort(adj): if push_or_not(problem, node, child_value, closed_set): child_node = Node(child_value, node) frontier.push(child_node) return None
def dft(self, starting_vertex): """ Print each vertex in depth-first order beginning from starting_vertex. """ # make a stack stack = Stack() # make a visited set visited = set() # put starting vertex in the stack stack.push(starting_vertex) # while the stack isn't empty while stack.size(): # Pop off the top of the stack, it is current item node = stack.pop() # if node isn't visited if node not in visited: print(node) # mark as visited visited.add(node) # for each of our current item's edges for edge in self.vertices[node]: stack.push(edge)
def dft(starting_position): """ Print each vertex in depth-first order beginning from starting_vertex. """ # Create a queue/stack as appropriate stack = Stack() # Put the starting point in that stack.push(starting_position.current_room) # Make a set to keep track of where we've been visited = {} # While there is stuff in the queue/stack while stack.size() > 0: # Pop the first item position = stack.pop() # If not visited if position.id not in visited: # DO THE THING! exits = position.get_exits() visited[position.id] = {'n': '?', 's': '?', 'w': '?', 'e': '?'} for exit in exits: for idx, val in visited[position.id].items(): if idx == exit: if idx == 'n': visited[position.id][idx] = position.n_to.id if idx == 's': visited[position.id][idx] = position.s_to.id if idx == 'e': visited[position.id][idx] = position.e_to.id if idx == 'w': visited[position.id][idx] = position.w_to.id for next_position in world.rooms: stack.push(world.rooms[next_position]) return visited
class Program: def __init__(self): self.focus = Stack() self.running = False self.win = None self.s = None self.tabs = None self.bomb = None def init_state(self): self.modules = [None, None, None, None, None, None, None, None] self.tabs = Tabs(5, 0, *["Empty"] * 8) self.focus = Stack() self.slot = -1 bomb = self.bomb = Bomb(self) bomb.notify_on_finish(self.bomb_info_finished) self.update_bomb_info(bomb) chooser = ModuleChooser(self) self.focus.push(chooser) self.focus.push(bomb) def run(self, screen): if self.running: return self.running = True self.screen = screen curses.noecho() curses.curs_set(0) curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK) curses.init_pair(2, curses.COLOR_BLUE, curses.COLOR_BLACK) curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE) max_y, max_y = screen.getmaxyx() self.win = win = curses.newwin(50, max_y, 7, 0) win.keypad(1) self.init_state() self.add_decoration() self.tabs.update(screen) while True: logging.debug("Program: Updating current object {:}".format(self.focus.cur())) self.focus.cur().update(win) logging.debug("Program: Refreshing window") screen.refresh() win.refresh() logging.debug("Program: Waiting for event") ev = win.getch() if ev == curses.KEY_F12: return elif ev == curses.KEY_F10: if not type(self.focus.cur()) is Bomb: self.slot = -1 win.erase() self.focus.push(self.bomb) elif ev == curses.KEY_F11: self.init_state() elif curses.KEY_F1 <= ev <= curses.KEY_F8: curses.curs_set(0) self.slot = ev - curses.KEY_F1 logging.debug("Program: Selected module {}".format(self.slot)) if not type(self.focus.cur()) is ModuleChooser: self.focus.pop() if self.modules[self.slot]: logging.debug("Program: Current module active: {!s:}".format(self.focus.cur())) self.focus.push(self.modules[self.slot]) self.win.erase() else: self.focus.cur().event(ev, chr(ev)) self.tabs.set_active(self.slot) self.tabs.update(screen) if self.focus.cur() is None: win.addstr(10, 50, "No module active") def bomb_info_finished(self, bomb): logging.debug("Program: Bomb info finished") self.update_bomb_info(bomb) if self.slot == -1: self.slot = 0 self.focus.pop() def update_bomb_info(self, bomb): self.screen.move(1,0) self.screen.clrtoeol() self.screen.addstr("batteries: {!s: <9} parallel: {}".format(bomb.batteries, bomb.parallel)) self.screen.move(2,0) self.screen.clrtoeol() self.screen.addstr("serial: {!s: <9} vowels: {}".format(bomb.serial, bomb.vowels)) self.screen.move(3,0) self.screen.clrtoeol() self.screen.addstr("FRK: {!s: <9} CAR: {}".format(bomb.frk, bomb.car)) def set_module(self, module): self.modules[self.slot] = module self.tabs.set_tab(self.slot, module.title) self.focus.push(module) def add_decoration(self): self.screen.addstr(0,0, " Keep talking and Nobody Explodes - Manual helper", curses.A_REVERSE | curses.A_BOLD) y, x = self.screen.getyx() max_y, max_x = self.screen.getmaxyx() length = max_x - x self.screen.addstr(" " * length, curses.A_REVERSE | curses.A_BOLD) self.screen.addstr(6,0, "─" * max_x)
def convert(self, verbose): self.verbose = verbose operators = "^*+-\/" # operands = string.ascii_lowercase + string.digits output = Queue() stack = Stack() for token in self.infix: operands = re.match("^[a-z]$|^\d+\.\d+$|^\d+$", token) operators = re.match("^[+-\/*^]$", token) # if token is a number or variable add it to putput if operands: output.push(token) if self.verbose == True: print "1 token = %s, output = %s" % (token, output.list[::-1]) # if the token is variable add it mapVariable dictionary if token in string.ascii_lowercase: self.mapVariables[token] = "" # if token is an operator elif operators: # while there is another operator on the stack while not stack.isEmpty(): # if operator is lef-associative and its precedence is less than or equal to that on stack, or operator has precedence less than that on stack (is not left-associative) if stack.lastOnStack() != "(" and ( ( self.precedence[token][0] <= self.precedence[stack.lastOnStack()][0] and self.precedence[token][1] == "L" ) or self.precedence[token][0] < self.precedence[stack.lastOnStack()][0] ): # push operator to output from stack output.push(stack.pop()) if self.verbose == True: print "2 token = %s, output = %s" % (token, output.list[::-1]) else: break # push operator to stack stack.push(token) if self.verbose == True: print "3 token = %s, stack = %s" % (token, stack.list[::-1]) # if token is left parenthesis push it to stack elif token == "(": stack.push(token) if self.verbose == True: print "4 token = %s, stack = %s" % (token, stack.list[::-1]) # if token is right parenthesis elif token == ")": # until token at the top of stack is not left parethesis while stack.lastOnStack() != "(": # push from stack to output output.push(stack.pop()) if self.verbose == True: print "5 token = %s, output = %s" % (token, output.list[::-1]) # and pop left parethesis from stack but not to output stack.pop() if self.verbose == True: print "Left on stack " + str(stack.list[::-1]) print "Output " + str(output.list) self._rpn = output.list[::-1] while len(stack.list) > 0: self._rpn.append(stack.pop()) if self.verbose == True: print "RPN value = " + str(self._rpn) return self._rpn
class DbSession(object): """Provides an API for users to make changes to an in-memory database with transactions. Attributes: database: An instance of an in-memory database. transaction_stack: A stack of active transactions. current_trans: The currently active transaction. Transactions are a set of keys which represent keys in the database that have been edited during the current transaction. """ def __init__(self): self.database = InMemoryDatabase() self.transaction_stack = Stack() self.current_trans = None self.reset_transaction_state() def reset_transaction_state(self): self.current_trans = set() if self.transaction_stack.is_empty() else self.transaction_stack.current() # Transaction stack should always have a 'base' transaction which can't be rolled back/commited self.transaction_stack = Stack(self.current_trans) def pop_transaction(self): self.transaction_stack.pop() self.current_trans = self.transaction_stack.current() def has_open_transaction(self): return self.transaction_stack.size() > 1 def begin(self): self.current_trans = set() self.transaction_stack.push(self.current_trans) def rollback(self): if not self.has_open_transaction(): print('NO TRANSACTION') else: map(self.database.remove, list(self.current_trans)) self.pop_transaction() def commit(self): if not self.has_open_transaction(): print('NO TRANSACTION') else: self.database.flatten() self.reset_transaction_state() def set_var(self, var, value): if var in self.current_trans: self.database.change(var, value) else: self.database.add(var, value) self.current_trans.add(var) def unset_var(self, var): self.set_var(var, None) def get_var(self, var): print(self.database.get(var) or 'NULL') def num_equal_to(self, value): print(self.database.num_equal_to(value)) def __repr__(self): return '{}\nTransaction Stack: {}'.format(self.database, self.transaction_stack)