from nessesary.parser.parser import parse_poly from nessesary.fraction import to_fraction from math import acos, cos, pi class Polynomial: def __init__(self, poly, fracmode=False): if isinstance(poly, str): self.coeff = parse_poly(poly) self.degree = len(parse_poly(poly)) - 1 elif isinstance(poly, list): self.coeff = poly self.degree = len(poly) - 1 else: raise ValueError self.fracmode = fracmode if fracmode: for c_index in range(len(self.coeff)): try: self.coeff[c_index] = to_fraction(self.coeff[c_index]) except: raise ValueError("Can't turn all number into fraction.") self.degree = len(self.coeff) #[degree0, degree1, degree2] def __add__(self, other): """ >>> p1 = Polynomial([1, 1, 1, 1, 1]) >>> p2 = Polynomial([1, 1, 1, 1, 1]) >>> p3 = p1 + p2 >>> str(p3) '2x^4+2x^3+2x^2+2x+2' """ if isinstance(other, Polynomial): large_index = max([len(self.coeff), len(other.coeff)]) temp = [0 for i in range(large_index)] result = Polynomial(temp) for degree_index in range(self.degree): result.coeff[degree_index] = self.coeff[degree_index] + other.coeff[degree_index] return result elif isinstance(other, (int, float)): result = Polynomial(self.coeff) result.coeff[0] += other return result def __radd__(self, other): return self+other def __sub__(self, other): """ >>> p1 = Polynomial([1, 1, 1, 1, 1]) >>> p2 = Polynomial([1, 1, 1, 1, 1]) >>> p3 = p1 - p2 >>> str(p3) '0' """ if isinstance(other, Polynomial): large_index = max([self.degree, other.degree]) temp = [0 for i in range(large_index)] result = Polynomial(temp) for degree_index in range(self.degree): result.coeff[degree_index] = self.coeff[degree_index] - other.coeff[degree_index] return result elif isinstance(other, (int, float)): result = Polynomial(self.coeff) result.coeff[0] -= other return result def __rsub__(self, other): return self-other def __mul__(self, other): """ >>> p1 = Polynomial([1, 1]) >>> p2 = Polynomial([1, 1]) >>> p3 = p1 * p2 >>> str(p3) x^2+2x+1 """ if isinstance(other, Polynomial): result = [0 for i in range(self.degree + other.degree +1)] for self_index in range(self.degree): for other_index in range(other.degree): result[self_index+other_index] += self.coeff[self_index]*other.coeff[other_index] poly_result = Polynomial(result) return poly_result elif isinstance(other, int) or isinstance(other, float): result = [0 for i in (range(self.degree))] for self_index in range(self.degree): result[self_index] += self.coeff[self_index]*other poly_result = Polynomial(result) return poly_result def __rmul__(self, other): return self*other def __pow__(self, other): """ >>> p1 = Polynomial([1, 1]) >>> str(p1 ** 2) x^2+2x+1 """ result = Polynomial([1]) if isinstance(other, int) and other >= 0: if other == 0: return Polynomial([1]) else: for i in range(other): result = result * self return result def to_str(self) -> str: """ convert coefficient list into string. >>> p1 = Polynomial([1, 1, 1, 1, 1]) >>> p1.to_str() 'x^4+x^3+x^2+x+1' >>> p2 = Polynomial([-2, 4, 0, -1, 2]) >>> p2.to_str() '2x^4-x^3+4x-2' """ # result = [] # for ind in range(len(self.coeff)): # if self.coeff[ind]: # if ind == 0: # temp = "" # elif ind == 1: # temp = "x" # else: # temp = "x^"+str(ind) # result.append(str(self.coeff[ind])+temp) # if result: # result.reverse() # return "+".join(result) # else: # return "0" # last_count = len(str(self.coeff[-1])) # result = [] # i = len(self.coeff) - 1 # while i >= 0: # if self.coeff[i] != 0: # if self.coeff[i] < 0: # result.append("-") # elif len(self.coeff) != 0: # result.append("+") # elif self.coeff[i] == 0: # i -= 1 # continue # if self.coeff[i] != 1 and self.coeff[i] != -1: # result.append(str(abs(self.coeff[i]))) # if (i == len(self.coeff) - 1): # result.append(str(self.coeff[i])) # if (self.coeff[i] == 1) and (i != len(self.coeff) - 1): # result.append(str(1)) # if i == 1: # result.append("x") # if i > 1: # result.append("x^"+str(i)) # i -= 1 # print(result) # if result[0] == "+" or result[0] == "-": # del result[0] # result = "".join(result) # return result i = len(self.coeff) - 1 result = '' if len(self.coeff) >= 3: while i >= 0: coe = self.coeff[i] if coe == 0: i -= 1 continue if i == len(self.coeff) - 1: if coe == 1: result += f'x^{i}' i -= 1 continue elif coe == -1: result += f'-x^{i}' i -= 1 continue elif (coe != 1) and (coe > 0): result += f'{coe}x^{i}' i -= 1 continue elif (coe != 1) and (coe < 0): result += f'{coe}x^{i}' i -= 1 continue else: if coe == 1: result += f'+x^{i}' i -= 1 continue elif coe == -1: result += f'-x^{i}' i -= 1 continue elif (coe != 1) and (coe > 0): result += f'+{coe}x^{i}' i -= 1 continue elif (coe != 1) and (coe < 0): result += f'{coe}x^{i}' i -= 1 continue else: if len(self.coeff) == 2: result = f'{self.coeff[1]}x' if self.coeff[0] > 0: result += f'+{self.coeff[0]}' elif self.coeff[0] < 0: result += f'-{self.coeff[0]}' elif self.coeff[0] == 0: pass return result elif len(self.coeff) == 1: return f'{self.coeff[0]}' if result[0] == "+": result = result[1:] return result def solve(self) -> dict: degree = len(self.coeff) - 1 sol = [{"real":0, "imag":0}, {"real":0, "imag":0}] if degree <= 2: try: a = self.coeff[2] except : a = 0 try: b = self.coeff[1] except : b = 0 try: c = self.coeff[0] except : c = 0 if a == 0: if b == 0: if c == 0: return sol else: sol[0]["real"] = c del sol[1] return sol else: sol[0]["real"] = -c/b sol.pop() return sol else: root_term = b**2-4*a*c if root_term < 0: # res1 = f"({-b}+{to_imag(root_term**0.5)})/{2*a}" # res2 = f"({-b}-{to_imag(root_term**0.5)})/{2*a}" sol[0]["real"] = -b/(2*a) sol[1]["real"] = -b/(2*a) sol[0]["imag"] = (abs(root_term)**0.5)/2*a sol[1]["imag"] = (-abs(root_term)**0.5)/2*a return sol else: if root_term == 0: sol[0]["real"] = -b/(2*a) del sol[1] return sol else: sol[0]["real"] = (-b-(root_term)**0.5)/(2*a) sol[1]["real"] = (-b+(root_term)**0.5)/(2*a) return sol elif degree >= 3: raise ValueError # elif degree == 3: # a, b = self.coeff[3], self.coeff[2] # c, d = self.coeff[1], self.coeff[0] # b, c, d = b/a, c/a, d/a # temp_q = 3.0*c-(b*b)/9.0 # temp_r = (-(27.0*d)+b*(9*c-2.0*(b * b)))/54.0 # first_term = b/3 # temp_check = (temp_q**3)+(temp_r**2) # sol = [{"real":0, "imag":0},{"real":0, "imag":0},{"real":0, "imag":0}] # if temp_check > 0: # temp = 1/3 # i = temp_r + (temp_check**0.5) # if i < 0: # i = -(-i**(temp)) # else: # i = i**temp # j = temp_r - (temp_check)**0.5 # if j < 0: # j = -(-j**(temp)) # else: # j = j**temp # sol[0]["real"] = -first_term + i + j # sol[2]["real"] = -(first_term+((i+j)/2)) # sol[1]["real"] = (first_term+((i+j)/2)) # sol[1]["imag"] = (3**0.5) * (-i+j)/2 # sol[2]["imag"] = -sol[1]["imag"] # return sol # elif temp_check == 0: # if temp_r < 0: # new_r = (-temp_r)**(1/3) # else: # new_r = temp_r**(1/3) # sol[0]["real"] = -first_term+2*new_r # sol[1]["real"] = -(new_r+first_term) # sol[2]["real"] = sol[1]["real"] # return sol # else: # temp2 = acos(temp_r/(-temp_q*-temp_q*-temp_q)**0.5) # temp = -first_term + 2*temp_q**0.5 # sol[0]["real"] = temp*cos(temp2/3) # sol[1]["real"] = temp*cos((temp2+2*pi)/3) # sol[2]["real"] = temp*cos((temp2+4*pi)/3) # return sol # elif degree == 4: # pass def __str__(self) -> str: return self.to_str() # p1 = Polynomial("x^2+2x+1", fracmode=True) # p2 = Polynomial("x^2+2x+1", fracmode=False) # print(p1.solve()) # if __name__ == "__main__": # import doctest # doctest.testmod() # Use the following line INSTEAD if you want to print all tests anyway. # doctest.testmod(verbose = True)