3

As an input, I have a list of nonnegative whole numbers which are supposed to be the coefficients of a polynomial. But I also want to evaluate the polynomial for a certain number x.

For example:

If we have L=[2,3,1] as an input and x=42 we get 2x^2+3x+1=3655 What I want is for example:

>>>p=polynomial([2,3,1])
>>>p(O)
1 
>>>p(42)
>>>3655

I guess I have to make use of the lambda function somehow, and I do know how it works for two variables on a given function, but in this case the function depends on my input.

def polynomial(coef):
coef=coef[::-1]
for i in range(len(coef)):
    p=lambda x: coef[i]*x**i
    p+=p
return lambda x: p

This is of course absolute nonsense, as I cannot add up one lambda function to another, but this is what my approaching "intuition" is.

Some hints are much appreciated.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Tesla
  • 141
  • 8
  • You should use [`sympy`](http://docs.sympy.org/latest/tutorial/intro.html) – Moses Koledoye Jan 11 '17 at 10:55
  • "I guess I have to make use of the lambda function somehow" <- Why do you guess that? `lambda` functions can't do anything that regular named functions don't already do. – Mark Dickinson Jan 11 '17 at 10:57
  • 1
    Is the usage of lambda mandatory? You could easily write a function returing a function (more precisely a closure) that does exactly what you want. – VPfB Jan 11 '17 at 10:57
  • No it is not mandatory, I just recently learned what lambda functions are, so it just came up my mind.. – Tesla Jan 11 '17 at 10:59
  • BTW, is `coef[i]` supposed to be the coefficient of `x**i` or of `x**(degree - i)`? Your example suggests the latter, but the code suggests the former. (Maybe you meant `coef = coef[::-1]` rather than `coef = coef[::1]`?) – Mark Dickinson Jan 11 '17 at 11:03
  • @MarkDickinson thanks, typo. coef[::-1][i] is the coefficient of x**i. – Tesla Jan 11 '17 at 11:06
  • Related, if not duplicate: http://stackoverflow.com/q/19837486/1639625 – tobias_k Jan 11 '17 at 11:26

4 Answers4

4

The most obvious pythonic solution (using a closure - with a lambda or (preferably) a named inner function) has already been posted, but for the sake of completeness I'll add the other pythonic solution - the OO version using a custom callable class:

class Polynomial(object):
    def __init__(self, coef):
        self.coef = coef

    def __call__(self, x):
        n = len(self.coef) - 1
        return sum(c * x ** (n - i) for (i, c) in enumerate(self.coef))

p = Polynomial([2,3,1])
print p(0)
print p(42)
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • +1 for the completeness. Besides, this solution is scalable, in the sense that more complex behaviour can be added later, while closures are alright because the case is pretty simple. – Right leg Jan 11 '17 at 11:43
2

Simple Python:

def make_poly(coefs):
    def poly(x):
        result = 0
        for c in coefs:
            result = result * x + c
        return result
    return poly

p = make_poly([2,3,1])

print(p(0))
print(p(42))

EDIT: code modified as suggested by Mark Dickinson in the comments

VPfB
  • 14,927
  • 6
  • 41
  • 75
  • 1
    Don't hesitate to leave a comment before downvoting. – VPfB Jan 11 '17 at 11:08
  • 1
    Thanks, but not exactly what I was looking for. What I was looking for is a function, where the input is a list before I am being asked to evaluate the polynomial at a point x, as I wrote above. Btw, wasn't me downvoting. – Tesla Jan 11 '17 at 11:18
  • 1
    @Tesla I think my code is doing just that. `make_poly` here is called `polynomial` in the example in your question. It takes a list as its input. It returns a function that evaulates the polynomial. It even gives the correct aswers p(0) = 1 and p(42) = 3655 :-) Am I still overlooking something? – VPfB Jan 11 '17 at 11:26
  • @VPfB Sorry about that, I was a bit in a hurry and forgot to comment (I even upvoted your comment!). To me, it's not a good answer to this question, because it does not use `lambda` functions, while the title mentions them (as well as the question itself), and OP even tagged `lambda`. I would not say however that this is a bad solution; I would tend to prefer simple functions over complicated lambda expressions. However, your post puts this as if it was an answer to the question, although it is not (IMO). Add some text explaining you propose an other approach, and I'll upvote ;) – Right leg Jan 11 '17 at 11:31
  • 1
    @Tesla this is actually one of the two idiomatic solutions (the other one being using a custom callable) – bruno desthuilliers Jan 11 '17 at 11:34
  • 1
    @Rightleg the fact the OP mentionned lambdas doesn't mean the pythonic solution would be to use a lambda. – bruno desthuilliers Jan 11 '17 at 11:35
  • @brunodesthuilliers Although I agree with you, no mention to pythonicity was made – Right leg Jan 11 '17 at 11:35
  • 1
    @Rightleg this doesn't mean we shouldn't care about pythonicity - part of the point of SO is to promote good practices, isn't it ? – bruno desthuilliers Jan 11 '17 at 11:40
  • Sorry I was mistaking. Still have the problem that I get an error just like I do on the other suggested codes. Need to figure out why. – Tesla Jan 11 '17 at 11:41
  • @Tesla if you're using Python3 you have to replace `print whatever` statements with `print(whatever)` function calls. – bruno desthuilliers Jan 11 '17 at 11:45
  • @brunodesthuilliers I couldn't agree more. – Right leg Jan 11 '17 at 11:48
  • 2
    You could simplify the evaluation a bit by consuming the coefficients in the original order and using Horner's rule: `for c in coefs: result = result * x + c`. – Mark Dickinson Jan 11 '17 at 11:50
  • That was not the issue, but I figured it out now, too embarrassing to point out. – Tesla Jan 11 '17 at 12:02
1

The following lambda function evaluates a polynomial function, input as a coeff list of coefficients, in a given x:

from functools import reduce

lambda coeff, x: reduce(lambda a, b: a*x + b, coeff)

It seems that you want to generate these polynomial functions. You can still do it with this method:

def generate_polynomial(coeff):
    return lambda x: (lambda y: reduce(lambda a, b: a*y + b, coeff))(x)

>>> p = generate_polynomial([20,0,17])
>>> p(10)
2017

This is merely based on Horner's algorithm.

Besides, if you want to use exclusively lambda and no built-in functions, you can also emulate reduce with lambda functions. You might want to give a look at Python - Removing duplicates in list only by using filter and lambda and Removing duplicates using only lambda functions, showing how to get rid of the filter function.

Community
  • 1
  • 1
Right leg
  • 16,080
  • 7
  • 48
  • 81
  • Thank you. What does the error ". at 0x7faf9bab6378>" mean, that is what I get if trying your code. – Tesla Jan 11 '17 at 11:24
  • @Tesla Could you please give more feedback? What you commented is just an address, it lacks the reason why it fails... Besides, it works perfectly on my Python 3.4, it might be a problem with Python 2? – Right leg Jan 11 '17 at 11:26
  • I use Python 3.4 as well, the problem occurs on the other codes as well.. Where can I check the reason? Sorry I am not too familiar with it yet. – Tesla Jan 11 '17 at 11:41
  • @Tesla Now that I read more closely what you commented, it appears that this is not an error, but just the address of the function you generated. Did you do something like `p = generate_polynomial(...)`, then `print p`? If so, `p` is a function, so you will want to evaluate it on a value to get a printable result. Try with `print(0)` for instance. – Right leg Jan 11 '17 at 11:46
  • That was not the issue, I did something terrible, but I fixed it now hehe. – Tesla Jan 11 '17 at 12:02
  • @Tesla I'm afraid to ask what terrible thing you did, but I'm pretty curious too... – Right leg Jan 11 '17 at 12:03
  • I just put >>>generate_polynomial([20,0,17]) instead of >>>p=generate_polynomial([20,0,17]). – Tesla Jan 11 '17 at 12:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/132907/discussion-between-right-leg-and-tesla). – Right leg Jan 11 '17 at 12:05
1

You can do it using lambda:

def polynomial(coef):
  n = len(coef) - 1
  return lambda x : sum([c * x ** (n - i) for (i, c) in enumerate(coef)])

Lambda isn't necessary however, you can define another function inside the polynomial function like so:

def polynomial(coef):
  def f(x):
    n = len(coef) - 1
    return sum([c * x ** (n - i) for (i, c) in enumerate(coef)])
  return f

Edit: Previously input was tied to 3 coefficients

  • The input is a list of arbitrary length though. Also, the list is the only input of the main function. – Tesla Jan 11 '17 at 11:08