From 204e54e4396be1d03b5dcc1465a253434f509db9 Mon Sep 17 00:00:00 2001 From: Emmanuel Murairi Date: Thu, 6 Oct 2022 10:24:02 +0400 Subject: [PATCH 1/6] implement function to handle polynomial operations --- maths/polynomials/__init__.py | 0 .../single_indeterminate_operations.py | 179 ++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 maths/polynomials/__init__.py create mode 100644 maths/polynomials/single_indeterminate_operations.py diff --git a/maths/polynomials/__init__.py b/maths/polynomials/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/maths/polynomials/single_indeterminate_operations.py b/maths/polynomials/single_indeterminate_operations.py new file mode 100644 index 000000000000..bd1b59a983c6 --- /dev/null +++ b/maths/polynomials/single_indeterminate_operations.py @@ -0,0 +1,179 @@ +""" +Operations on single indeterminate polynomials + +Reference: https://en.wikipedia.org/wiki/Polynomial + +""" + + +class Polynomial: + def __init__(self, degree: int, coefficients: list[int]): + """ + The coeffients should be in order of degree, from smallest to largest. + >>> p = Polynomial(2, [1, 2, 3]) + >>> p = Polynomial(2, [1, 2, 3, 4]) + Traceback (most recent call last): + ... + ValueError: The number of coefficients should be equal to the degree + 1. + + """ + if len(coefficients) != degree + 1: + raise ValueError( + "The number of coefficients should be equal to the degree + 1." + ) + + self.coefficients = coefficients + self.degree = degree + + def __add__(self, polynomial_2): + """ + Polynomial addition + >>> p = Polynomial(2, [1, 2, 3]) + >>> q = Polynomial(2, [1, 2, 3]) + >>> p + q + 6x^2 + 4x + 2 + """ + + if self.degree > polynomial_2.degree: + coefficients = self.coefficients.copy() + for i in range(polynomial_2.degree + 1): + coefficients[i] += polynomial_2.coefficients[i] + return Polynomial(self.degree, coefficients) + else: + coefficients = polynomial_2.coefficients.copy() + for i in range(self.degree + 1): + coefficients[i] += self.coefficients[i] + return Polynomial(polynomial_2.degree, coefficients) + + def __sub__(self, polynomial_2): + """ + Polynomial subtraction + >>> p = Polynomial(2, [1, 2, 4]) + >>> q = Polynomial(2, [1, 2, 3]) + >>> p - q + 1x^2 + """ + return self + polynomial_2 * Polynomial(0, [-1]) + + def __neg__(self): + """ + Polynomial negation + >>> p = Polynomial(2, [1, 2, 3]) + >>> -p + - 3x^2 - 2x - 1 + """ + return Polynomial(self.degree, [-c for c in self.coefficients]) + + def __mul__(self, polynomial_2): + """ + Polynomial multiplication + >>> p = Polynomial(2, [1, 2, 3]) + >>> q = Polynomial(2, [1, 2, 3]) + >>> p * q + 9x^4 + 12x^3 + 10x^2 + 4x + 1 + """ + coefficients = [0] * (self.degree + polynomial_2.degree + 1) + for i in range(self.degree + 1): + for j in range(polynomial_2.degree + 1): + coefficients[i + j] += ( + self.coefficients[i] * polynomial_2.coefficients[j] + ) + + return Polynomial(self.degree + polynomial_2.degree, coefficients) + + def evaluate(self, x): + """ + Evaluates the polynomial at x. + >>> p = Polynomial(2, [1, 2, 3]) + >>> p.evaluate(2) + 17 + """ + result = 0 + for i in range(self.degree + 1): + result += self.coefficients[i] * (x**i) + return result + + def __str__(self) -> str: + """ + >>> p = Polynomial(2, [1, 2, 3]) + >>> print(p) + 3x^2 + 2x + 1 + """ + polynomial = "" + for i in range(self.degree, -1, -1): + if self.coefficients[i] == 0: + continue + elif self.coefficients[i] > 0: + if polynomial: + polynomial += " + " + else: + polynomial += " - " + + if i == 0: + polynomial += str(abs(self.coefficients[i])) + elif i == 1: + polynomial += str(abs(self.coefficients[i])) + "x" + else: + polynomial += str(abs(self.coefficients[i])) + "x^" + str(i) + + return polynomial + + def __repr__(self) -> str: + """ + >>> p = Polynomial(2, [1, 2, 3]) + >>> p + 3x^2 + 2x + 1 + """ + return self.__str__() + + def derivative(self): + """ + Returns the derivative of the polynomial. + >>> p = Polynomial(2, [1, 2, 3]) + >>> p.derivative() + 6x + 2 + """ + coefficients = [0] * self.degree + for i in range(self.degree): + coefficients[i] = self.coefficients[i + 1] * (i + 1) + return Polynomial(self.degree - 1, coefficients) + + def integral(self, constant=0): + """ + Returns the integral of the polynomial. + >>> p = Polynomial(2, [1, 2, 3]) + >>> p.integral() + 1.0x^3 + 1.0x^2 + 1.0x + """ + coefficients = [0] * (self.degree + 2) + coefficients[0] = constant + for i in range(self.degree + 1): + coefficients[i + 1] = self.coefficients[i] / (i + 1) + return Polynomial(self.degree + 1, coefficients) + + def __eq__(self, polynomial_2): + """ + Checks if two polynomials are equal. + >>> p = Polynomial(2, [1, 2, 3]) + >>> q = Polynomial(2, [1, 2, 3]) + >>> p == q + True + """ + if self.degree != polynomial_2.degree: + return False + + for i in range(self.degree + 1): + if self.coefficients[i] != polynomial_2.coefficients[i]: + return False + + return True + + def __ne__(self, polynomial_2): + """ + Checks if two polynomials are not equal. + >>> p = Polynomial(2, [1, 2, 3]) + >>> q = Polynomial(2, [1, 2, 3]) + >>> p != q + False + """ + return not self.__eq__(polynomial_2) From 3fd43048bf8b00015c8f09358bee8dad2aa111a4 Mon Sep 17 00:00:00 2001 From: Emmanuel Murairi Date: Thu, 6 Oct 2022 10:50:41 +0400 Subject: [PATCH 2/6] edit documentation --- maths/polynomials/single_indeterminate_operations.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maths/polynomials/single_indeterminate_operations.py b/maths/polynomials/single_indeterminate_operations.py index bd1b59a983c6..3101161e5756 100644 --- a/maths/polynomials/single_indeterminate_operations.py +++ b/maths/polynomials/single_indeterminate_operations.py @@ -1,5 +1,6 @@ """ -Operations on single indeterminate polynomials + +This module implements a single indeterminate polynomials class with some basic operations Reference: https://en.wikipedia.org/wiki/Polynomial From 846c687be92d0e057bf9f33c1ccf48cb2ef406c2 Mon Sep 17 00:00:00 2001 From: Emmanuel Murairi Date: Thu, 6 Oct 2022 11:51:21 +0400 Subject: [PATCH 3/6] fix type hint and linter errors --- .../single_indeterminate_operations.py | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/maths/polynomials/single_indeterminate_operations.py b/maths/polynomials/single_indeterminate_operations.py index 3101161e5756..4dcd6792360c 100644 --- a/maths/polynomials/single_indeterminate_operations.py +++ b/maths/polynomials/single_indeterminate_operations.py @@ -1,14 +1,18 @@ """ -This module implements a single indeterminate polynomials class with some basic operations +This module implements a single indeterminate polynomials class +with some basic operations Reference: https://en.wikipedia.org/wiki/Polynomial """ +from __future__ import annotations +from typing import MutableSequence + class Polynomial: - def __init__(self, degree: int, coefficients: list[int]): + def __init__(self, degree: int, coefficients: MutableSequence[float]) -> None: """ The coeffients should be in order of degree, from smallest to largest. >>> p = Polynomial(2, [1, 2, 3]) @@ -23,10 +27,10 @@ def __init__(self, degree: int, coefficients: list[int]): "The number of coefficients should be equal to the degree + 1." ) - self.coefficients = coefficients + self.coefficients: list[float] = list(coefficients) self.degree = degree - def __add__(self, polynomial_2): + def __add__(self, polynomial_2: Polynomial) -> Polynomial: """ Polynomial addition >>> p = Polynomial(2, [1, 2, 3]) @@ -36,17 +40,17 @@ def __add__(self, polynomial_2): """ if self.degree > polynomial_2.degree: - coefficients = self.coefficients.copy() + coefficients = self.coefficients[:] for i in range(polynomial_2.degree + 1): coefficients[i] += polynomial_2.coefficients[i] return Polynomial(self.degree, coefficients) else: - coefficients = polynomial_2.coefficients.copy() + coefficients = polynomial_2.coefficients[:] for i in range(self.degree + 1): coefficients[i] += self.coefficients[i] return Polynomial(polynomial_2.degree, coefficients) - def __sub__(self, polynomial_2): + def __sub__(self, polynomial_2: Polynomial) -> Polynomial: """ Polynomial subtraction >>> p = Polynomial(2, [1, 2, 4]) @@ -56,7 +60,7 @@ def __sub__(self, polynomial_2): """ return self + polynomial_2 * Polynomial(0, [-1]) - def __neg__(self): + def __neg__(self) -> Polynomial: """ Polynomial negation >>> p = Polynomial(2, [1, 2, 3]) @@ -65,7 +69,7 @@ def __neg__(self): """ return Polynomial(self.degree, [-c for c in self.coefficients]) - def __mul__(self, polynomial_2): + def __mul__(self, polynomial_2: Polynomial) -> Polynomial: """ Polynomial multiplication >>> p = Polynomial(2, [1, 2, 3]) @@ -73,7 +77,7 @@ def __mul__(self, polynomial_2): >>> p * q 9x^4 + 12x^3 + 10x^2 + 4x + 1 """ - coefficients = [0] * (self.degree + polynomial_2.degree + 1) + coefficients: list[float] = [0] * (self.degree + polynomial_2.degree + 1) for i in range(self.degree + 1): for j in range(polynomial_2.degree + 1): coefficients[i + j] += ( @@ -82,14 +86,14 @@ def __mul__(self, polynomial_2): return Polynomial(self.degree + polynomial_2.degree, coefficients) - def evaluate(self, x): + def evaluate(self, x: int | float) -> int | float: """ Evaluates the polynomial at x. >>> p = Polynomial(2, [1, 2, 3]) >>> p.evaluate(2) 17 """ - result = 0 + result: int | float = 0 for i in range(self.degree + 1): result += self.coefficients[i] * (x**i) return result @@ -127,32 +131,32 @@ def __repr__(self) -> str: """ return self.__str__() - def derivative(self): + def derivative(self) -> Polynomial: """ Returns the derivative of the polynomial. >>> p = Polynomial(2, [1, 2, 3]) >>> p.derivative() 6x + 2 """ - coefficients = [0] * self.degree + coefficients: list[float] = [0] * self.degree for i in range(self.degree): coefficients[i] = self.coefficients[i + 1] * (i + 1) return Polynomial(self.degree - 1, coefficients) - def integral(self, constant=0): + def integral(self, constant: int | float = 0) -> Polynomial: """ Returns the integral of the polynomial. >>> p = Polynomial(2, [1, 2, 3]) >>> p.integral() 1.0x^3 + 1.0x^2 + 1.0x """ - coefficients = [0] * (self.degree + 2) + coefficients: list[float] = [0] * (self.degree + 2) coefficients[0] = constant for i in range(self.degree + 1): coefficients[i + 1] = self.coefficients[i] / (i + 1) return Polynomial(self.degree + 1, coefficients) - def __eq__(self, polynomial_2): + def __eq__(self, polynomial_2: object) -> bool: """ Checks if two polynomials are equal. >>> p = Polynomial(2, [1, 2, 3]) @@ -160,6 +164,9 @@ def __eq__(self, polynomial_2): >>> p == q True """ + if not isinstance(polynomial_2, Polynomial): + return False + if self.degree != polynomial_2.degree: return False @@ -169,7 +176,7 @@ def __eq__(self, polynomial_2): return True - def __ne__(self, polynomial_2): + def __ne__(self, polynomial_2: object) -> bool: """ Checks if two polynomials are not equal. >>> p = Polynomial(2, [1, 2, 3]) From 601c7a455105674ebb96231e068fe45cf961ade2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 6 Oct 2022 07:53:17 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- maths/polynomials/single_indeterminate_operations.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maths/polynomials/single_indeterminate_operations.py b/maths/polynomials/single_indeterminate_operations.py index 4dcd6792360c..11a132eef65b 100644 --- a/maths/polynomials/single_indeterminate_operations.py +++ b/maths/polynomials/single_indeterminate_operations.py @@ -8,7 +8,8 @@ """ from __future__ import annotations -from typing import MutableSequence + +from collections.abc import MutableSequence class Polynomial: From 51d276e314aaf09c732cc3be1fa5b7af7ff3ab2d Mon Sep 17 00:00:00 2001 From: Emmanuel Murairi Date: Thu, 6 Oct 2022 12:09:44 +0400 Subject: [PATCH 5/6] fix short variable name --- maths/polynomials/single_indeterminate_operations.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/polynomials/single_indeterminate_operations.py b/maths/polynomials/single_indeterminate_operations.py index 4dcd6792360c..2492dc69b857 100644 --- a/maths/polynomials/single_indeterminate_operations.py +++ b/maths/polynomials/single_indeterminate_operations.py @@ -86,7 +86,7 @@ def __mul__(self, polynomial_2: Polynomial) -> Polynomial: return Polynomial(self.degree + polynomial_2.degree, coefficients) - def evaluate(self, x: int | float) -> int | float: + def evaluate(self, subtitution: int | float) -> int | float: """ Evaluates the polynomial at x. >>> p = Polynomial(2, [1, 2, 3]) @@ -95,7 +95,7 @@ def evaluate(self, x: int | float) -> int | float: """ result: int | float = 0 for i in range(self.degree + 1): - result += self.coefficients[i] * (x**i) + result += self.coefficients[i] * (subtitution**i) return result def __str__(self) -> str: From 6d742f77cd79bfe30e840cfb42085ab518dd340d Mon Sep 17 00:00:00 2001 From: Emmanuel Murairi Date: Thu, 6 Oct 2022 12:22:38 +0400 Subject: [PATCH 6/6] fix spelling --- maths/polynomials/single_indeterminate_operations.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/maths/polynomials/single_indeterminate_operations.py b/maths/polynomials/single_indeterminate_operations.py index 3bcd9a3a8ca8..8bafdb591793 100644 --- a/maths/polynomials/single_indeterminate_operations.py +++ b/maths/polynomials/single_indeterminate_operations.py @@ -15,7 +15,7 @@ class Polynomial: def __init__(self, degree: int, coefficients: MutableSequence[float]) -> None: """ - The coeffients should be in order of degree, from smallest to largest. + The coefficients should be in order of degree, from smallest to largest. >>> p = Polynomial(2, [1, 2, 3]) >>> p = Polynomial(2, [1, 2, 3, 4]) Traceback (most recent call last): @@ -87,7 +87,7 @@ def __mul__(self, polynomial_2: Polynomial) -> Polynomial: return Polynomial(self.degree + polynomial_2.degree, coefficients) - def evaluate(self, subtitution: int | float) -> int | float: + def evaluate(self, substitution: int | float) -> int | float: """ Evaluates the polynomial at x. >>> p = Polynomial(2, [1, 2, 3]) @@ -96,7 +96,7 @@ def evaluate(self, subtitution: int | float) -> int | float: """ result: int | float = 0 for i in range(self.degree + 1): - result += self.coefficients[i] * (subtitution**i) + result += self.coefficients[i] * (substitution**i) return result def __str__(self) -> str: