June 23rd, 2003, 10:31 PM

a few newbie questions
hi. i've been hacking away at python for a few days, and i've run into a few problems where something stumped me and i couldn't figure out how to do it or what command in python to use. hope you guys can help here's a list of what i need help with
1. when writing a summation function, i couldn't figure out how to replace the x with the current incrementing number in the for loop. using the re module didn't help much, since it doesn't let you replace a matched string with a variable. i need to replace the Xs in an equation with the current number of the for loop. that's how summation works but, this also leads to another problem...
2. the eval() function confuses me. for example, if i tell it to evaluate "2**2", it won't do it. i'm pretty sure it's because it's in string format, but i don't know how to make it turn into a doable math equation.
3. how would someone recommend i combine like terms in an algebra equation? an idea i had was to swap (for example) 4x to x4, organize alphabetically, then go through the list, lump the ones that start with the same letters together, and then go through the process of pulling off the letters, doing the math, and putting the letters back on. but i can't figure out how to swap 4x into x4. another idea i had was to somehow keep track of what variables had been encountered while looping through the equation, and put them all on the subarray that has like terms with, but then i realized that i had no clue how to code this
aaand the last pressing question i have right now (i have a lot ) is how can i modify a global variable with a function? it just stays the same when i try to change it. is this the purpose of a global variable, and it's not meant to be changed?
thanks for any help
edit: one problem solved. i had no idea python had a count() function. and i'd been doing things the contrived, errorfilled way.
Last edited by Sparky the Fox; June 23rd, 2003 at 11:24 PM.
June 24th, 2003, 02:31 AM

June 24th, 2003, 03:07 AM

hi. i couldn't really be more specific with my other questions, since i haven't tried writing the code. i did manage to solve the mode thing, though, which i attached if you want to pick at it and tell me what i need to improve
and what more info do you need?? i thought i was pretty clear in my questions
Code:
def mode(numbers):
b = 0
highs = ([], []) #number, count
numbers.sort()
while b < (len(numbers)):
c = numbers.count(numbers[b])
if c > 1:
highs[0].append(numbers[b])
highs[1].append(c)
b += c
b = ([0],[0]) #number, count
for c in range(len(highs[0])):
if highs[1][c] > b[1][0]:
b[1][0] = highs[1][c]
b[0][0] = highs[0][c]
continue
if highs[1][c] == b[1][0]:
b[0].append(highs[0][c])
if b[0][0] == '':
b[0][0] = "none"
return b # returns in the format ([modes], [highest # of occurences])
edit: oh! and something that's been driving me nuts for the past five hours or so (yes, im that pathetic)... i've been trying to code a formula to do the binomial theorem. i'm doing a math module to get my homework done faster, which explains all of this nerdy math stuff anyway, i can get it to the point where i have the nj coefficients and the x and y variables in parallel arrays (i'm a big fan of those ). what i've been struggling like heck to do, though, is complete the formula. maybe it's just late, and i'm not able to think clearly, but one of the things i've not been able to do is extract the letter variable from the x or y array (depending on which one has a variable in the first place), and put it into a separate array so i can evaluate the powers of just the coefficients. findall() (to extract the letters) from the re module has decided it hates me, and it'll only do what i want it to in the interactive window in pythonwin. i take its results into an array, and try to access element [0]. works fine in the window, generates dimension errors in the program. i was observant enough to use findall on a str()converted array element instead of just the array element directly (it complained about that too). anyway, i'll elaborate more tomorrow, and here's my current struggling work on it
Code:
def multoutbinomial(eq, n):
i, holder = 1, (["empty"],[0],[0]) # no letter on the nj coefficient.
eq = cleaner(eq,0)
eq = eq.split(" ")
parts = [0],[0],[0],[0] # nj coefficient, a, b, multiplied result
for i in range(1,(n+1)): # put the things into arrays
if i == 1:
parts[0].append(i)
else:
parts[0].append(((ni+1)*parts[0][i1])/(i1))
parts[1].append(eq[0] + "**" + str(ni))
parts[2].append(eq[1] + "**" + str(i1))
print parts # only for testing!
for b in range(1,3): # store letters in parallel thingy
for i in range(1,n+1):
current = str(parts[b][i])
letter = re.findall("[azAZ]", current)
holder[b].append(letter[0] + "^" + str(ni+1) or "")
multoutbinomial("2x  3", 6)
note: it only works up until the store letters comment. comment that out if you want to see an example of the output.
sorry about the babbling... i just have lots of questions and can't seem to stop leaping off the tangent cliff
cleaner():
Code:
def cleaner(eq, split = 1): # breaks the equation into coefficients and xvalues
eq = re.sub("\s\\s", " ", eq)
eq = re.sub("\s\+\s", " ", eq)
if split == 1:
eq = eq.split(" = ")
return eq
Last edited by Sparky the Fox; June 24th, 2003 at 03:20 AM.
June 24th, 2003, 01:12 PM

