Source

CS193P Assignment 1 / Calculator / descriptionOfProgram.py

Full commit
def descriptionOfTopOfStack(stack, depth=0, lastOperation=None):
    operation = result = None
    if len(stack) > 0:
        topOfStack = stack.pop()
    depth += 1

    if type(topOfStack) is int:
        result = str(topOfStack)
    else:
        operation = topOfStack
        # print "{1} descriptionOfTopOfStack(): this operation: {0}; last
        # operation: {2}".format(operation, depth, lastOperation)

        if operation in ("+", "-", "*", "/"):
            operandRight = descriptionOfTopOfStack(stack, depth, operation)
            operandLeft = descriptionOfTopOfStack(stack, depth, operation)
            if operation == "*" and operandLeft == operandRight and " " not in operandLeft:
                # Icing on the cake: Print x^2 if encountering x * x
                # only use ^2 if x is not a complex expression (avoid missing
                # ())
                result = operandLeft + '^2'
            else:
                template = "({} {} {})" if useBracket(
                    depth, operation, lastOperation) else "{} {} {}"
                result = template.format(operandLeft, operation, operandRight)
        elif operation in ('sin', 'cos', 'tan', 'sqrt', '+/-'):
            template = "{}({})" if useBracket(
                depth, operation, lastOperation) else "{}{}"
            result = template.format(
                operation, descriptionOfTopOfStack(stack, depth, operation))
        elif operation in ('pi'):
            result = 'pi'
        else:
            result = operation

    return result


def useBracket(depth, currentOperation, lastOperation):
    # print "useBracket(): {} {} {}".format(depth, currentOperation,
    # lastOperation)
    if depth == 1 and currentOperation in ('+', '-', '*', '/'):
        return False
    if currentOperation in ('*', '/') and lastOperation in ('+', '-', '*', '/'):
        return False
    if currentOperation in ('+', '-') and lastOperation in ('+', '-'):
        return False
    if lastOperation in ('sin', 'cos', 'tan', 'sqrt', '+/-') and currentOperation in ('+', '-', '*', '/'):
        return False
    return True


def nextOperation(stack):
    try:
        idx = -1
        while(1):
            if type(stack[idx]) is str:
                return stack[idx]
            idx = idx - 1
    except IndexError:
        pass
    return None


def descriptionOfProgram(program):
    output = []
    while (len(program) > 0):
        output.append(descriptionOfTopOfStack(program))
    return ', '.join(output)


tests = [
    [10, 'sqrt'],  # Requirement a
    [3, 5, '+'],  # Requirement b
    [3, 5, 6, 7, '+', '*', '-'],  # Example a
    [3, 5, 6, 7, '+', '*', '-', 'sin'],  # Example a variation 1
    [3, 5, 6, 7, '+', '*', '-', 'sin', 'cos'],  # Example a variation 2
    [3, 5, '+', 'sqrt'],  # Example b
    [3, 'sqrt', 'sqrt'],  # Example c
    [3, 5, 'sqrt', '+'],  # Example d
    ['pi', 4, 4, '*', '*'],  # Example e
    [5, 5, '*', 6, 6, '*', '+', 'sqrt'],  # Example f
    [3, 5, '+', 6, '*'],  # Expects (3 + 5) * 6
    # Commas
    [3, 5],  # Expects 5, 3
    [3, 5, '+', 6, 7, '*', 9, 'sqrt'],  # Expects: sqrt(9), 6 * 7, 3 + 5
]

for test in tests:
    print descriptionOfProgram(test)