September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -1,51 +1,31 @@
|
|||
from math import log as ln
|
||||
from math import sqrt, log, exp, sin, cos, tan, pi, e
|
||||
from ast import literal_eval
|
||||
|
||||
"""
|
||||
>>> # EXAMPLE USAGE
|
||||
>>> result = rpn_to_infix('3 4 2 * 1 -5 - ln 2 3 ** ** / +', VERBOSE=True)
|
||||
>>> result = rpn_to_infix('3 4 2 * 1 5 - 2 3 ^ ^ / +', VERBOSE=True)
|
||||
TOKEN STACK
|
||||
3 ['3']
|
||||
4 ['3', '4']
|
||||
2 ['3', '4', '2']
|
||||
* ['3', Node('2','*','4')]
|
||||
1 ['3', Node('2','*','4'), '1']
|
||||
-5 ['3', Node('2','*','4'), '1', '-5']
|
||||
- ['3', Node('2','*','4'), Node('-5','-','1')]
|
||||
ln ['3', Node('2','*','4'), Node(Node('-5','-','1'),'ln',None)]
|
||||
2 ['3', Node('2','*','4'), Node(Node('-5','-','1'),'ln',None), '2']
|
||||
3 ['3', Node('2','*','4'), Node(Node('-5','-','1'),'ln',None), '2', '3']
|
||||
** ['3', Node('2','*','4'), Node(Node('-5','-','1'),'ln',None), Node('3','**','2')]
|
||||
** ['3', Node('2','*','4'), Node(Node('3','**','2'),'**',Node(Node('-5','-','1'),'ln',None))]
|
||||
/ ['3', Node(Node(Node('3','**','2'),'**',Node(Node('-5','-','1'),'ln',None)),'/',Node('2','*','4'))]
|
||||
+ [Node(Node(Node(Node('3','**','2'),'**',Node(Node('-5','-','1'),'ln',None)),'/',Node('2','*','4')),'+','3')]
|
||||
>>> result
|
||||
5 ['3', Node('2','*','4'), '1', '5']
|
||||
- ['3', Node('2','*','4'), Node('5','-','1')]
|
||||
2 ['3', Node('2','*','4'), Node('5','-','1'), '2']
|
||||
3 ['3', Node('2','*','4'), Node('5','-','1'), '2', '3']
|
||||
^ ['3', Node('2','*','4'), Node('5','-','1'), Node('3','^','2')]
|
||||
^ ['3', Node('2','*','4'), Node(Node('3','^','2'),'^',Node('5','-','1'))]
|
||||
/ ['3', Node(Node(Node('3','^','2'),'^',Node('5','-','1')),'/',Node('2','*','4'))]
|
||||
+ [Node(Node(Node(Node('3','^','2'),'^',Node('5','-','1')),'/',Node('2','*','4')),'+','3')]
|
||||
"""
|
||||
|
||||
prec_dict = {'abs':5, 'sqrt':5, 'exp':5, 'log':5, 'ln':5,
|
||||
'sin':5, 'cos':5, 'tan':5,
|
||||
'**':4, '*':3, '/':3, '+':2, '-':2}
|
||||
assoc_dict = {'abs':0, 'sqrt':0, 'exp':0, 'log':0, 'ln':0,
|
||||
'sin':0, 'cos':0, 'tan':0,
|
||||
'**':1, '*':0, '/':0, '+':0, '-':0}
|
||||
arity_dict = {'abs':1, 'sqrt':1, 'exp':1, 'log':1, 'ln':1,
|
||||
'sin':1, 'cos':1, 'tan':1,
|
||||
'**':2, '*':2, '/':2, '+':2, '-':2}
|
||||
prec_dict = {'^':4, '*':3, '/':3, '+':2, '-':2}
|
||||
assoc_dict = {'^':1, '*':0, '/':0, '+':0, '-':0}
|
||||
|
||||
class Node:
|
||||
def __init__(self,x,op,y=None):
|
||||
self.precedence = prec_dict[op]
|
||||
self.assocright = assoc_dict[op]
|
||||
self.arity = arity_dict[op]
|
||||
self.op = op
|
||||
|
||||
if not self.assocright and self > x and \
|
||||
isinstance(x, Node) and self.arity == 2:
|
||||
self.x = x.x
|
||||
self.y = Node(x.y, x.op, y)
|
||||
else:
|
||||
self.x,self.y = x,y
|
||||
self.x,self.y = x,y
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
|
|
@ -53,7 +33,6 @@ class Node:
|
|||
Building an infix string that looks pretty and evaluates
|
||||
correctly requires more effort.
|
||||
"""
|
||||
|
||||
# easy case, Node is unary
|
||||
if self.y == None:
|
||||
return '%s(%s)'%(self.op,str(self.x))
|
||||
|
|
@ -65,7 +44,6 @@ class Node:
|
|||
(str_y[0] is '-' and self.assocright):
|
||||
|
||||
str_y = '(%s)'%str_y
|
||||
|
||||
# determine right side string and operator
|
||||
str_x = str(self.x)
|
||||
str_op = self.op
|
||||
|
|
@ -80,7 +58,6 @@ class Node:
|
|||
getattr(self.x, 'op', 1) != getattr(self, 'op', 2)):
|
||||
|
||||
str_x = '(%s)'%str_x
|
||||
|
||||
return ' '.join([str_y, str_op, str_x])
|
||||
|
||||
def __repr__(self):
|
||||
|
|
@ -100,76 +77,25 @@ class Node:
|
|||
return self.precedence > other.precedence
|
||||
return self.precedence > prec_dict.get(other,9)
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Node):
|
||||
return self.precedence == other.precedence
|
||||
return self.precedence > prec_dict.get(other,9)
|
||||
|
||||
|
||||
|
||||
def rpn_to_infix(s, VERBOSE=False):
|
||||
"""
|
||||
|
||||
converts rpn notation to infix notation for string s
|
||||
|
||||
"^" are replaced with "**"
|
||||
|
||||
>>> rpn_to_infix('5 4 +')
|
||||
'5 + 4'
|
||||
>>> rpn_to_infix('5 -4 +')
|
||||
'5 - 4'
|
||||
>>> rpn_to_infix('5 -4 -')
|
||||
'5 + 4'
|
||||
>>> rpn_to_infix('5 -4.2 +')
|
||||
'5 - 4.2'
|
||||
>>> rpn_to_infix('-4 2 **')
|
||||
'(-4) ** 2'
|
||||
>>> rpn_to_infix('x y +')
|
||||
'x + y'
|
||||
>>> rpn_to_infix('x -y +')
|
||||
'x - y'
|
||||
>>> rpn_to_infix('5 4 3 2 ** ** **')
|
||||
'5 ** 4 ** 3 ** 2'
|
||||
>>> rpn_to_infix('5 6 ** 7 **')
|
||||
'(5 ** 6) ** 7'
|
||||
>>> rpn_to_infix('1 2 3 + -')
|
||||
'1 - (2 + 3)'
|
||||
>>> rpn_to_infix('4 3 2 + +')
|
||||
'4 + 3 + 2'
|
||||
>>> rpn_to_infix('5 4 3 2 + + +')
|
||||
'5 + 4 + 3 + 2'
|
||||
>>> rpn_to_infix('5 4 3 2 * * *')
|
||||
'5 * 4 * 3 * 2'
|
||||
>>> rpn_to_infix('5 4 3 2 + - +')
|
||||
'5 + (4 - (3 + 2))'
|
||||
>>> rpn_to_infix('3 4 5 * -')
|
||||
'3 - 4 * 5'
|
||||
>>> rpn_to_infix('3 4 5 - *')
|
||||
'(3 - 4) * 5'
|
||||
>>> rpn_to_infix('4 2 * 1 5 - +')
|
||||
'4 * 2 + (1 - 5)'
|
||||
>>> rpn_to_infix('4 2 * 1 5 - 2 ** /')
|
||||
'4 * 2 / (1 - 5) ** 2'
|
||||
>>> rpn_to_infix('3 4 2 * 1 5 - 2 3 ** ** / +')
|
||||
'3 + 4 * 2 / (1 - 5) ** 2 ** 3'
|
||||
>>> rpn_to_infix('1 2 + 3 4 + ** 5 6 + **')
|
||||
'((1 + 2) ** (3 + 4)) ** (5 + 6)'
|
||||
>>> rpn_to_infix('x sin')
|
||||
'sin(x)'
|
||||
>>> rpn_to_infix('5 4 3 2 + sqrt - +')
|
||||
'5 + (4 - sqrt(3 + 2))'
|
||||
>>> rpn_to_infix('5 4 3 2 + sqrt ln - +')
|
||||
'5 + (4 - ln(sqrt(3 + 2)))'
|
||||
>>> rpn_to_infix('5 sin 4 cos *')
|
||||
'sin(5) * cos(4)'
|
||||
>>> rpn_to_infix('5 4 cos * sin')
|
||||
'sin(5 * cos(4))'
|
||||
>>> rpn_to_infix('3 4 2 * 1 -5 - ln 2 3 ** ** / +')
|
||||
'3 + 4 * 2 / ln(1 + 5) ** 2 ** 3'
|
||||
"""
|
||||
if VERBOSE : print('TOKEN STACK')
|
||||
|
||||
stack=[]
|
||||
for token in s.replace('^','**').split():
|
||||
for token in s.replace('^','^').split():
|
||||
if token in prec_dict:
|
||||
if arity_dict[token] == 1:
|
||||
stack.append(Node(stack.pop(),token))
|
||||
elif arity_dict[token] == 2:
|
||||
stack.append(Node(stack.pop(),token,stack.pop()))
|
||||
stack.append(Node(stack.pop(),token,stack.pop()))
|
||||
else:
|
||||
stack.append(token)
|
||||
|
||||
|
|
@ -178,36 +104,14 @@ def rpn_to_infix(s, VERBOSE=False):
|
|||
|
||||
return str(stack[0])
|
||||
|
||||
def rpn_eval(s):
|
||||
"""
|
||||
computes the value of an rpn string
|
||||
|
||||
>>> rpn_eval('5 4 +') == eval(rpn_to_infix('5 4 +'))
|
||||
True
|
||||
>>> rpn_eval('-4 2 **') == eval(rpn_to_infix('-4 2 **'))
|
||||
True
|
||||
>>> round(rpn_eval('3 4 2 * 1 -5 - ln 2 3 ** ** / +'),7) == \
|
||||
round(eval(rpn_to_infix('3 4 2 * 1 -5 - ln 2 3 ** ** / +')),7)
|
||||
True
|
||||
>>> round(rpn_eval('5 4 3 2 + sqrt ln - +'),7) == \
|
||||
round(eval(rpn_to_infix('5 4 3 2 + sqrt ln - +')),7)
|
||||
True
|
||||
"""
|
||||
|
||||
stack=[]
|
||||
for token in s.replace('^','**').split():
|
||||
if token in prec_dict:
|
||||
if arity_dict[token] == 1:
|
||||
stack.append(literal_eval('%s(%s)'%(token,stack.pop())))
|
||||
elif arity_dict[token] == 2:
|
||||
x,y=stack.pop(),stack.pop()
|
||||
stack.append(literal_eval('(%s) %s %s'%(y,token,x)))
|
||||
else:
|
||||
stack.append(token)
|
||||
|
||||
return stack[0]
|
||||
|
||||
strTest = "3 4 2 * 1 -5 - ln 2 3 ** ** / +"
|
||||
strResult = rpn_to_infix(strTest)
|
||||
strTest = "3 4 2 * 1 5 - 2 3 ^ ^ / +"
|
||||
strResult = rpn_to_infix(strTest, VERBOSE=False)
|
||||
print ("Input: ",strTest)
|
||||
print ("Output:",strResult)
|
||||
|
||||
print()
|
||||
|
||||
strTest = "1 2 + 3 4 + ^ 5 6 + ^"
|
||||
strResult = rpn_to_infix(strTest, VERBOSE=False)
|
||||
print ("Input: ",strTest)
|
||||
print ("Output:",strResult)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue