quiz about symbolic manipulation
Bengt Richter
bokr at oz.net
Sat Dec 14 00:43:05 EST 2002
On 14 Dec 2002 00:05:19 GMT, bokr at oz.net (Bengt Richter) wrote:
[ ... first version substitute routine ...]
> 'square(square(x+y)+z)+square(x+w)'
> >>> substitute(e, 'square','(%s)**2')
> '((x+y)**2+z)**2+(x+w)**2'
>
>Well, this is not so exciting for functions with multiple parameters. How
>might you want to rewrite those? Probably isolate terms and rewrite each term
>and then feed that as a tuple to a rewfmt? If you can assume no terms containing
>nested commas (probably reasonable for math expressions) then it shouldn't be
>too hard. But much beyond that and you may want to use the Python parser after all ;-)
>
>Anyway, I'll leave the rest as an exercise ;-)
It was such a jellybean project I couldn't resist modding it a it to handle
comma separated function args, and multiple functions:
====< simiosub.py >=======================================
# simiosub.py
# a program to rewrite function calls in an expression
from __future__ import generators
import tokenize, StringIO, token
def tokens(expr):
tokens = tokenize.generate_tokens(StringIO.StringIO(expr).readline)
return [t[1] for t in tokens]
def substitute(expr, **funs):
def funrew(expr, funs):
if isinstance(expr, str): toks = tokens(expr)
else: toks = expr
while toks:
if toks[0] not in funs:
yield toks.pop(0)
continue
currfun = toks.pop(0)
# find and process parenthesized call parameter expression
i = ump = 0
for t in toks:
i += 1
if t =='(': ump += 1
if t == ')':
ump -= 1
if not ump: break
rest = toks[i:]
parenexp = toks[1:i-1]
ixcommas = [t[1] for t in zip(parenexp,range(len(parenexp)))
if t[0]==',']+[len(parenexp)]
j = 0; paramlist= []
for k in ixcommas:
paramlist.append(''.join(funrew(parenexp[j:k], funs)))
j = k+1
yield (funs[currfun] % tuple(paramlist))
toks = rest
return ''.join(funrew(expr, funs))
e = 'square(square(x+y)+z)+square(x+w)'
# substitute(e, 'square','(%s)**2')
if __name__ == '__main__':
import sys
args = sys.argv[1:]
if not args: args = ['square(square(x+y)+z)+square(x+w)', 'square=(%s)**2']
# should return '((x+y)**2+z)**2+(x+w)**2'
e = args.pop(0); funs = dict(map(lambda x: tuple(x.split('=')),args))
print 'before:', e
for sub in args: print ' ',sub
print ' after:', substitute(e, **funs)
==========================================================
Default test:
[21:44] C:\pywk\clp>simiosub.py
before: square(square(x+y)+z)+square(x+w)
square=(%s)**2
after: ((x+y)**2+z)**2+(x+w)**2
A little more complex:
[21:44] C:\pywk\clp>simiosub.py foo(x*y)+zeep(1,foo(2),3) "foo=(foo %s)" "zeep=(zeep %s %s %s)"
before: foo(x*y)+zeep(1,foo(2),3)
foo=(foo %s)
zeep=(zeep %s %s %s)
after: (foo x*y)+(zeep 1 (foo 2) 3)
Regards,
Bengt Richter
More information about the Python-list
mailing list