Advertisement
aribahaz

Untitled

Feb 4th, 2018
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.38 KB | None | 0 0
  1. # Submitter: hazaria (Hazari, Areba)
  2. # Partner : dcpeng (Peng, Deone)
  3. # We certify that we worked cooperatively on this programming
  4. # assignment, according to the rules for pair programming
  5.  
  6. from collections import defaultdict
  7. import copy
  8.  
  9. class Poly:
  10. def __init__(self, *args):
  11. self.terms = dict()
  12. for k, v in args:
  13. assert (type(k) is int or type(k) is float)
  14. assert ((type(v) is int) and v >= 0)
  15. assert sorted(args, key = lambda x: x[1], reverse = True) == list(args)
  16.  
  17. if k != 0:
  18. if v not in self.terms:
  19. self.terms[v] = k
  20. else:
  21. raise AssertionError
  22.  
  23.  
  24. def __repr__(self):
  25. #__repr__ method returns a string, which when passed to eval returns a newly constructed
  26. # Poly with the same value as the object __repr__ was called on.
  27. self.rep_list = []
  28. for k in self.terms.keys():
  29. self.rep_list.append((self.terms[k], k))
  30. return 'Poly' + str(tuple(self.rep_list))
  31.  
  32.  
  33. def __str__(self):
  34. #__str__ method that returns a string that nicely displays a polynomial, using all the standard
  35. #mathematical abbreviations for coefficients and powers (ordered from highest to lowest power).
  36. poly_str = ''
  37. sorted_list = sorted(self.terms.items(), key = lambda x: x[0], reverse = True)
  38. #remove any poly with a 0 coefficient
  39. updated_list = [tup for tup in sorted_list if tup[1] != 0]
  40.  
  41. for pow, coef in updated_list:
  42. if poly_str == '': #first term
  43. if pow == 1:
  44. if coef == 1:
  45. poly_str += f'x'
  46. elif coef == -1:
  47. poly_str += f'-x'
  48. else:
  49. poly_str += f'{coef}x'
  50.  
  51. elif pow == 0:
  52. poly_str += f'{coef}'
  53.  
  54. else:
  55. if coef == 1:
  56. poly_str += f'x^{pow}'
  57. elif coef == -1:
  58. poly_str += f'-x^{pow}'
  59. else:
  60. poly_str += f'{coef}x^{pow}'
  61.  
  62.  
  63. else: # Other terms
  64. if pow == 1:
  65. if coef == 1 or coef == -1:
  66. poly_str += f' + x' if coef == 1 else f' - x'
  67. else:
  68. poly_str += f' + {coef}x' if coef > 0 else f' - {abs(coef)}x'
  69.  
  70. elif pow == 0:
  71. poly_str += f' + {coef}' if coef > 0 else f' - {abs(coef)}'
  72. else:
  73. if coef == 1 or coef == -1:
  74. poly_str += f' + x^{pow}' if coef == 1 else f' - x^{pow}'
  75. else:
  76. poly_str += f' + {coef}x^{pow}' if coef > 0 else f' - {abs(coef)}x^{pow}'
  77.  
  78. return '0' if self.terms == dict() else poly_str
  79.  
  80.  
  81. def __bool__(self):
  82. # __bool__ method returns True if the Poly represents any polynomial that is not 0.
  83. return True if self.terms != dict() else False
  84.  
  85.  
  86. def __len__(self):
  87. #__len__ method returns the highest power in the polynomial.
  88. return max(self.terms.keys()) if self.terms != dict() else 0
  89.  
  90.  
  91. def __call__(self, sub_x):
  92. # __call__ method that takes one numeric (int or float) argument: it
  93. #returns the value produced by evaluating the polynomial with that value substituted for x.
  94. assert(type(sub_x) is int or type(sub_x) is float)
  95. total = 0
  96. for power, coef in self.terms.items():
  97. total += (coef * (sub_x ** power))
  98. return total
  99.  
  100.  
  101. def __iter__(self):
  102. #__iter__ method that produces 2-tuples (containing a coefficient
  103. #followed by its power), such that the powers of the tuples are decreasing
  104. pass
  105.  
  106.  
  107. def __getitem__(self, key):
  108. #__getitem__ method whose argument is any power; it returns the coefficient associated
  109. #with that power. If the argument is not an integer or is < 0, raise a TypeError exception with an
  110. #appropriate message. If the argument is not a power in the polynomial's dictionary, return the int 0.
  111. if type(key) != int or key < 0:
  112. raise TypeError('Illegal power')
  113. for k in self.terms.keys():
  114. if key == k:
  115. return self.terms[key]
  116. else:
  117. return 0
  118.  
  119.  
  120. def __setitem__(self, power, coef):
  121. #__setitem__ method whose arguments are any power and its new coefficient; it associates the power with
  122. #the coefficient, whether or not that power is already in the polynomial dictionary. If the power argument
  123. #is not an integer or is < 0, raise a TypeError exception with an appropriate message. If the coefficient argument
  124. #is equal to 0, don't create/change that term, but instead delete it from the dictonary, if it is present,
  125. #because no coefficients of 0 should appear in the polynomial. This method can mutate the state of a polynomial.
  126. if (type(power) is not int) or (power < 0):
  127. raise TypeError(f'Poly.__setitem__: Power value({power}) is not a non-negative integer')
  128. if coef == 0:
  129. if power in self.terms:
  130. self.terms.pop(power)
  131. else:
  132. self.terms[power] = coef
  133.  
  134. def __delitem__(self, item):
  135. #__delitem__ method whose argument is any power; it deletes that power (and its associated coefficient) from the
  136. #polynomial if it is present (if the power is not present, the polynomial remains unchanged). If the argument is not an
  137. #integer or is < 0, raise a TypeError exception with an appropriate message. This method can mutate the state of a polynomial.
  138. if ((type(item) != int) or item < 0):
  139. raise TypeError(f'Poly.__delitem__: Argument({item}) is not a non-negative integer')
  140. if item in self.terms:
  141. del(self.terms[item])
  142.  
  143.  
  144. def _add_term(self, coef, power):
  145. # _add_term which take a Poly object (as the self parameter) and a coefficient and power as arguments that specify the term:
  146. #the coefficient must be numeric (int or float) and the power must be an int that is >= 0; otherwise raise a TypeError
  147. #exception with an appropriate message. It mutates the Poly object to include (add in) the specified term according to the
  148. #following rules: (1) if the power is not in the polynomial and the coefficient is not 0, it is added along with the
  149. #coefficient; (2) if the power is in the polynomial, the coefficient is added to existing coefficient for that power, but
  150. #(2a)and if the resulting sum/coefficient is 0 that power is deleted from the polynomial.
  151. if ((type(power) != int) or power < 0):
  152. raise TypeError(f'Poly._add_term: Power({power}) must be a non-negative integer')
  153. if type(coef) not in {int,float}:
  154. raise TypeError(f'Poly._add_term: Coefficient({coef}) must be an integer or float')
  155. if power not in self.terms:
  156. self.terms[power] = coef
  157. else:
  158. self.terms[power] += coef
  159.  
  160.  
  161. def __pos__(self):
  162. copy_pos = copy.deepcopy(self)
  163. return copy_pos
  164.  
  165.  
  166. def __neg__(self):
  167. copy_neg = copy.deepcopy(self)
  168. for power, coef in copy_neg.terms.items():
  169. copy_neg[power] = (-coef)
  170. return copy_neg
  171.  
  172.  
  173. def __abs__(self):
  174. #Absolute of value passed
  175. copy_abs = copy.deepcopy(self)
  176. for power, coef in copy_abs.terms.items():
  177. copy_abs[power] = abs(coef)
  178. return copy_abs
  179.  
  180.  
  181. def differentiate(self):
  182. #differentiate method; it returns the derivative of the polynomial. The derivative of a polynomial is a polynomial with
  183. #each term cxp in the original polynomial transformed to the term cpxp-1.
  184. p = Poly()
  185. for power, coef in self.terms.items():
  186. if power != 0:
  187. new_pow = power - 1
  188. new_coef = coef * power
  189. else:
  190. new_coef = 0
  191. p._add_term((new_coef), (new_pow))
  192. return p
  193.  
  194.  
  195. def integrate(self, num = 0):
  196. #integrate method that takes a numeric (int or float) argument whose default value is 0; it returns the integral of
  197. #the polynomial The integral of a polynomial is a polynomial with each term cxp in the original polynomial
  198. #transformed to the term c/(p+1)xp+1 added to the constant term specified by the argument.
  199. if type(num) not in {int, float}:
  200. raise TypeError('Unsupported operand type(s)')
  201. p = Poly()
  202. for power, coef in self.terms.items():
  203. new_pow = power + 1
  204. new_coef = (coef/new_pow)
  205. p._add_term((new_coef), (new_pow))
  206. p._add_term(num, 0)
  207. return p
  208.  
  209.  
  210. def def_integrate(self, num1, num2):
  211. #def_integrate method takes two numeric (int or float) arguments; it returns
  212. #the area under the curve specified by the polynomial between the first and second argument.
  213. if (type(num1) not in {int, float}) or (type(num2) not in {int, float}):
  214. raise TypeError('Unsupported operand type(s)')
  215. p = Poly()
  216. val = 0
  217. for power, coef in self.terms.items():
  218. new_pow = power + 1
  219. new_coef = (coef/new_pow)
  220. p._add_term((new_coef), (new_pow))
  221. for k, v in p.terms.items():
  222. val += v * pow(num2, k) - v * pow(num1, k)
  223. return val
  224.  
  225.  
  226. def __add__(self, rhs):
  227. if type(rhs) not in {Poly, int, float}:
  228. raise TypeError('Unsupported operand type(s)')
  229. if type(rhs) != Poly:
  230. rhs = Poly( (rhs,0) )
  231. result = copy.deepcopy(self)
  232. for power, coef in rhs.terms.items():
  233. result._add_term(coef, power)
  234. return result
  235.  
  236.  
  237. def __radd__(self, lhs):
  238. if type(lhs) not in {Poly,int,float}:
  239. raise TypeError('Unsupported operand type(s)')
  240. if type(lhs) != Poly:
  241. lhs = Poly( (lhs,0) )
  242. result = copy.deepcopy(self)
  243. for power, coef in lhs.terms.items():
  244. result._add_term(coef, power)
  245. return result
  246.  
  247.  
  248. def __sub__(self, rhs):
  249. if type(rhs) not in {Poly, int, float}:
  250. raise TypeError('Unsupported operand type(s)')
  251. if type(rhs) != Poly:
  252. rhs = Poly( (rhs,0) )
  253. result = copy.deepcopy(self)
  254. for power, coef in rhs.terms.items():
  255. result._add_term((-coef), power)
  256. return result
  257.  
  258.  
  259. def __rsub__(self, lhs):
  260. if type(lhs) not in {Poly, int, float}:
  261. raise TypeError('Unsupported operand type(s)')
  262. if type(lhs) != Poly:
  263. lhs = Poly( (lhs,0) )
  264. result = copy.deepcopy(self)
  265. for power, coef in lhs.terms.items():
  266. result._add_term((-coef), power)
  267. return result
  268.  
  269.  
  270. def __mul__(self, rhs):
  271. if type(rhs) not in {Poly, int, float}:
  272. raise TypeError('Unsupported operand type(s)')
  273. if type(rhs) != Poly:
  274. rhs = Poly( (rhs,0) )
  275. result = Poly()
  276. for power, coef in rhs.terms.items():
  277. for self_power, self_coef in self.terms.items():
  278. new_coef = coef * self_coef
  279. new_pow = power + self_power
  280. result._add_term(new_coef, new_pow)
  281. return result
  282.  
  283.  
  284. def __rmul__(self, lhs):
  285. if type(lhs) not in {Poly, int, float}:
  286. raise TypeError('Unsupported operand type(s)')
  287. if type(lhs) != Poly:
  288. lhs = Poly( (lhs,0) )
  289. result = Poly()
  290. for power, coef in lhs.terms.items():
  291. for self_power, self_coef in self.terms.items():
  292. new_coef = coef * self_coef
  293. new_pow = power + self_power
  294. result._add_term(new_coef, new_pow)
  295. return result
  296.  
  297.  
  298. def __pow__(self, right):
  299. if (type(right) != int) or (right < 0):
  300. raise TypeError('Unsupported operand type(s)')
  301. result = copy.deepcopy(self)
  302. if right == 0:
  303. return 1
  304. while right > 1:
  305. result = result.__mul__(self)
  306. right -= 1
  307. return result
  308.  
  309.  
  310. def __eq__(self,rhs):
  311. if type(rhs) not in {Poly, int, float}:
  312. raise TypeError('Unsupported operand type(s)')
  313. if type(rhs) == int:
  314. rhs = Poly( (rhs, 0) )
  315. return (self.terms.items() == rhs.terms.items())
  316.  
  317.  
  318. def __lt__(self,rhs):
  319. if type(rhs) not in {Poly, int, float}:
  320. raise TypeError('Unsupported operand type(s)')
  321. if type(rhs) == int:
  322. len_rhs = 0
  323. else:
  324. len_rhs = rhs.__len__()
  325. len_self = self.__len__()
  326. if len_self == len_rhs:
  327. for power, coef in self.terms.items():
  328. self_coef = coef
  329. if len_self == 0:
  330. return self_coef < rhs
  331. else:
  332. for rhs_pow, right_coef in rhs.terms.items():
  333. rhs_coef = right_coef
  334. return self_coef < right_coef
  335. return len_self < len_rhs
  336.  
  337.  
  338. def __gt__(self,rhs):
  339. if type(rhs) not in {Poly, int, float}:
  340. raise TypeError('Unsupported operand type(s)')
  341. if type(rhs) == int:
  342. len_rhs = 0
  343. else:
  344. len_rhs = rhs.__len__()
  345. len_self = self.__len__()
  346. if len_self == len_rhs:
  347. for power, coef in self.terms.items():
  348. self_coef = coef
  349. if len_self == 0:
  350. return self_coef > rhs
  351. else:
  352. for rhs_pow, right_coef in rhs.terms.items():
  353. rhs_coef = right_coef
  354. return self_coef > right_coef
  355.  
  356. return len_self > len_rhs
  357.  
  358.  
  359. def __le__(self, rhs):
  360. if type(rhs) not in {Poly, int, float}:
  361. raise TypeError('Unsupported operand type(s)')
  362. if type(rhs) == int:
  363. len_rhs = 0
  364. else:
  365. len_rhs = rhs.__len__()
  366. len_self = self.__len__()
  367. if len_self == len_rhs:
  368. for power, coef in self.terms.items():
  369. self_coef = coef
  370. if len_self == 0:
  371. return self_coef <= rhs
  372. else:
  373. for rhs_pow, right_coef in rhs.terms.items():
  374. rhs_coef = right_coef
  375. return self_coef <= right_coef
  376. return len_self <= len_rhs
  377.  
  378.  
  379. def __ge__(self,rhs):
  380. if type(rhs) not in {Poly, int, float}:
  381. raise TypeError('Unsupported operand type(s)')
  382. if type(rhs) == int:
  383. len_rhs = 0
  384. else:
  385. len_rhs = rhs.__len__()
  386. len_self = self.__len__()
  387. if len_self == len_rhs:
  388. for power, coef in self.terms.items():
  389. self_coef = coef
  390. if len_self == 0:
  391. return self_coef >= rhs
  392. else:
  393. for rhs_pow, right_coef in rhs.terms.items():
  394. rhs_coef = right_coef
  395. return self_coef >= right_coef
  396. return len_self >= len_rhs
  397.  
  398.  
  399. #*************** #16 & #17 functions*********************
  400.  
  401. #def __setattr__(self):
  402. # __setattr__ method that ensures objects in the Poly class are immutable
  403. #The methods that you will write should never bind any instance name
  404. #(except in __init__, which initializes them) but exclusively returns newly constructed
  405. #Poly objects with the correct values. If an attempt is made to mutate an object (by defining
  406. #a new attribute or rebinding an existing attribute), raise an AssertionError with an appropriate
  407. #message. Unfortunately, we can still mutate an existing attribute.
  408. # pass
  409.  
  410.  
  411.  
  412.  
  413. if __name__ == '__main__':
  414. #Simple tests before running driver
  415. #Put your own test code here to test Poly before doing bsc tests
  416. '''
  417. print('Start of simple tests')
  418. p = Poly((3,2),(-2,1),(4,0))
  419. print(' For Polynomial: 3x^2 - 2x + 4')
  420. print(' str(p):',p)
  421. print(' repr(p):',repr(p))
  422. print(' len(p):',len(p))
  423. print(' p(2):',p(2))
  424. print(' list collecting the iterator results:', [t for t in p])
  425. print(' p+p:',p+p)
  426. print(' p+2:',p+2)
  427. print(' p*p:',p*p)
  428. print(' p*2:',p*2)
  429. print('End of simple tests\n\n')
  430. '''
  431. import driver
  432. driver.default_file_name = 'bscp22W18.txt'
  433. # driver.default_show_exception= True
  434. # driver.default_show_exception_message= True
  435. # driver.default_show_traceback= True
  436. driver.driver()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement