Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Submitter: hazaria (Hazari, Areba)
- # Partner : dcpeng (Peng, Deone)
- # We certify that we worked cooperatively on this programming
- # assignment, according to the rules for pair programming
- from collections import defaultdict
- import copy
- class Poly:
- def __init__(self, *args):
- self.terms = dict()
- for k, v in args:
- assert (type(k) is int or type(k) is float)
- assert ((type(v) is int) and v >= 0)
- assert sorted(args, key = lambda x: x[1], reverse = True) == list(args)
- if k != 0:
- if v not in self.terms:
- self.terms[v] = k
- else:
- raise AssertionError
- def __repr__(self):
- #__repr__ method returns a string, which when passed to eval returns a newly constructed
- # Poly with the same value as the object __repr__ was called on.
- self.rep_list = []
- for k in self.terms.keys():
- self.rep_list.append((self.terms[k], k))
- return 'Poly' + str(tuple(self.rep_list))
- def __str__(self):
- #__str__ method that returns a string that nicely displays a polynomial, using all the standard
- #mathematical abbreviations for coefficients and powers (ordered from highest to lowest power).
- poly_str = ''
- sorted_list = sorted(self.terms.items(), key = lambda x: x[0], reverse = True)
- #remove any poly with a 0 coefficient
- updated_list = [tup for tup in sorted_list if tup[1] != 0]
- for pow, coef in updated_list:
- if poly_str == '': #first term
- if pow == 1:
- if coef == 1:
- poly_str += f'x'
- elif coef == -1:
- poly_str += f'-x'
- else:
- poly_str += f'{coef}x'
- elif pow == 0:
- poly_str += f'{coef}'
- else:
- if coef == 1:
- poly_str += f'x^{pow}'
- elif coef == -1:
- poly_str += f'-x^{pow}'
- else:
- poly_str += f'{coef}x^{pow}'
- else: # Other terms
- if pow == 1:
- if coef == 1 or coef == -1:
- poly_str += f' + x' if coef == 1 else f' - x'
- else:
- poly_str += f' + {coef}x' if coef > 0 else f' - {abs(coef)}x'
- elif pow == 0:
- poly_str += f' + {coef}' if coef > 0 else f' - {abs(coef)}'
- else:
- if coef == 1 or coef == -1:
- poly_str += f' + x^{pow}' if coef == 1 else f' - x^{pow}'
- else:
- poly_str += f' + {coef}x^{pow}' if coef > 0 else f' - {abs(coef)}x^{pow}'
- return '0' if self.terms == dict() else poly_str
- def __bool__(self):
- # __bool__ method returns True if the Poly represents any polynomial that is not 0.
- return True if self.terms != dict() else False
- def __len__(self):
- #__len__ method returns the highest power in the polynomial.
- return max(self.terms.keys()) if self.terms != dict() else 0
- def __call__(self, sub_x):
- # __call__ method that takes one numeric (int or float) argument: it
- #returns the value produced by evaluating the polynomial with that value substituted for x.
- assert(type(sub_x) is int or type(sub_x) is float)
- total = 0
- for power, coef in self.terms.items():
- total += (coef * (sub_x ** power))
- return total
- def __iter__(self):
- #__iter__ method that produces 2-tuples (containing a coefficient
- #followed by its power), such that the powers of the tuples are decreasing
- pass
- def __getitem__(self, key):
- #__getitem__ method whose argument is any power; it returns the coefficient associated
- #with that power. If the argument is not an integer or is < 0, raise a TypeError exception with an
- #appropriate message. If the argument is not a power in the polynomial's dictionary, return the int 0.
- if type(key) != int or key < 0:
- raise TypeError('Illegal power')
- for k in self.terms.keys():
- if key == k:
- return self.terms[key]
- else:
- return 0
- def __setitem__(self, power, coef):
- #__setitem__ method whose arguments are any power and its new coefficient; it associates the power with
- #the coefficient, whether or not that power is already in the polynomial dictionary. If the power argument
- #is not an integer or is < 0, raise a TypeError exception with an appropriate message. If the coefficient argument
- #is equal to 0, don't create/change that term, but instead delete it from the dictonary, if it is present,
- #because no coefficients of 0 should appear in the polynomial. This method can mutate the state of a polynomial.
- if (type(power) is not int) or (power < 0):
- raise TypeError(f'Poly.__setitem__: Power value({power}) is not a non-negative integer')
- if coef == 0:
- if power in self.terms:
- self.terms.pop(power)
- else:
- self.terms[power] = coef
- def __delitem__(self, item):
- #__delitem__ method whose argument is any power; it deletes that power (and its associated coefficient) from the
- #polynomial if it is present (if the power is not present, the polynomial remains unchanged). If the argument is not an
- #integer or is < 0, raise a TypeError exception with an appropriate message. This method can mutate the state of a polynomial.
- if ((type(item) != int) or item < 0):
- raise TypeError(f'Poly.__delitem__: Argument({item}) is not a non-negative integer')
- if item in self.terms:
- del(self.terms[item])
- def _add_term(self, coef, power):
- # _add_term which take a Poly object (as the self parameter) and a coefficient and power as arguments that specify the term:
- #the coefficient must be numeric (int or float) and the power must be an int that is >= 0; otherwise raise a TypeError
- #exception with an appropriate message. It mutates the Poly object to include (add in) the specified term according to the
- #following rules: (1) if the power is not in the polynomial and the coefficient is not 0, it is added along with the
- #coefficient; (2) if the power is in the polynomial, the coefficient is added to existing coefficient for that power, but
- #(2a)and if the resulting sum/coefficient is 0 that power is deleted from the polynomial.
- if ((type(power) != int) or power < 0):
- raise TypeError(f'Poly._add_term: Power({power}) must be a non-negative integer')
- if type(coef) not in {int,float}:
- raise TypeError(f'Poly._add_term: Coefficient({coef}) must be an integer or float')
- if power not in self.terms:
- self.terms[power] = coef
- else:
- self.terms[power] += coef
- def __pos__(self):
- copy_pos = copy.deepcopy(self)
- return copy_pos
- def __neg__(self):
- copy_neg = copy.deepcopy(self)
- for power, coef in copy_neg.terms.items():
- copy_neg[power] = (-coef)
- return copy_neg
- def __abs__(self):
- #Absolute of value passed
- copy_abs = copy.deepcopy(self)
- for power, coef in copy_abs.terms.items():
- copy_abs[power] = abs(coef)
- return copy_abs
- def differentiate(self):
- #differentiate method; it returns the derivative of the polynomial. The derivative of a polynomial is a polynomial with
- #each term cxp in the original polynomial transformed to the term cpxp-1.
- p = Poly()
- for power, coef in self.terms.items():
- if power != 0:
- new_pow = power - 1
- new_coef = coef * power
- else:
- new_coef = 0
- p._add_term((new_coef), (new_pow))
- return p
- def integrate(self, num = 0):
- #integrate method that takes a numeric (int or float) argument whose default value is 0; it returns the integral of
- #the polynomial The integral of a polynomial is a polynomial with each term cxp in the original polynomial
- #transformed to the term c/(p+1)xp+1 added to the constant term specified by the argument.
- if type(num) not in {int, float}:
- raise TypeError('Unsupported operand type(s)')
- p = Poly()
- for power, coef in self.terms.items():
- new_pow = power + 1
- new_coef = (coef/new_pow)
- p._add_term((new_coef), (new_pow))
- p._add_term(num, 0)
- return p
- def def_integrate(self, num1, num2):
- #def_integrate method takes two numeric (int or float) arguments; it returns
- #the area under the curve specified by the polynomial between the first and second argument.
- if (type(num1) not in {int, float}) or (type(num2) not in {int, float}):
- raise TypeError('Unsupported operand type(s)')
- p = Poly()
- val = 0
- for power, coef in self.terms.items():
- new_pow = power + 1
- new_coef = (coef/new_pow)
- p._add_term((new_coef), (new_pow))
- for k, v in p.terms.items():
- val += v * pow(num2, k) - v * pow(num1, k)
- return val
- def __add__(self, rhs):
- if type(rhs) not in {Poly, int, float}:
- raise TypeError('Unsupported operand type(s)')
- if type(rhs) != Poly:
- rhs = Poly( (rhs,0) )
- result = copy.deepcopy(self)
- for power, coef in rhs.terms.items():
- result._add_term(coef, power)
- return result
- def __radd__(self, lhs):
- if type(lhs) not in {Poly,int,float}:
- raise TypeError('Unsupported operand type(s)')
- if type(lhs) != Poly:
- lhs = Poly( (lhs,0) )
- result = copy.deepcopy(self)
- for power, coef in lhs.terms.items():
- result._add_term(coef, power)
- return result
- def __sub__(self, rhs):
- if type(rhs) not in {Poly, int, float}:
- raise TypeError('Unsupported operand type(s)')
- if type(rhs) != Poly:
- rhs = Poly( (rhs,0) )
- result = copy.deepcopy(self)
- for power, coef in rhs.terms.items():
- result._add_term((-coef), power)
- return result
- def __rsub__(self, lhs):
- if type(lhs) not in {Poly, int, float}:
- raise TypeError('Unsupported operand type(s)')
- if type(lhs) != Poly:
- lhs = Poly( (lhs,0) )
- result = copy.deepcopy(self)
- for power, coef in lhs.terms.items():
- result._add_term((-coef), power)
- return result
- def __mul__(self, rhs):
- if type(rhs) not in {Poly, int, float}:
- raise TypeError('Unsupported operand type(s)')
- if type(rhs) != Poly:
- rhs = Poly( (rhs,0) )
- result = Poly()
- for power, coef in rhs.terms.items():
- for self_power, self_coef in self.terms.items():
- new_coef = coef * self_coef
- new_pow = power + self_power
- result._add_term(new_coef, new_pow)
- return result
- def __rmul__(self, lhs):
- if type(lhs) not in {Poly, int, float}:
- raise TypeError('Unsupported operand type(s)')
- if type(lhs) != Poly:
- lhs = Poly( (lhs,0) )
- result = Poly()
- for power, coef in lhs.terms.items():
- for self_power, self_coef in self.terms.items():
- new_coef = coef * self_coef
- new_pow = power + self_power
- result._add_term(new_coef, new_pow)
- return result
- def __pow__(self, right):
- if (type(right) != int) or (right < 0):
- raise TypeError('Unsupported operand type(s)')
- result = copy.deepcopy(self)
- if right == 0:
- return 1
- while right > 1:
- result = result.__mul__(self)
- right -= 1
- return result
- def __eq__(self,rhs):
- if type(rhs) not in {Poly, int, float}:
- raise TypeError('Unsupported operand type(s)')
- if type(rhs) == int:
- rhs = Poly( (rhs, 0) )
- return (self.terms.items() == rhs.terms.items())
- def __lt__(self,rhs):
- if type(rhs) not in {Poly, int, float}:
- raise TypeError('Unsupported operand type(s)')
- if type(rhs) == int:
- len_rhs = 0
- else:
- len_rhs = rhs.__len__()
- len_self = self.__len__()
- if len_self == len_rhs:
- for power, coef in self.terms.items():
- self_coef = coef
- if len_self == 0:
- return self_coef < rhs
- else:
- for rhs_pow, right_coef in rhs.terms.items():
- rhs_coef = right_coef
- return self_coef < right_coef
- return len_self < len_rhs
- def __gt__(self,rhs):
- if type(rhs) not in {Poly, int, float}:
- raise TypeError('Unsupported operand type(s)')
- if type(rhs) == int:
- len_rhs = 0
- else:
- len_rhs = rhs.__len__()
- len_self = self.__len__()
- if len_self == len_rhs:
- for power, coef in self.terms.items():
- self_coef = coef
- if len_self == 0:
- return self_coef > rhs
- else:
- for rhs_pow, right_coef in rhs.terms.items():
- rhs_coef = right_coef
- return self_coef > right_coef
- return len_self > len_rhs
- def __le__(self, rhs):
- if type(rhs) not in {Poly, int, float}:
- raise TypeError('Unsupported operand type(s)')
- if type(rhs) == int:
- len_rhs = 0
- else:
- len_rhs = rhs.__len__()
- len_self = self.__len__()
- if len_self == len_rhs:
- for power, coef in self.terms.items():
- self_coef = coef
- if len_self == 0:
- return self_coef <= rhs
- else:
- for rhs_pow, right_coef in rhs.terms.items():
- rhs_coef = right_coef
- return self_coef <= right_coef
- return len_self <= len_rhs
- def __ge__(self,rhs):
- if type(rhs) not in {Poly, int, float}:
- raise TypeError('Unsupported operand type(s)')
- if type(rhs) == int:
- len_rhs = 0
- else:
- len_rhs = rhs.__len__()
- len_self = self.__len__()
- if len_self == len_rhs:
- for power, coef in self.terms.items():
- self_coef = coef
- if len_self == 0:
- return self_coef >= rhs
- else:
- for rhs_pow, right_coef in rhs.terms.items():
- rhs_coef = right_coef
- return self_coef >= right_coef
- return len_self >= len_rhs
- #*************** #16 & #17 functions*********************
- #def __setattr__(self):
- # __setattr__ method that ensures objects in the Poly class are immutable
- #The methods that you will write should never bind any instance name
- #(except in __init__, which initializes them) but exclusively returns newly constructed
- #Poly objects with the correct values. If an attempt is made to mutate an object (by defining
- #a new attribute or rebinding an existing attribute), raise an AssertionError with an appropriate
- #message. Unfortunately, we can still mutate an existing attribute.
- # pass
- if __name__ == '__main__':
- #Simple tests before running driver
- #Put your own test code here to test Poly before doing bsc tests
- '''
- print('Start of simple tests')
- p = Poly((3,2),(-2,1),(4,0))
- print(' For Polynomial: 3x^2 - 2x + 4')
- print(' str(p):',p)
- print(' repr(p):',repr(p))
- print(' len(p):',len(p))
- print(' p(2):',p(2))
- print(' list collecting the iterator results:', [t for t in p])
- print(' p+p:',p+p)
- print(' p+2:',p+2)
- print(' p*p:',p*p)
- print(' p*2:',p*2)
- print('End of simple tests\n\n')
- '''
- import driver
- driver.default_file_name = 'bscp22W18.txt'
- # driver.default_show_exception= True
- # driver.default_show_exception_message= True
- # driver.default_show_traceback= True
- driver.driver()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement