コード例 #1
0
ファイル: expression.py プロジェクト: whenyd/dsa_python
def cal_simple_expression(exp):
    """只有+-*/四种运算, 运算数为整数, 运算符前后有空格."""
    end = '$'  # 表达式结束标志, 最低优先级
    priority = {end: 0, '+': 1, '-': 1, '*': 2, '/': 2}
    operator_func = {'+': add, '-': sub, '*': mul, '/': truediv}

    operand = ArrayStack()
    operator = ArrayStack()

    exp = exp.split()
    exp.append(end)  # 添加表达式结束标志以计算最终结果

    i = 0
    while i < len(exp):
        e = exp[i]
        if e not in priority.keys():
            operand.push(int(e))
            i += 1
        else:
            # 高优先级运算符直接push
            if operator.is_empty() or priority[e] > priority[operator.top()]:
                operator.push(e)
                i += 1

            # 低优先级运算符在下一次循环时处理
            else:
                func = operator_func[operator.pop()]
                num1 = operand.pop()
                num2 = operand.pop()
                operand.push(func(num2, num1))

    return operand.pop()
コード例 #2
0
def evaluate_expression(tokens):
    stack_number = ArrayStack()
    stack_operator = ArrayStack()
    stack_pa = ArrayStack()
    for token in tokens:
        if token.isdigit():
            stack_number.push(BinaryTree(token))
        else:
            if token in '({[':
                stack_pa.push(token)
            elif token in '+-*/':
                stack_operator.push(BinaryTree(token))

            else:
                if stack_operator.is_empty():
                    return
                stack_pa.pop()
                arg_2 = stack_number.pop()
                arg_1 = stack_number.pop()
                tree = stack_operator.pop()
                tree.left_node = arg_1
                tree.right_node = arg_2
                stack_number.push(tree)

    if stack_number.is_empty():
        return
    value = stack_number.pop()
    if not stack_number.is_empty():
        return
    if not stack_pa.is_empty():
        return
    if not stack_operator.is_empty():
        return
    return value
コード例 #3
0
def match_paranthesis(paranthesis):
    left = '{[(|'
    right = '}])|'
    stack = ArrayStack()
    for s in paranthesis:
        if s in left and s not in right:
            stack.push(s)
        if s in right:
            if s not in left:
                if stack.is_empty():
                    return False
                else:
                    if right.index(s) == left.index(stack.top()):
                        stack.pop()
                    else:
                        return False
            else:
                if stack.is_empty():
                    stack.push(s)
                else:
                    if s != stack.top():
                        stack.push(s)
                    else:
                        stack.pop()
    return stack.is_empty()
コード例 #4
0
ファイル: Project1.py プロジェクト: brandonbooth11/project1
def postFix(e):
    '''
    I've noticed that this sometimes doesnt work because somehow the '*' and '-' characters
    are technically different on some computers than others, so if it doesnt work, just
    replace the symbols in my 'if' statements with the versions on your keyboard and then
    try your examples
    '''
    
    #solves an expression in postfix notation

    #makes the array stack to store values from the expression until they are used
    s = ArrayStack()

    #checks each char in the expression to see if it is a digit. If it is, it puts it in the stack,
    #otherwise it performs the proper operation on the last 2 numbers in the stack
    for i in e:
        if i in ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]:
            s.push(int(i))
        elif i == "+":
            s.push(s.pop()+s.pop())
        elif i == "-":
            a = s.pop()
            b = s.pop()
            s.push(b-a)
        elif i == "*":
            s.push(s.pop()*s.pop())
        elif i == "/":
            a = s.pop()
            b = s.pop()
            s.push(b/a)

    #returns the end value
    return s.pop()
コード例 #5
0
def evalueate_expression(tokens):
    parentheses = {')': '(', '}': '{', ']': '['}
    stack = ArrayStack()
    for token in tokens:
        try:
            token = (int(token))
        except ValueError:
            pass

        if token not in parentheses:
            stack.push(token)
        else:
            try:
                arg_2 = stack.pop()
                operator = stack.pop()
                arg_1 = stack.pop()
                opening_group_symbol = stack.pop()
                if parentheses[token] != opening_group_symbol:
                    return
                stack.push({
                    '+': add,
                    '-': sub,
                    '*': mul,
                    '/': truediv
                }[operator](arg_1, arg_2))
            except EmptyStackError:
                return
    if stack.is_empty():
        return
    value = stack.pop()
    if not stack.is_empty():
        return
    return value
