JNB Lab Solutions

3.6. JNB Lab Solutions#

Exercise 1.1

def evaluate_polynomial(coefficients, x) :
    assert len(coefficients) > 0
    if len(coefficients) == 1 : 
        return coefficients[0]
    else :
        return evaluate_polynomial(coefficients[:-1],x) + coefficients[-1] * x**len(coefficients)

Exercise 1.2

Treating the product of an empty list as 1 makes the recursion work. If the base case returned 0, then all other products would be 0.

Exercise 2.1

def evaluate_polynomial(coefficients, x) :
    assert len(coefficients) > 0
    return sum([coefficients[i] * x**i for i in range(len(coefficients))])

Exercise 2.2

\(\mathbb{Z}_{n+1}\) includes \(n\) itself, which \(\mathbb{Z}_n\) doesn’t. Moreover, \(n\) is a valid index to the list of coefficients. Mathematically, \(\mathbb{Z}_{n+1}\) is equivalent to range(len(coefficients)) in code, since the length of the list (which is also the number of coefficients) is one more than the degree of the polynomial.

Exercise 3.1

def evaluate_polynomial(coefficients, x) :
    result = 0
    for i in reversed(range(len(coefficients))) :
        result = coefficients[i] + x * result
    return result

Exercise 3.2

def evaluate_polynomial(coefficients, x) :
    assert len(coefficients) > 0
    if len(coefficients == 1) :
        return coefficients[0]
    else :
        return coefficients[0] + x * evaluate_polynomial(coefficients[1:], x)

Exercise 3.3

\(n-1\).

Exercise 4.1

def differentiate_polynomial(coefficients) :
    return [coefficients[i]/i for i in range(1,len(coefficients))]

Exercise 4.2

def integrate_polynomial_indef(coefficients) :
    # 17.0 is an arbitrary constant. Happy Cicada Brood XIII Year, 2024
    return [17.0] + [coefficients[i]/(i+1) for i in range(len(coefficients))]

Exercise 4.3

def integrate_polynomial_def(coefficients, a, b) :
    antideriv = integrate_polynomial_indef(coefficients)
    return evaluate_polynomial(antideriv, b) - evaluate_polynomial(antideriv, a)

Exercise 5.1

class Polynomial :
    def __init__(self, coeffs) :
        self.coefficients = coeffs.copy()
        
    def __call__(self, x) :
        result = 0
        x_pow = 1 # This is always x^i; it's the power of x for the next iterations
        for i in range(len(self.coefficients)) :
            result += self.coefficients[i] * x_pow
            x_pow *= x
        return result
    
    def degree(self) :
        return len(self.coefficients)-1

    # Another special function, this one makes a nice string representation
    # of the object
    def __str__(self) :
        if len(self.coefficients) == 0 :
            return '0.0'
        else :
            to_return = str(self.coefficients[0]) 
            for i in range(1, len(self.coefficients)) :
                to_return += ' + ' + str(self.coefficients[i]) + 'x'
                if i > 1 :
                    to_return += '^' + str(i)
            return to_return
            
    
    # The next three are for the exercises
    def differentiate(self) :
        return Polynomial([self.coefficients[i]/i for i in range(1,len(self.coefficients))])    
    
    def integrate_indef(self) :
        return Polynomial([17.0] + [self.coefficients[i]/(i+1) for i in range(len(selfcoefficients))])
    
    def integrate_def(self, a, b) :
        antideriv = self.integrate_indef()
        return antideriv(b) - antiderive(a)