June 24th, 2003, 01:54 PM

hi thanks for trying to help even if my math babble is a bit too much here are the things i want to know how to do, only in less dorky
terms
1 & 2. in a summation function, you have three variables. a starting number k (most of the times 0 or 1), an ending number n, and an equation.
what you do, is you replace the x in the equation with the k, and add it to the total sum so far. you increment k by one, and continue substituting and adding to the total until k = n. in cases where n is in infinity, only a general form can be found, and i didn't really expect to be able to write code to do this, so we don't hafta worry about that aspect what i was unable to do, is, say for example the equation was 2x**2, replace the x with whatever k is now, and then evaluate the new equation 2(k)**2. my first idea was to use re.sub() to replace the letter value ([az]) with the current k, which is incrementing by one each time the loop runs. re.sub() doesn't like dynamic variables, even if they stay the same when it's actually doing the substituting. also, even if i did manage to replace the variable with the current step number, eval() would not let me evaluate the equation. if the equation was currently 2(5)**2, it would say "int object is not callable", and i have no idea what format eval needs, or how to convert it to standard int and mathsigns format.
3. combining like terms is changing "3x + 2 + 5x  3" into "8x  1". it's just taking all similar terms, and adding or subtracting them into the most simplified form. this is necessary for some of my algebra modules, which assume the equation is already in the form ax + b = c. what i was unable to do, is come up with an idea for how to do this that worked. one idea i had, was to swap each NumberLetter to LetterNumber, so the terms could be grouped by like terms, and even alphabetically, which is a plus. the code would then temporarily store the letter of all like terms, combine the coefficients (number part), and then replace the letter. but i can't even figure out how to swap it into LetterNumber. the subarray idea i babbled about would turn into spaghetti code if i tried to impliment it, so i'm not even going to try it
4. the binomial theorem junk. it's where you have a binomial, like (3x + 2) (binomial means two terms), and you raise the whole thing to a power, like (3x + 2)^6. there's a theorem that tells you how the result will turn out without having to multiply 3x + 2 by itself 6 times. it's kind of nasty looking, but it consists of three parts for each term that arises. the default form is (x + y)^n an nj coefficient, which i call that because it looks like an n on top of a j inside big parentheses (it's just n!/(nj)!j!); an x variable (which is the x aspect of each term, including its power); and a y variable (which is the y aspect of each term). the x variable can either be a number and a letter, or just an x. the y variable can be a number and a letter, just a letter, or just a number. so far, my program calculates the nj coefficient, and the x and y variables, and stores them in parallel arrays, each element corresponding to a term of the solution. the problem is, that the x or y variables still look like "x**6" or "(2x)**5" or some variance of that. i can't do anything with this, so to simplify it, i need to separate (2)**5 and x**5 for each variable. my current idea is to store these variables that were pulled off on another parallel array for easy access when i need to tack them back on for the final equation. only i can't even get the x off. i've been trying to use array = re.findall("[az]", string), which works exactly as expected in the window, but in my program, i can't access element[0], which contains the matched part. it says that it's out of the index range, which is total bullcrap because it only has one element, and that element IS [0]. i can print the array and see for myself that the array is ['x']. this is my current major hindrance. i'm sure if i can get this re.findall() bug out of the way, i can finish my program.
if you need more clarification i'll be happy to elaborate more
thanks for helping also, i got the mode thing figured out, and the script works fine, if that's what you were talking about in your post
June 24th, 2003, 04:34 PM