コード例 #6
0
def test_array_stack():
    array_stack = ArrayStack()

    # Assert that we start with an empty stack
    assert array_stack.is_empty()
    with pytest.raises(Empty):
        array_stack.top()

    # Push a bunch of elements onto the stack
    for i in range(10):
        array_stack.push(i)
        array_stack, top = array_stack.top()
        assert top == i
        assert len(array_stack) == i + 1

    # Pop all the elements off
    for i in range(len(array_stack) - 1, -1, -1):
        array_stack, val = array_stack.pop()
        assert val == i
        assert len(array_stack) == i

    # Assert we are back to an empty stack
    assert array_stack.is_empty()
    with pytest.raises(Empty):
        array_stack.pop()
コード例 #7
0
 def test_push_two_then_pop(self):
     stack = ArrayStack()
     stack.push(1)
     stack.push(2)
     res = stack.pop()
     self.assertEqual(res, 2)
     self.assertEqual(stack.list(), [1])
コード例 #8
0
def infix_to_postfix(expression):
    postfix = []
    priority = {'(': 1, '+': 2, '-': 2, '*': 3, '/': 3, '^': 4}
    operators = ArrayStack()

    for token in expression:
        if token in OPERATORS:
            # Operators are added to the stack, but first the ones with a
            # higher priority are added to the result:
            while not operators.is_empty() and priority[token] <= priority[
                    operators.top()]:
                postfix.append(operators.pop())

            operators.push(token)

        # Left parenthesis are added to the stack:
        elif token == '(':
            operators.push(token)

        # Operators between parenthesis are added from the stack to the result:
        elif token == ')':
            while operators.top() != '(':
                postfix.append(operators.pop())

            operators.pop()  # Pop the left parentheses from the stack.

        # Operands are added to the result:
        else:
            postfix.append(token)

    while not operators.is_empty():
        # The remaining operators are added from the stack to the result:
        postfix.append(operators.pop())

    return postfix
コード例 #9
0
def is_matching(expr):
    """
    Return True if delimiters in expr match correctly, False otherwise
    Parameters
    ----------
    test_str: str or unicode
        expression to evaluate parameters correctness
    Returns
    -------
        Boolean
    """
    delimiters_map = {'(': ')', '{': '}', '[': ']'}

    stack = ArrayStack()

    for c in expr:
        if c in delimiters_map:
            stack.push(c)
        elif c in delimiters_map.itervalues():
            if stack.is_empty() or delimiters_map[stack.top()] != c:
                return False
            else:
                stack.pop()

    return stack.is_empty()
コード例 #10
0
def parse_expression(tokens):
    stack = ArrayStack()
    for token in tokens:
        stack.push(token)
        if token in [')', '}', ']']:
            try:
                right = stack.pop()
                arg_2 = stack.pop()
                if type(arg_2) == str:
                    arg_2 = BinaryTree(int(arg_2))
                operate = stack.pop()
                arg_1 = stack.pop()
                if type(arg_1) == str:
                    arg_1 = BinaryTree(int(arg_1))
                left = stack.pop()
            except EmptyStackError:
                return
            except ValueError:
                return
            if (left, right) not in [('(', ')'), ('{', '}'), ('[', ']')]:
                return
            parse_tree = BinaryTree(operate)
            parse_tree.left_node = arg_1
            parse_tree.right_node = arg_2
            stack.push(parse_tree)
    if stack.is_empty():
        return
    parse_tree = stack.pop()
    if not stack.is_empty():
        return
    if type(parse_tree) == str:
        parse_tree = BinaryTree(int(parse_tree))
    return parse_tree
コード例 #11
0
def parse_expression(tokens):
    parentheses = {')': '(', ']': '[', '}': '{'}
    stack = ArrayStack()
    for token in tokens:
        try:
            token = BinaryTree(int(token))
        except ValueError:
            pass
        if token not in parentheses:
            stack.push(token)
        else:
            try:
                arg_2 = stack.pop()
                operator = stack.pop()
                arg_1 = stack.pop()
                opening_group_symbol = stack.pop()
                if parentheses[token] != opening_group_symbol:
                    return
                parse_tree = BinaryTree(operator)
                parse_tree.left_node = arg_1
                parse_tree.right_node = arg_2
                stack.push(parse_tree)
            except EmptyStackError:
                return
    if stack.is_empty():
        return
    parse_tree = stack.pop()
    if not stack.is_empty():
        return
    return parse_tree
コード例 #12
0
def is_valid_html(raw_html):
    """
    Return True if the each opening html tag in the raw_html string has and associated closing html tag.
    Parameters
    ----------
    raw_html: str or unicode
        The raw html string we need to check for validity
    Returns
    -------
        Boolean
    """
    def is_opening_tag(tag):
        return not tag.startswith('/')

    stack = ArrayStack()
    opening_idx = raw_html.find('<')
    while opening_idx != -1:
        closing_idx = raw_html.find('>', opening_idx + 1)
        if closing_idx == -1:
            return False
        tag = raw_html[opening_idx + 1:closing_idx]

        if is_opening_tag(tag):
            stack.push(tag)
        else:
            if stack.is_empty() or stack.top() != tag[1:]:
                return False
            else:
                stack.pop()
        opening_idx = raw_html.find('<', closing_idx + 1)

    return stack.is_empty()
コード例 #13
0
def reverse_file(file_path):
    stack = ArrayStack()
    with open(file_path, 'r') as f:
        for line in f:
            stack.push(line.rstrip('\n'))

    with open(file_path, 'w') as f:
        while not stack.is_empty():
            f.write(''.join([stack.pop(), '\n']))
コード例 #14
0
def match_paranthesis(expression):
    """Checks if the parantheses from the expression match up correctly"""
    stack=ArrayStack()
    for s in expression:
        if s == '(':
            stack.push(s)
        if s == ')':
            if stack.is_empty():
                return False
            else:
                stack.pop()
    return stack.is_empty()
コード例 #15
0
class ArrayStack:
    """LIFO Stack implementation using a Python list as underlying storage."""
    def __init__(self):
        """Create an empty stack."""
        self._data = []  # nonpublic list instance

    def __len__(self):
        """Return the number of elements in the stack."""
        return len(self._data)

    def is_empty(self):
        """Return True if the stack is empty."""
        return len(self._data) == 0

    def push(self, e):
        """Add element e to the top of the stack."""
        self._data.append(e)  # new item stored at end of list

    def top(self):
        """
        Return (but do not remove) the element at the top of the stack.

        Raise Empty exception if the stack is empty.
        """
        if self.is_empty():
            raise Exception('Stack is empty')
        return self._data[-1]  # the last item in the list

    def pop(self):
        """Remove and return the element from the top of the stack (i.e., LIFO).

        Raise Empty exception if the stack is empty.
        """
        if self.is_empty():
            raise Exception('Stack is empty')
        return self._data.pop()  # remove last item from list

    if __name__ == '__main__':

        from array_stack import ArrayStack
        s = ArrayStack()

        # question 3 of take home exam
        s.push(3)  # bottom
        s.push(2)  # middle
        s.push(1)  # top

        x = s.pop()
        if x < s.top():
            x = s.top()

        print x
def reverse_file(filename):
    """Overwrite given file with its contents reversed line-by-line"""
    S = ArrayStack()
    original = open(filename)
    for line in original:
        S.push(line.rstrip('\n'))             #we will re-insert newlines when writing
    original.close()

    #Now overwrite contents with LIFO order
    output = open(filename, 'w')
    while not S.is_empty():
        output.write(S.pop() + '\n')
    output.close()
コード例 #17
0
def is_matched_delimiters(expr):
    sym_stack = ArrayStack()
    lefty = "[{("
    righty = "]})"
    for c in expr:
        if c in lefty:
            sym_stack.push(c)
        elif c in righty:
            if sym_stack.is_empty():
                return False
            e = sym_stack.pop()
            if lefty.index(e) != righty.index(c):
                return False
    return sym_stack.is_empty()
コード例 #18
0
def is_matched(expr):
    """Return True if all delimiters are matched; False otherwise"""
    openers = '([{'
    closers = ')]}'
    S = ArrayStack()
    for c in expr:
        if c in openers:
            S.push(c)
        elif c in closers:
            if S.is_empty():  #nothing to match
                return False
            elif closers.index(c) != openers.index(S.pop()):  #mismatched
                return False
    return S.is_empty()  #Are all opening brackets matched?
