Exemplo n.º 1
0
def run_stack_demo():
    print("\nRandomly generated stack")
    stack = Stack()
    for i in range(10):
        stack.push_random_number()

    popped = 1
    while popped:
        popped = stack.pop()
        print(f"Popped {popped}")
def valid_parenthesis(s: str) -> bool:
    """
    Returns whether the parenthetical expression, s, is valid.
    @Algorithm: - Keep track of open parens that require terminating using a stack
                - If we encounter an open paren, push to indicate we are still to find a terminating closed paren
                - If we encounter a closed paren,
                    - If open paren stack is empty, then we cannot match the closed paren to anything -- invalid
                    - Check if closed paren terminates the open paren at the top of the stack
                        - If it does, pop() the open paren to indicate we have found its termination
                        - If it doesn't, then -- invalid
    :param s: string with parentheses
    :Time: O(N)
    :Space: O(N)
    :return: true if valid
    """
    open_parens = Stack(
    )  # tracks history of open parentheses that need to be terminated
    for c in s:
        if c in closed_parens:  # if closed paren, check if top of stack is open paren of same type
            if open_parens.get_size() == 0:
                return False  # no open paren to match this closed paren

            if open_parens.peek() == matching_open_paren[
                    c]:  # proper termination found for open paren at top of stack
                open_parens.pop(
                )  # pop to indicate this paren has found a terminating closing paren
            else:
                return False  # incorrect termination
        else:
            open_parens.push(c)  # if open paren, add to stack

    return open_parens.is_empty(
    )  # if stack is empty, valid; else, indicates an open paren hasn't been terminated
Exemplo n.º 3
0
def depth_first_search(start, goals=[]):
    stack = Stack((start, start.previous))
    visited = {start.id: True}

    while len(stack) > 0:
        node, previous = stack.pop()

        if node.id in goals:
            return node

        for neighbor, cost in node.expand_neighbors():
            if neighbor.id not in visited:
                visited[neighbor.id] = True
                neighbor.previous = node
                stack.push((neighbor, node))

    return None
Exemplo n.º 4
0
class StackWithMin(Stack):
    def __init__(self):
        super(StackWithMin, self).__init__()
        self.s2 = Stack(
        )  # This stack stores the minimum element; the top of the stack contains the minimum

    def push(self, item):
        # This time, when pushing, we check to see if the item being pushed is less than (or equal) to our current min
        # If so, we add this item to the top of our second stack
        if item <= self.get_min():
            self.s2.push(item)
        super().push(item)

    def pop(self):
        ret_val = super().pop()
        # This time, when popping, if the item we are popping is the minimum, reflect this in our second stack, s2
        if ret_val == self.get_min():
            self.s2.pop()
        return ret_val

    def get_min(self):
        """
        Returns the minimum element in the original stack, which is stored at the top of s2.
        :Time: O(1)
        :Space: O(1)
        :return: the minimum element in the stack
        """
        if self.s2.is_empty():
            return float('+inf')
        else:
            return self.s2.peek()
Exemplo n.º 5
0
def is_palindrome(head: ListNode) -> bool:
    """
    Returns whether the linked list is a palindrome.
    Algorithm: Add each node into a stack
               Then, for each node pop() and check if that node equals the popped node; if not, return False
               since a palindrome must read the same backwards and forwards
    :param head: head of list
    :Time: O(N)
    :Space: O(N)
    :return: true if palindrome
    """
    S = Stack()
    curr = head
    while curr is not None:
        S.push(curr)  # add each node onto a stack
        curr = curr.next
    curr = head
    while curr is not None:
        if curr.key != S.pop(
        ).key:  # check if the current node is the same as the node at the top of the stack
            return False  # if not, then LL is not a palindrome
        curr = curr.next
    return True
Exemplo n.º 6
0
def sort_stack(s1):
    ''' sorts a stack with smallest elements on top '''

    if s1.is_empty():
        return False

    s2 = Stack()
    s2.push(s1.pop())

    while not s1.is_empty():
        compare(s1, s2)

    while not s2.is_empty():
        s1.push(s2.pop())
Exemplo n.º 7
0
def clone_reverse(head: ListNode) -> ListNode:
    """
    Reverses the original list by creating a new one with the help of a stack
    :param head: original list head
    :Time: O(N)
    :Space: O(N)
    :return: new list head
    """
    S = Stack()
    curr = head
    while curr is not None:
        S.push(curr)  # add each node onto a stack
        curr = curr.next
    new_list = ListNode(S.pop().key)
    new_list_head = new_list
    while not S.is_empty():
        new_list.next = ListNode(S.pop().key)
        new_list = new_list.next
    return new_list_head
Exemplo n.º 8
0
"""Exercise 10.1-1."""
# Using Figure 10.1 as a model, illustrate the result of each operation in the
# sequence PUSH(S,4), PUSH(S,1), PUSH(S,3), POP(S), PUSH(S,8), and POP(S) on
# an initially empty stack S stored in array S[1...6].
from data_structures.Stack import Stack

if __name__ == "__main__":
    S = Stack()
    print(S.items)

    S.push(4)
    print(S.items)

    S.push(1)
    print(S.items)

    S.push(3)
    print(S.items)

    S.pop()
    print(S.items)

    S.push(8)
    print(S.items)

    S.pop()
    print(S.items)
 def __init__(self):
     super(MyQueue, self).__init__()
     self.s1 = Stack()
     self.s2 = Stack()
Exemplo n.º 10
0
class MyQueue(Queue):
    def __init__(self):
        super(MyQueue, self).__init__()
        self.s1 = Stack()
        self.s2 = Stack()

    def enqueue(self, item):
        """
        Enqueues an item onto the queue by pushing the item onto stack 1.
        :param item: item to enqueue
        :Time: O(1)
        :Space: O(1)
        :return: none
        """
        self.s1.push(item)  # Simply push item onto s1

    def dequeue(self):
        """
        Returns the element at the front of the queue. This is achieved by popping from s2, which mimics a queue.
        @note: To save needlessly shifting elements into s2, we will only populate s2 when it is depleted.
                I.e. only update s2 until the previously populated items have been popped.
        :Time: O(N)
        :Space: O(N)
        :return: none
        """
        if self.s2.is_empty(
        ):  # We will only update s2 when it cannot be popped() from further
            self.shift_stacks()
        return self.s2.pop()

    def peek(self):
        if self.s2.is_empty():
            self.shift_stacks()
        return self.s2.peek()

    def shift_stacks(self):
        """
        Pops each element in s1 and pushes it onto s2 such that s2 now mimics a queue which can be dequeued via popping
        :Time: O(N)
        :Space: O(N)
        :return: none
        """
        while not self.s1.is_empty():  # pop() from s1 and push() onto s2
            self.s2.push(self.s1.pop())

    def get_size(self):
        return self.s1.get_size() + self.s2.get_size(
        )  # Size of queue is the size of both stacks

    def is_empty(self):
        return self.get_size() == 0
Exemplo n.º 11
0
 def approach_2(self, l1: ListNode, l2: ListNode) -> ListNode:
     """
     Adds the two lists in forward order and returns the head of the resulting list.
     Algorithm: Insert both lists, l1 and l2, into separate stacks, S1 and S2.
                 - Then, as from the original alg, pop off S1 and S2 concurrently and add into a new list l3
                 - If either S1 or S2 has remaining items, accumulate into l3
                 - If carry = 1, as before, we add append the carry onto the end as well.
     TODO: *Note that l3 is in reverse order which we do not want. E.g. 7 + 999 = 6001. Fix this by appending to start of l3.
             todo: hack used by reversing l3 at the end -- implement an "insertAtBeginning()" method for l3 to fix!!
     :param l1: list 1
     :param l2: list 2
     :Time: O(n + m)
     :Space: O(n + m)
     :return: head of resulting list
     """
     # Push each list onto a separate stack
     S1 = Stack()
     S2 = Stack()
     while l1:
         S1.push(l1.key)
         l1 = l1.next
     while l2:
         S2.push(l2.key)
         l2 = l2.next
     # What follows is similar to the original approach
     l3_h = l3 = ListNode(-1)
     carry = 0
     while not S1.is_empty() and not S2.is_empty(
     ):  # add elements while both stacks are not empty
         num = S1.pop() + S2.pop() + carry
         l3.next = ListNode(num % 10)  # add last digit of sum
         if num > 9:
             carry = 1
         else:
             carry = 0
         l3 = l3.next
     while not S1.is_empty():  # add remaining elements in S1
         num = S1.pop() + carry
         l3.next = ListNode(num % 10)  # add last digit of sum
         if num > 9:
             carry = 1
         else:
             carry = 0
         l3 = l3.next
     while not S2.is_empty():  # add remaining elements in S2
         num = S2.pop() + carry
         l3.next = ListNode(num % 10)  # add last digit of sum
         if num > 9:
             carry = 1
         else:
             carry = 0
         l3 = l3.next
     # important: if carry is set to 1, then it means the sum is overflowing and must include the carry bit
     if carry == 1:
         l3.next = ListNode(carry)
     return reverse_list(
         l3_h.next
     )  # todo this is a hack!! when appending sums, append to l3 at the beginning!!!
Exemplo n.º 12
0
 def __init__(self, threshold):
     self.threshold = threshold
     self.data = {1: Stack()}
     self.cur = 1  #current stack
Exemplo n.º 13
0
 def __init__(self):
     ''' add: push everything to s1 first '''
     ''' remove: push everything to self.s2 first '''
     self.s1 = Stack()
     self.s2 = Stack()
Exemplo n.º 14
0
class My_Queue:
    ''' implementation of a queue using 2 stacks '''
    def __init__(self):
        ''' add: push everything to s1 first '''
        ''' remove: push everything to self.s2 first '''
        self.s1 = Stack()
        self.s2 = Stack()

    def __str__(self):
        return "s1:\n" + str(self.s1) + "\ns2:\n" + str(self.s2)

    def add(self, value):
        while not self.s2.is_empty():
            self.s1.push(self.s2.pop())
        self.s1.push(value)

    def remove(self):
        while not self.s1.is_empty():
            self.s2.push(self.s1.pop())
        self.s2.pop()

    def is_empty(self):
        return self.s1.data == [] and self.s2.data == []

    def size(self):
        return len(self.s1.data) + len(self.s2.data)
Exemplo n.º 15
0
def runStack():
    s=Stack()

    print(s.isEmpty())
    s.push(4)
    s.push('dog')
    print(s.peek())
    s.push(True)
    print(s.size())
    print(s.isEmpty())
    s.push(8.4)
    print(s.pop())
    print(s.pop())
    print(s.size())
Exemplo n.º 16
0
def runStack():
    s = Stack()

    print(s.isEmpty())
    s.push(4)
    s.push('dog')
    print(s.peek())
    s.push(True)
    print(s.size())
    print(s.isEmpty())
    s.push(8.4)
    print(s.pop())
    print(s.pop())
    print(s.size())
Exemplo n.º 17
0
 def __init__(self):
     super(StackWithMin, self).__init__()
     self.s2 = Stack(
     )  # This stack stores the minimum element; the top of the stack contains the minimum
Exemplo n.º 18
0
        return False

    s2 = Stack()
    s2.push(s1.pop())

    while not s1.is_empty():
        compare(s1, s2)

    while not s2.is_empty():
        s1.push(s2.pop())


if __name__ == "__main__":
    print "-------Test 1----------"
    print "unsorted stack test"
    s = Stack()
    s.push(4)
    s.push(1)
    s.push(1)
    s.push(2)
    s.push(3)
    s.push(5)
    s.push(1)
    print "INITIAL:"
    print s
    sort_stack(s)
    print "FINAL:"
    print s

    print "-------Test 2----------"
    print "already sorted stack test"
Exemplo n.º 19
0
def evaluate_expression(expr):
    values = Stack()
    operators = Stack()

    for idx, element in enumerate(expr):
        if element == '(': pass
        elif element in ['^', '+', '-', '*', '/']:
            operators.push(element)
        elif element.isdigit():
            values.push(int(element))
        elif element == ')':
            if operators.get_size() == 0: continue
            operand = operators.pop()
            values = calculate(operand, values)
        else:
            raise InvalidInputError(idx=idx, element=element)

    while operators.get_size() != 0:
        operand = operators.pop()
        values = calculate(operand, values)

    assert values.get_size(
    ) == 1, "Values stack contains {} elements at termination".format(
        values.get_size())
    return float(values.pop())
Exemplo n.º 20
0
 def push(self, item):
     if self.is_full(self.data[self.cur]):
         self.cur += 1
         if self.cur not in self.data:
             self.data[self.cur] = Stack()
     self.data[self.cur].push(item)