Guest User

Untitled

a guest
Jul 18th, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.87 KB | None | 0 0
  1. import sys
  2.  
  3. # Constants
  4. OPERATORS = ['*', '/', '+', '-']
  5. DECIMAL_SYMBOLS = [',', '.']
  6. SIGN_SYMBOLS = ['-', '+']
  7. PARENTHESIS_OPEN = '('
  8. PARENTHESIS_CLOSE = ')'
  9. PRECEDENCE = [[PARENTHESIS_OPEN], ['*', '/'], ['+', '-']]
  10.  
  11. # State variables
  12. should_exit = False
  13.  
  14. # Utility functions
  15. def subtraction(a, b):
  16. if b > 0:
  17. return subtraction(a, b - 1) - 1
  18. else:
  19. return a
  20.  
  21. def addition(a, b):
  22. if b > 0:
  23. return addition(a, b - 1) + 1
  24. else:
  25. return a
  26.  
  27. def multiplication(a, b):
  28. if (b > 0):
  29. return addition(multiplication(a, b - 1), a)
  30. else:
  31. return 0
  32.  
  33. def division(a, b):
  34. if (a > b):
  35. return 1 + division(subtraction(a, b), b)
  36. else:
  37. return 1
  38.  
  39. OPERATOR_FUNCS = {'-': subtraction, '+': addition, '*': multiplication, '/': division}
  40.  
  41. def halt_error(s):
  42. print('invalid expression: %s' % s)
  43. sys.exit()
  44.  
  45. def is_operator(s):
  46. return s in OPERATORS
  47.  
  48. def tokenize(str):
  49. tokens = []
  50.  
  51. c = [] # Temporary storage for operands
  52. s = [] # Set of tokens
  53. for cr in str:
  54. if cr.isnumeric():
  55. c.append(cr) # Keep track of operand
  56. elif cr == PARENTHESIS_OPEN or cr == PARENTHESIS_CLOSE or is_operator(cr):
  57. s.append(c) # Push operand
  58. c = [] # Empty storage
  59. s.append(cr) # Push operator
  60. elif cr in DECIMAL_SYMBOLS:
  61. halt_error('no support for floating point arithmetic')
  62.  
  63. s.append(c) # Push operand
  64.  
  65. return list(map(''.join, [v for v in s if v])) # Remove empty lists, join each inner list
  66.  
  67. # Returns the intersection of a and b
  68. def intersect(a, b):
  69. return [v for v in a if v in b]
  70.  
  71. # Returns the nth index of v in l
  72. def nth_index(l, v, n):
  73. i = -1
  74. for j in range(n):
  75. i = l.index(v, i + 1)
  76. return i
  77.  
  78. def execute(expr):
  79. for group in PRECEDENCE:
  80. while len(intersect(expr, group)) > 0:
  81. symbol = intersect(expr, group)[0] # Fetch the first operator in the intersection of the precedence group and the expression
  82. if (symbol == PARENTHESIS_OPEN):
  83. s = expr.index(PARENTHESIS_OPEN) # Find open parenthesis
  84.  
  85. try:
  86. e = nth_index(expr, PARENTHESIS_CLOSE, expr.count(PARENTHESIS_OPEN))
  87. sub_expr = expr[s+1:e] # Containing expression
  88. new_expr = execute(sub_expr) # New expression resulting from recursive call
  89. rem_expr_a = expr[e+1:] # Remaining expression after
  90. rem_expr_b = expr[:s] # Remaining expression before
  91. expr = rem_expr_b + new_expr + rem_expr_a # Reconstruct expression based on new result
  92. except ValueError:
  93. halt_error('could not find matching parenthesis ")"')
  94. elif (is_operator(symbol)):
  95. s = expr.index(symbol) # Find operator
  96. a = int(expr[s-1]) # First operand
  97. b = int(expr[s+1]) # Second operand
  98. new_expr = [OPERATOR_FUNCS[symbol](a, b)] # New expression resulting from operator implementation
  99. rem_expr_a = expr[s+2:] # Remaining expression after
  100. rem_expr_b = expr[:s-1] # Remaining expression before
  101. expr = rem_expr_b + new_expr + rem_expr_a # Reconstruct expression based on new result
  102. return expr
  103.  
  104. def bc(str):
  105. tokens = tokenize(str)
  106. return execute(tokens).pop()
  107.  
  108. #Main logic
  109. while not should_exit:
  110. s = input('')
  111. print(bc(s))
Add Comment
Please, Sign In to add comment