コード例 #19
0
def is_matched(expr):
    """Return True if all delimiters are properly match; False otherwise."""
    lefty = '({['                               # opening delimiters
    righty = ')}]'                              # respective closing delims
    S = ArrayStack()
    for c in expr:
        if c in lefty:
            S.push(c)                               # push left delimiter on stack
        elif c in righty:
            if S.is_empty():
                return False                          # nothing to match with
            if righty.index(c) != lefty.index(S.pop()):
                return False                          # mismatched
            return S.is_empty()                         # were all symbols matched?
コード例 #20
0
def is_matched_html(raw):
    """Return True if all HTML tags are properly match; False otherwise."""
    S = ArrayStack()
    j = raw.find('<')  # find first '<' character (if any)
    while j != -1:
        k = raw.find('>', j + 1)  # find next '>' character
        if k == -1:
            return False  # invalid tag
        tag = raw[j + 1:k]  # strip away < >
        if not tag.startswith('/'):  # this is opening tag
            S.push(tag)
        else:  # this is closing tag
            if S.is_empty():
                return False  # nothing to match with
            if tag[1:] != S.pop():  # tag[1:] strip away '/'
                return False  # mismatched delimiter
        j = raw.find('<', k + 1)  # find next '<' character (if any)
    return S.is_empty()  # were all opening tags matched?
def delimiter_matched_v2(expr: str) -> bool:
    """
    >>> delimiter_matched_v2('[(2+x)*(3+y)]')
    True

    >>> delimiter_matched_v2('{[{(xbcd))]}')
    False
    """
    S = ArrayStack()
    d = {")": "(", "]": "[", "}": "{"}

    for c in expr:
        if c in d.values():
            S.push(c)
        elif c in d:
            if S.is_empty() or d[c] != S.pop():
                return False
    return S.is_empty()
コード例 #22
0
def is_matched_html(raw):
    """Return True if all HTML tags are propery matched; False otherwise"""
    S = ArrayStack()
    j = raw.find('<')  #find first opening tag
    while j != -1:  #while there are still opening tags left
        k = raw.find('>', j + 1)  #find next closing tag
        if k == -1:
            return False
        tag = raw[j + 1:k]  #strip off brackets... TODO: only select tag name
        if not tag.startswith('/'):  #this is an opening tag
            S.push(tag)
        else:  #closing tag
            if S.is_empty():  #nothing to match with
                return False
            if tag[1:] != S.pop():
                return False  #mismatched
        j = raw.find('<', k + 1)  #find next delimiter
    return S.is_empty()  #were all opening tags matched?
コード例 #23
0
def evaluate_expression(tokens):
    stack = ArrayStack()
    for token in tokens:
        stack.push(token)
        if token in [')', '}', ']']:
            try:
                right = stack.pop()
                arg_2 = stack.pop()
                if type(arg_2) == str:
                    arg_2 = int(arg_2)
                operate = stack.pop()
                arg_1 = stack.pop()
                if type(arg_1) == str:
                    arg_1 = int(arg_1)
                left = stack.pop()
            except EmptyStackError:
                return
            except ValueError:
                return
            #print((left,right))
            if (left, right) not in [('(', ')'), ('{', '}'), ('[', ']')]:
                return
            A = {
                '+': add,
                '-': sub,
                '*': mul,
                '/': truediv
            }[operate](arg_1, arg_2)
            #print(A)
            stack.push({
                '+': add,
                '-': sub,
                '*': mul,
                '/': truediv
            }[operate](arg_1, arg_2))

    if stack.is_empty():
        return
    value = stack.pop()
    if not stack.is_empty():
        return
    if type(value) == str:
        value = int(value)
    return value
def delimiter_matched_v1(expr):
    """Return True if all delimiters are properly match; False otherwise.

    >>> delimiter_matched_v1('[(2+x)*(3+y)]')
    True

    >>> delimiter_matched_v1('{[{(xbcd))]}')
    False
    """
    left, right = '({[', ')}]'
    S = ArrayStack()

    for c in expr:
        if c in left:
            S.push(c)
        elif c in right:
            if S.is_empty() or right.index(c) != left.index(S.pop()):
                return False
    return S.is_empty()
