search and replace text in python - python

I am kinda to python programming
I have no clue how to solve that task:
for line in f: br
m = re.search("f(\S+\s+,\s+\S+)",
"56 - f(32 , 6*3) + 62 * ( 54 - 3 ) + f(5 , 9+y)")
print m.group()
I have to convert all f(x , y) to x*y.
I haven't got an idea how to solve that. I tried with splitting but didn't worked.
Thanks!

I would recommend a tour towards the python tutorial, perhaps the string section.
After that, the regexp tutorial.

Regular expressions can be a complicated beast, I suggest reading up on them. For this particular scenario re.sub should do the trick.
Here's a sample of what I've come up with using the input you provided.
import re
inp = "56 - f(32 , 6*3) + 62 * ( 54 - 3 ) + f(5 , 9+y)"
# Matches on characters, arithmetic operations, and digits (hopefully)
pattern = r"f\(\s*([a-z\d\-\+\*/]+)\s*,\s*([a-z\d\-\+\*/]+)\s*\)"
print re.sub(pattern, r"\1 * \2", inp)
This should produce:
56 - 32 * 6*3 + 62 * ( 54 - 3 ) + 5 * 9+y
I am no expert when it comes to regular expressions but hopefully the above will get you started. I doubt the above regex will catch all occurrences and for that I suggest you ask someone with better regex-fu. Merely providing this as an example.

Try re.sub.
regex = re.compile('a+')
x = re.sub(regex, 'd', 'baac')
print(x)
Prints:
bdc

Like this!?
>>> inp = "56 - f(32 , 6*3) + 62 * ( 54 - 3 ) + f(5 , 9+y)"
>>> import re
>>> re.sub(r'f\((\S+)\s*,\s*(\S+)\)',r'\1*\2',inp)
'56 - 32*6*3 + 62 * ( 54 - 3 ) + 5*9+y'
probably its useful to put the multiplication in parantheses? Then you could use the following regexp:
>>> re.sub(r'f\((\S+\s*),(\s*\S+)\)',r'(\1*\2)',inp)
'56 - (32 * 6*3) + 62 * ( 54 - 3 ) + (5 * 9+y)'

Related

Sympy : simplification with expression substitution