I/C heheh
Ok I'm not gonna pretend to fully understand all of what you just said but I think I know what you need to do.. lets just work on the first part for a bit.
The exec function executes a Python statment in the form of a string (like perls eval function) i.e
Code:
exec("var = 2 * 2")
should set the value of var to 4 check out the maths skills.
Anyway what you need to do is..
1. create a string which consists of k and the equasion
2. use exec to assign the new value of k based on your previous equasion.
Hope this makes sence because im just kinda riping as i go but have a quick hack at this whenever and see if you can get it working for you, if not i'll have a go but I might need some help because im not 100% on the consept.
What it seems like is,
Define a function which takes a value, and an equasion. Contructs a string version of the equasion with appropriate values using string formatting then run the equasion and return an answer so you can do whatever comes next with it.
right?
Have Fun,
Mark.
June 24th, 2003, 05:12 PM

i got the summation thing figured out after hacking away at it for 30 minutes or so... here's what i ended up doing
Code:
import re
def summation(eq="x**2",n=2,k=0):
sum = 0
if re.findall("\.?\d+", eq):
eq = re.sub("", "(", eq)
eq = re.sub("\*\*", ")**", eq)
eq = re.sub(alpha, "x", eq)
while k <= n:
x = k
sum += eval(eq)
k += 1
return(sum)
i got the binomial thing working for equations in the form ax + C (c is a number), but not x + y. im working on that now, though i changed my algorithm for finding the nj coefficient (a row of pascal's triangle) to a separate program. i can post that too if you're curious
thanks for helping what's the difference between exec() and eval()?
edit: ah, the source of my problem with x + y forms. when y is a number, it puts the term array elements in the correct order, but when y is a string, it *reverses* the order for some reason. for example, instead of being [1, "y", "y^2", "y^3"] like it should be, it'll be ["y^3", "y^2", "y^1", 1] for no apparent reason. ideas?
Last edited by Sparky the Fox; June 24th, 2003 at 05:40 PM.
June 25th, 2003, 02:58 AM

sqeet
Hey Fox, glad you got it working. the differance between eval and exec is, eval evaluates a Python expression i.e. 1 + 4 and ecec executes a Python statment i.e. 'print 1 + 4'.
check thic out Fox, seems to be dojgn that you wanted, binomial stuff as I sasid, I'm no maths wiz lol.
Yeah post ur code i'd love to see it.
Well I hope some of this has helped, even though you kinda did it all on your own
Have a good day,
Mark.
June 25th, 2003, 03:45 AM

i did get it working, only now it doesn't support expansion of the form (ax^b + cy^d)^n, just standard (ax + by)^n, and the output's still kinda ugly. 1x and stuff still hanging around. i haven't had any luck finding a more compact algorithm, so it looks pretty bloated and nasty in its current state. there are lots of comments to aid in reading, and to keep my sanity
Code:
from re import sub, findall
from math import sqrt
global alpha; alpha = re.compile("[azAZ]")
global s; s = re.sub
global f; f = re.findall
def cleaner(eq, splittype = "equal"):
""" Separates an equation into array elements based on splittype """
eq = s("\s\\s", " ", eq)
eq = s("\s\+\s", " ", eq)
if splittype == "equal":
eq = eq.split(" = ")
if splittype == "space":
eq = eq.split()
else:
eq = eq.split(", ")
return eq
def pascalsTri(n):
""" Finds the row of Pascal's Triangle that corresponds
to the nth term of a binomial expansion """
init = [1]
for i in range(0,n):
init.append((ni) * init[i] / (i+1))
return init
def multoutbinomial(eq="5x + 3y", n=5): # add support for (ax^b + cy^d)^n
""" Multiplies out a binomial of the form (ax + by) to the nth term. """
i, holder, sol = 1, (["empty"],[0],[0]), "" # no letter in the nj coefficient.
eq = cleaner(eq,"space")
parts = [0],[0],[0],[0] # nj coefficient, a, b, multiplied result
pascal = pascalsTri(n)
for i in pascal: parts[0].append(i) # puts the nj coefficients into an array
for i in range(1,n+2): # put the things into arrays & do x and y
parts[1].append(eq[0] + "**" + str(ni+1)) # does the powers
parts[2].append(eq[1] + "**" + str(i1))
for b in range(1,3): # store letters in parallel truple
for i in range(1,n+2): # sort through each element
current = str(parts[b][i])
if f(alpha, current): # is the current element a letter?
letter = f(alpha, current) # find the letter
if (ni+1) != 1:
holder[b].append((letter[0]) + "^" + str(ni+1))
elif (ni+1) == 1: # so there isn't x^1
holder[b].append(letter[0])
if f("[az]\^0", str(holder[b][1])):
holder[b][1] = 0 # removes x^0 to maintain intended holder[] functionality
current = s(alpha, "", current) # removes letter from coefficient
else:
holder[b].append(0) # if there is no letter, put a 0 instead
if f("", current):
current = s("", "(", current) # (a)^n is not the same as a^n
current = s("\*\*", ")**", current)
if f("^\*\*\d+", current) or f("^\(\)\*\*\d+", current):
current = s("(?:\W*)\*\*", "1**", current) # fixed the ()**n weirdness
parts[b][i] = current
for i in range(1,n+1): # multiply the coefficients
parts[3].append(parts[0][i] * eval(parts[1][i]) * eval(parts[2][i]))
if holder[2][1] != 0: # unreverses the secondary letter array
holder[2].reverse(); holder[2].pop(); holder[2].insert(0, 0)
for i in range(1,n+1): # puts everything together, cosmetics
current = str(parts[3][i]) # go through each element of the solution array
if f("", current) and i != 1: # makes "a" "  a", only if not [1]
current = s("", " ", current)
elif i != 1: # makes "a" into " + a", only if not [1]
current = s("^", "+ ", current)
for b in range(1,3):
if holder[b][i] != 0: # does the corresponding letter array element have a letter?
current += str(holder[b][i])
sol += " " + current
current = str(eval(parts[2][1])) # evaluate the last coefficient
if f("", current):
current = s("", "  ", current)
else:
current = " + " + current # clean up this last coefficient
sol += current
if holder[2][1] != 0: sol += holder[2][1] # tack on the last variable, if there is one
return sol
i apologize for its atrociousness. it solves pretty quickly on my cpu, though. takes 0.017 cpu seconds. at least i think that's fast :\ i don't know much about how fast a program should be. the things that took the longest were the re.sub() and re.findall() calls, but i don't know how to make the algorithm without implicitly matching and substituting parts of strings :\
also, is there a way to do a quickandsimple if statement? in perl, for example, i was able to do things like $var = $i if $i != 0; but i haven't seen a similar ability in python. if there is such an option, please post an example
thanks for being patient with my tangents
Last edited by Sparky the Fox; June 25th, 2003 at 02:05 PM.
June 25th, 2003, 03:31 PM

Optimized
Hey, it's a hell of alot longer than i thought it would be but . to answer you questions. Thats an ok runtime, if it was around half a second i'd worry but no thats fine. you could always use this if statment.
Also there are several built in functions you might be interested in.
Code:
string_or_variable.replace('string to be replaces', 'with').
and
Code:
string_or_variable.find('string to be found')
which should work roughly the same as the re modules sub and findall, the main differance being you can't use regexp's in them but they are faster..
You can get a list of the builtin functions at http://www.python.org/doc/current/li...infuncs.html
Have fun fox,
Take care,
Mark.