コード例 #25
0
def is_matched_html(string):
    tag_stack = ArrayStack()
    open_idx = string.find("<")
    while open_idx != -1:
        close_idx = string.find(">", open_idx + 1)
        if close_idx == -1:
            return False
        tag = string[open_idx + 1:close_idx]
        if tag.startswith("/"):  # It is close tag
            if tag_stack.is_empty():
                return False
            if tag_stack.pop() != tag[1:]:
                return False
        else:
            tag_stack.push(tag)

        open_idx = string.find("<", close_idx + 1)

    return tag_stack.is_empty()
コード例 #26
0
def evaluate(expression):
    operands = ArrayStack()

    for token in expression:
        if token in OPERATORS:
            b = operands.pop()  # second operand
            a = operands.pop()  # first operand

            if token == '/' and b == 0:
                return 'Cannot divide by zero, try again.'
            elif token == '^' and b < 1 and a < 0:
                return 'Cannot root negative number, try again.'
            else:
                operands.push(calculate(b, a, token))

        else:
            operands.push(float(token))

    return operands.pop()
コード例 #27
0
def text2notes(text):
    '''
    Takes text and maps it to notes.
    '''
    notes = []  # The notes
    num_stack = ArrayStack()  # Our stack of numbers

    for ch in text:  # Iterate over every character in the string
        note = __get_mapping(ch)  # Get the mapping
        if ch.isdigit():
            # If digit, add to num_stack
            num_stack.push(int(ch))
        elif ch.lower() == repeat_char and not num_stack.is_empty():
            # If the repeat character and numbers on the stack,
            # pop the most recent number and call the repeat function
            __append_repeat(notes, num_stack.pop())
        elif note != None:
            # If the note has a mapping, add it to notes
            notes.append(note)

    return notes
コード例 #28
0
def is_matched_html(raw):
    stack = ArrayStack()
    j = raw.find('<')

    while j != -1:
        k = raw.find('>', j + 1)  # find next '>'
        if k == -1:
            return False

        tag = raw[j + 1:k]  # < > 之间的内容
        if not tag.startswith('/'):  # it's a opening tag
            stack.push(tag)
        else:
            if stack.is_empty():
                return False
            if tag[1:] != stack.pop():
                return False  # mismatched delimiter

        j = raw.find('<', k + 1)

    return stack.is_empty()
コード例 #29
0
 def test_stack(self):
     stack = ArrayStack()
     assert stack.__repr__() == 'Stack: bottom [] top'
     assert stack.is_empty() == True
     stack.push(1)
     assert stack.is_empty() == False
     assert stack.__repr__() == 'Stack: bottom [1] top'
     stack.push(2)
     assert len(stack) == 2
     assert stack.__repr__() == 'Stack: bottom [1,2] top'
     assert stack.top() == 2
     assert stack.pop() == 2
     assert len(stack) == 1
     assert stack.__repr__() == 'Stack: bottom [1] top'
     assert stack.top() == 1
     assert stack.pop() == 1
     assert stack.__repr__() == 'Stack: bottom [] top'
     with pytest.raises(EmptyError):
         stack.top()
     with pytest.raises(EmptyError):
         stack.pop()
コード例 #30
0
def main():
    print("Creating a stack...")
    a = ArrayStack()
    print("Length of the stack:", len(a))
    print("The stack is empty:", a.is_empty())
    print()

    print("Pushing 10 to the stack...")
    a.push(10)
    print("The element at the top of the stack is", a.top())
    print("Length of the stack:", len(a))
    print("The stack is empty:", a.is_empty())
    print()

    print("Pushing 20 30 40 50 to the stack in this order...")
    a.push(20)
    a.push(30)
    a.push(40)
    a.push(50)
    print("The element at the top of the stack is", a.top())
    print("Length of the stack:", len(a))
    print("The stack is empty:", a.is_empty())
    print()

    print("Popping the stack...")
    a.pop()
    print("The element at the top of the stack is", a.top())
    print("Length of the stack:", len(a))
    print("The stack is empty:", a.is_empty())
    print()

    print("Popping the stack 4 times...")
    for i in range(3):
        a.pop()
    print("The element at the top of the stack is", a.top())
    print("Length of the stack:", len(a))
    print("The stack is empty:", a.is_empty())
    print()