# coding: utf-8
# ## Exercise for the course [Python for MATLAB users](http://sese.nu/python-for-matlab-users-ht15/), by Olivier Verdier
# In[ ]:
import numpy as np
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
# The goal of this exercise is to define a class `Polynomial`, which behaves like a polynomial. For instance
#
# ```
# p = Polynomial([1.,2.])
# ```
# should represent the polynomial $1 + 2X$.
#
# The object `p` should be callable
#
# ```
# p(.2) # value of the polynomial at 0.2
# ```
#
# One should be able to add, multiply two polynomials.
#
# You will be guided through by the following detailed tasks.
# In[ ]:
class Polynomial:
pass # implement here
# Implement the `__init__` method, which stores a list of coefficients. Use the `array` function to copy the list, or array, of coefficiente which is passed. Store the coefficients in a property `coeffs`.
# In[ ]:
a = np.array([1.,2.])
p = Polynomial(a)
assert not p.coeffs is a
# Implement the method `__getitem__`, which allows to give acess to the coefficients. An out of bound index should return zero, like in mathematics.
# In[ ]:
assert np.allclose(p[0], 1.)
assert np.allclose(p[3], 0.)
# Implement the method `__add__`, which adds two polynomials.
# In[ ]:
q = Polynomial([1.,2.,3])
z = p+q
assert np.allclose((p+q)[0], 2.)
assert np.allclose((p+q)[2], 3.)
# Implement the method `__repr__`, which returns a string such as `Polynomial(array([1.,2.]))`.
#
# **Hint**: use the function `repr` on the coefficient array of the polynomial.
# In[ ]:
assert repr(p) == "Polynomial(array([ 1., 2.]))"
# Implement `differentiate` which returns the derivative of the polynomial.
# In[ ]:
assert np.allclose(p.differentiate().coeffs, array([2.]))
# Implement the method `__call__`, which evaluates the polynomial at a given point.
#
# **Bonus** if the method works with array inputs, like `p(array([1.,2.,3.])`.
#
# **Hint**: Use the functions `reduce` and, possibly, the function `reversed`.
# In[ ]:
get_ipython().run_line_magic('pinfo', 'reduce')
# In[ ]:
assert allclose(p(0.), 1.)