I have several expressions involving the norm or norm squared of a vector u. I'd like to simplify these expressions by substituting a known value for the norm of u. However, it seems that obvious expressions involving even simple multiples of the norm are not simplified.
As an example, this code does what I would expect :
import sympy as sp
u1,u2,u3 = sp.symbols('u_1, u_2, u_3',real=True,positive=True)
utu = u1**2 + u2**2 + u3**2
print("Ex. 1")
print(utu.subs(utu,1))
This produces the expected output
Ex. 1
1
However, 2*utu does not simplify in the way I would expect :
print("Ex 2")
print((2*utu).subs(utu,1))
Ex 2
2*u_1**2 + 2*u_2**2 + 2*u_3**2
I can explicitly force the substitution with this :
print("Ex 3")
print((2*utu).subs(2*utu,2))
which produces the expected output :
Ex 3
2
Ideally, I'd like to substitute under a norm function, but the run into the same issue.
u = sp.Matrix(3, 1, [u1,u2,u3])
print("Ex 4")
print(u.norm().subs(utu,1))
print("Ex 5")
print((2*u).norm().subs(utu,1))
print("Ex 6")
print((2*u).norm().subs(4*utu,4))
which produces
Ex 4
1
Ex 5
sqrt(4*u_1**2 + 4*u_2**2 + 4*u_3**2)
Ex 6
2
Are there tricks I am missing that will catch these obvious (to me at least - maybe not to Sympy?) simplifications? I've tried factor and expand, without much luck.
Let's analyze this expression:
expr = 2*utu
# out: 2*u_1**2 + 2*u_2**2 + 2*u_3**2
The multiplication has been evaluated. This is SymPy's default behavior: it evaluates things. We can work with the expression manipulation functions to achieve our goal.
For example:
expr = collect_const(expr)
# out: 2*(u_1**2 + u_2**2 + u_3**2)
expr.subs(utu, 1)
# out: 2
Another example:
expr = (2 * u).norm()
# out: sqrt(4*u_1**2 + 4*u_2**2 + 4*u_3**2)
expr = expr.simplify() # Note that expr.factor() produces the same result with this expression
# out: 2*sqrt(u_1**2 + u_2**2 + u_3**2)
expr.subs(utu, 1)
# out: 2
If you play (and modify) with these examples, you will realize that the same result can be achieved with different functions (factor, simplify, collect, collect_const, ...), but even one little change in the expression might prevent one function from "doing its work", while others might be able to. Expression manipulation is kind of an art that one should practice (a lot).
For completeness, I'm going to show you UnevaluatedExpr, which allows a particular expression to remain unevaluated during expression manipulation, though it might not always be the best choice:
n = UnevaluatedExpr(utu)
# out: u_1**2 + u_2**2 + u_3**2
expr = 4 * n
# out: 4*(u_1**2 + u_2**2 + u_3**2)
Note that SymPy didn't proceed with the full evaluation. Now:
expr.subs(utu, 1)
# out: 4*1
Why is there a 4*1 instead of 4? The 1 refers to the UnevaluateExpr object that we created earlier: to evaluate it we can use the doit() method:
expr.subs(utu, 1).doit()
# 4
Keep in mind that while using UnevaluateExpr, the expression becomes non-commutative (I think it's a bug with SymPy), which will prevent other functions to produce the expected results.
Substituting compound expressions is problematic. For the most part you should only expect subs to work if the expression to be replaced is known to always appear literally as part of the expression tree that you are substituting into. When possible then it is better to rearrange for a single symbol like:
In [10]: utu
Out[10]:
2 2 2
u₁ + u₂ + u₃
In [11]: (2*utu).subs(u1**2, 1 - u2**2 - u3**2)
Out[11]: 2
Even here we are substituting for a power of a symbol (u1**2) which is potentially fragile if we can't be sure that exactly that power will always appear in the expression. More generally there are functions that can simplify expressions based on knowing some polynomial relation e.g. ratsimpmodprime:
In [16]: e = (1 - u1**2) / (u1**2 + u2**2 + u3**2)
In [17]: e
Out[17]:
2
1 - u₁
───────────────
2 2 2
u₁ + u₂ + u₃
In [18]: ratsimpmodprime(e, [u1**2 + u2**2 + u3**2 - 1])
Out[18]:
2 2
u₂ + u₃
Other possibilities could be using resultants or Groebner bases to do similar things. Note that u.norm() has a square root which is symbolically awkward so it is better to work with the square of the norm (same as when working on pen and paper):
In [20]: ratsimpmodprime((2*u).norm()**2, [u1**2 + u2**2 + u3**2 - 1])
Out[20]: 4
Also if you just want a more powerful version of subs then you can use replace but with patterns:
In [21]: a = Wild('a')
In [22]: p = a*u1**2 + a*u2**2 + a*u3**2
In [23]: (2*utu).replace(p, a)
Out[23]: 2
In [24]: (2*u).norm().replace(p, a)
Out[24]: 2
Both solid answers already. If you have an arbitrary expression that you expect to be a factor in another, factor_terms is what I try first to make that factor appear. It will collect common factors without doing factoring. But if this doesn't work and you know you have a factor, div is a nice way to check and see the expression with the factor removed:
>>> expr = 2*(x + y)
>>> factor_terms(expr)
2*(x + y)
>>> e2 = expand(expr*(x -y)) # 2*x**2 - y**2
>>> factor_terms(e2)
2*(x**2 - y**2)
>>> div(_,-x-y)
(-2*x + 2*y, 0)
>>> _[0]*z # if you wanted to replace factor -x-y with z
z*(-2*x + 2*y)

symbolic solution of linear equations using Sympy

Basically I have [5x5][5x1]=[0] and would like to have the symbolic expression of the solution.
Here is my code.
from sympy import symbols, solve
gm1, gm2, gm4 = symbols(['gm1', 'gm2', 'gm4'])
gds1, gds2, gds3, gds4, gds5 = symbols(['gds1', 'gds2', 'gds3', 'gds4', 'gds5'])
s = symbols(['s'])
Cd, CF , Cin, Ct = symbols(['Cd', 'CF', 'Cin', 'Ct'])
K = symbols(['K'])
vb, vc, ve, vout, iin = symbols(['vb', 'vc', 've', 'vout', 'iin'])
sol = solve([-(gds1+gds3+(s*Cd))*vb + (gm1+gds1)*ve + -gm1*vout, \
-gm4*vb + (gds4-gds2-(s*Cin)-(s*CF))*vc + (gds2+gm2)*ve + s*CF*vout + iin, \
gds1*vb + gds2*vc + (-(s*Ct)-gds5-gds1-gm1-gm2-gds2)*ve + gm1*vout, \
K*vc + vout], [vout])
print(sol)
but, I got this error
TypeError: can't multiply sequence by non-int of type 'Symbol'
From here, symbolic multiplication seems working just fine.
I am not sure whether I describe my problem in a way that does not comply with Sympy or something else.
What did I miss here?
The problem is in the assignment of the single symbols s and K. If instead you do:
s, K = symbols(['s', 'K'])
Or:
s = symbols('s')
K = symbols('K')
Whether you get the right answer or not is another matter :)
When you pass a list to symbols you get a list back. You can unpack that like [s] = symbols(['s']) or you can just pass a string of space or comma separated strings like x, y = symbols('x y') or x, y = symbols(','.join(['x', 'y']).
If you select manual=True you will get a solution vout=K*vc which sets the 4th equation to 0. But that was almost obvious, right? And you didn't need the other 3 equations to tell you that. So go ahead and pick up to 3 other variables for which you want to solve. There are lots of possibilities:
>>> from sympy.functions.combinatorial.numbers import nC
>>> allsym = Tuple(*eqs).free_symbols
>>> nfree = len(allsym) - 1 # always take vout
>>> print(nC(nfree, 3)) # want 3 others
816
For example, selecting (vout, gds4, gm1, gds5) gives a solution of
[{gds4: (CF*K*s*vc + CF*s*vc + Cin*s*vc + gds2*vc -
gds2*ve - gm2*ve + gm4*vb - iin)/vc,
gm1: (Cd*s*vb + gds1*vb - gds1*ve + gds3*vb)/(K*vc + ve),
gds5: -(Cd*s*vb + Ct*s*ve - gds2*vc + gds2*ve + gds3*vb + gm2*ve)/ve,
vout: -K*vc}]

sympy.subs - wrong substitution

I have this equation:
(1 - tau2)**3 + (tau2-tau1)**5
And I want to substitute (1-tau2) by (1-tau3). However, I get the wrong result.
This is my code:
tau1,tau2,tau3= symbols('tau1,tau2,tau3')
exp= (1-tau2)**3+(tau2-tau1)**5
res=exp.subs((1-tau2),(1-tau3))
print('exp:',exp)
print('res:',res)
And the result is:
exp= (1 - tau2)**3 + (-tau1 + tau2)**5
res= (1 - tau3)**3 + (-tau1 + tau3)**5
But it should be:
res= (1 - tau3)**3 + (-tau1 + tau2)**5
How can I solve this?
Sometimes you want a smart substitution -- in this case, recognizing that your substitution is equivalent to replacing tau2 with tau3 -- and sometimes you want an exact substitution. In case of the latter, use xreplace:
>>> from sympy.abc import x, y
>>> (1-x)**3+(x-y)**5
(1 - x)**3 + (x - y)**5
>>> _.xreplace({1-x: z})
z**3 + (x - y)**5

Python string function parameter replacing

I would like to ask your help. I have started learning python, and there are a task that I can not figure out how to complete. So here it is.
We have a input.txt file containing the next 4 rows:
f(x, 3*y) * 54 = 64 / (7 * x) + f(2*x, y-6)
x + f(21*y, x - 32/y) + 4 = f(21 ,y)
86 - f(7 + x*10, y+ 232) = f(12*x-4, 2*y-61)*32 + f(2, x)
65 - 3* y = f(2*y/33 , x + 5)
The task is to change the "f" function and its 2 parameters into dividing. There can be any number of spaces between the two parameters. For example f(2, 5) is the same as f(2 , 5) and should be (2 / 5) with exactly one space before and after the divide mark after the running of the code. Also, if one of the parameters are a multiplification or a divide, the parameter must go into bracket. For example: f(3, 5*7) should become (3 / (5*7)). And there could be any number of function in one row. So the output should look like this:
(x / (3*y)) * 54 = 64 / (7 * x) + ((2*x) / (y-6))
x + ((21*y) / (x - 32/y)) + 4 = (21 / y)
86 - ((7 + x*10) / (y+ 232)) = ((12*x-4) / (2*y-61))*32 + (2 / x)
65 - 3* y = ((2*y/33) / (x + 5))
I would be very happy if anyone could help me.
Thank you in advance,
David
Using re:
In [84]: ss=r'f(x, 3*y) * 54 = 64 / (7 * x) + f(2*x, y-6)'
In [85]: re.sub(r'(f\()(.*?),(.*?)(\))', lambda m: '((%s) / (%s))'%(m.group(2), m.group(3)), ss)
Out[85]: '((x) / ( 3*y)) * 54 = 64 / (7 * x) + ((2*x) / ( y-6))'
Explanation:
re.sub(pattern, repl, string, count=0, flags=0) returns the string obtained by replacing the leftmost
non-overlapping occurrences of the pattern in string by the
replacement repl.
The () are used to catch the groups;
*? is a non-greedy qualifier, which matches as little text as possible.
Here's some places to start:
You can check if one string is in another string using string1 in
string2 (e.g., 'bcd' in 'abcdefg' -> True)
You can identify the insides of f() calls by finding the locations of 'f(' in a
string and then adding 1 to an index (that starts at 1) when you find
a '(' and removing 1 when you find ')'. When you hit 0 you're done.
You can break a string into a list by a matching string by
string1.split(string2) (e.g., 'a,b'.split(',') -> ['a', 'b']
You can format a string easily using the
.format method
(e.g., '({0} % {1})'.format(string1, string2))

Python 3 Beginner - Iterating Triangle

I am going through a past test and the output of the code is this:
Enter the height:
5
5
44
333
2222
11111
I have to write down the code - so far I know how to make a normal triangle with:
for i in range(5):
print('*'*i)
*
**
***
****
My main question is how do I get the body if the triangle to iterate over the numbers?
So what would the code of the first triangle be?
Help would be appreciated:)
The code for this is virtually the same, you just need to change the number of times you print each character, and change the * that you are printing to a number.
for i in range(5):
print(str(5-i) * (i+1))
This generates:
5
44
333
2222
11111
To make it right aligned, like in your example, just use string multiplication on a space character.
for i in range(5):
print(' ' * (4-i) + str(5-i) * (i+1))
This will get you:
5
44
333
2222
11111
You can use str:
for i in range(5):
print(str(i)*i)
Some of the other answers have been essentially correct, but this one right justifies your triangle like the original output.
def print_triangle(rows):
for i in range(rows + 1):
print((str(rows + 1-i)*i).rjust(rows))
height = 5
for i in range(height, 0, -1):
empty_chars = ' ' * (i - 1)
filler_chars = str(i) * (height - i + 1)
print('{}{}'.format(empty_chars, filler_chars))
Formatted string & spacing with an external array and a negated variable.
def height(num):
rangenum=range(num+1)
for i in rangenum:
print(("%"+str(num)+"s")%(i*str(rangenum[-i])))
print("%(spacing as a number)s"%(a string))
returns
(spacing as a number)-(a string)
example:
print("%10s"%"this")
returns:
" this"
side note:
%-(a number)s
is right justified.
(though python tries to cut down the millions of ways to do the same thing, there still are thousands)
https://docs.python.org/2/tutorial/inputoutput.html

Categories