#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    7
    Rep Power
    0

    Question 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 24th, 2003 at 12:24 AM.
  2. #2
  3. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69

    global statement


    Yo Sparky can I see your code it might hey me understand what you want to do.

    I'd look at the exec() as the answer to the second but again without knowing that your code looks like I couldn't be more spacific, also, a lil unsure why your using eval()/ecec() anyway.

    and finally yes functions can make changes to global variables..something like this.

    Code:
    #setup variable named var 
    var = 'some value'
    
    #if nothing is passed to chnage new = new value.
    def change(new = 'new value'):
    	#set local variable to global
    	global var
    	var = new
    	return var
    
    #chnage value	
    change()
    
    #print var variable
    print var
    need more info k ..

    Have fun,
    Mark
  4. #3
  5. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    7
    Rep Power
    0
    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(((n-i+1)*parts[0][i-1])/(i-1))
            parts[1].append(eq[0] + "**" + str(n-i))
            parts[2].append(eq[1] + "**" + str(i-1))
        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("[a-zA-Z]", current)
                holder[b].append(letter[0] + "^" + str(n-i+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 x-values
        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 04:20 AM.
  6. #4
  7. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69

    Maths :)


    Hey, there wasn't anything wrong with the way you discribed it, a lil over complicated maybe but it was more the fact that i'd just got up. Still quite compilcated, Im sure it makes perfect sence.. just not to me lol.

    Anyway I'm not sure if im understanding you so lets give this a try your first point seems like you wana do something like this..

    Code:
    def line(list = []):
    	for num in xrange(len(list)):
    		print list[num] + 'is number:' + num
    This code shows how to print the contents of the list/array and the number it is in the list/array (starting at 0 but this is easy to fix).

    but looking at your code you seem to want to see which occurs the most and print them out in order :S grrrr i've comfused myself to hell, could we try this again. In simple terms without all the maths terms tell me what you want each functiont to do

    i.e if you want to see which value occures most in a list then say.. well that and ill try my best to help

    I got a D in maths and this stuff seems way way advanced, hard to get my head around.

    Sorry, guess I must sound like the newbie .

    Take care.

    Have fun,
    Mark
  8. #5
  9. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    7
    Rep Power
    0
    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 ([a-z]) 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 math-signs 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 Number-Letter to Letter-Number, 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 Letter-Number. 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!/(n-j)!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("[a-z]", 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
  10. #6
  11. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69

    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.
  12. #7
  13. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    7
    Rep Power
    0
    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 06:40 PM.
  14. #8
  15. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69

    Talking 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.
  16. #9
  17. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2003
    Posts
    7
    Rep Power
    0
    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("[a-zA-Z]")
    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((n-i) * 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(n-i+1)) # does the powers
            parts[2].append(eq[1] + "**" + str(i-1))
        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 (n-i+1) != 1:
                        holder[b].append((letter[0]) + "^" + str(n-i+1)) 
                    elif (n-i+1) == 1: # so there isn't x^1
                        holder[b].append(letter[0])
                    if f("[a-z]\^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 quick-and-simple 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 03:05 PM.
  18. #10
  19. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69

    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.

    Code:
    if i != 0: var = i
    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...-in-funcs.html

    Have fun fox,

    Take care,
    Mark.

IMN logo majestic logo threadwatch logo seochat tools logo