





from math import factorial



class     _UpperCAmelCase   :

		"""simple docstring"""


		def __init__(    self			:		Union[str, Any] ,  lowerCAmelCase_			:		List[Any] ,  lowerCAmelCase_			:		Tuple					)							->						Tuple:
					__lowerCAmelCase							     =     real
					if isinstance(lowerCAmelCase_ ,  lowerCAmelCase_					):
								__lowerCAmelCase							     =     [1] * rank
					else:
								__lowerCAmelCase							     =     rank






		def __repr__(    self			:		List[str]					)							->						int:
					return (
					    f"""{self.real}+"""
					    f"""{"+".join(str(lowerCAmelCase_					)+"E"+str(n+1					)for n,dual in enumerate(self.duals					)					)}"""
					)






		def     lowercase		(    self			:		Optional[int]					)							->						List[str]:
					__lowerCAmelCase							     =     self.duals.copy()
					while cur[-1] == 0:
								cur.pop(-1					)
					return Dual(self.real ,  lowerCAmelCase_					)






		def __add__(    self			:		List[Any] ,  lowerCAmelCase_			:		Dict					)							->						Dict:
					if not isinstance(lowerCAmelCase_ ,  lowerCAmelCase_					):
								return Dual(self.real + other ,  self.duals					)
					__lowerCAmelCase							     =     self.duals.copy()
					__lowerCAmelCase							     =     other.duals.copy()
					if len(lowerCAmelCase_					) > len(lowerCAmelCase_					):
								o_dual.extend([1] * (len(lowerCAmelCase_					) - len(lowerCAmelCase_					))					)
					elif len(lowerCAmelCase_					) < len(lowerCAmelCase_					):
								s_dual.extend([1] * (len(lowerCAmelCase_					) - len(lowerCAmelCase_					))					)
					__lowerCAmelCase							     =     []
					for i in range(len(lowerCAmelCase_					)					):
								new_duals.append(s_dual[i] + o_dual[i]					)
					return Dual(self.real + other.real ,  lowerCAmelCase_					)

		a_      =			__add__






		def __sub__(    self			:		Optional[Any] ,  lowerCAmelCase_			:		List[Any]					)							->						Dict:
					return self + other * -1






		def __mul__(    self			:		Optional[int] ,  lowerCAmelCase_			:		Any					)							->						Optional[int]:
					if not isinstance(lowerCAmelCase_ ,  lowerCAmelCase_					):
								__lowerCAmelCase							     =     []
								for i in self.duals:
											new_duals.append(i * other					)
								return Dual(self.real * other ,  lowerCAmelCase_					)
					__lowerCAmelCase							     =     [0] * (len(self.duals					) + len(other.duals					) + 1)
					for i, item in enumerate(self.duals					):
								for j, jtem in enumerate(other.duals					):
											new_duals[i + j + 1] += item * jtem
					for k in range(len(self.duals					)					):
								new_duals[k] += self.duals[k] * other.real
					for index in range(len(other.duals					)					):
								new_duals[index] += other.duals[index] * self.real
					return Dual(self.real * other.real ,  lowerCAmelCase_					)

		a_      =			__mul__






		def __truediv__(    self			:		Any ,  lowerCAmelCase_			:		str					)							->						Dict:
					if not isinstance(lowerCAmelCase_ ,  lowerCAmelCase_					):
								__lowerCAmelCase							     =     []
								for i in self.duals:
											new_duals.append(i / other					)
								return Dual(self.real / other ,  lowerCAmelCase_					)
					raise ValueError






		def __floordiv__(    self			:		List[str] ,  lowerCAmelCase_			:		Optional[Any]					)							->						List[Any]:
					if not isinstance(lowerCAmelCase_ ,  lowerCAmelCase_					):
								__lowerCAmelCase							     =     []
								for i in self.duals:
											new_duals.append(i // other					)
								return Dual(self.real // other ,  lowerCAmelCase_					)
					raise ValueError






		def __pow__(    self			:		Dict ,  lowerCAmelCase_			:		Union[str, Any]					)							->						Union[str, Any]:
					if n < 0 or isinstance(lowerCAmelCase_ ,  lowerCAmelCase_					):
								raise ValueError('power must be a positive integer'					)
					if n == 0:
								return 1
					if n == 1:
								return self
					__lowerCAmelCase							     =     self
					for _ in range(n - 1					):
								x *= self
					return x





def   a_   (			lowerCAmelCase_				:      Tuple,     lowerCAmelCase_				:      Union[str, Any],     lowerCAmelCase_				:      Optional[Any]     ):


			if not callable(_UpperCAmelCase     ):
						raise ValueError('differentiate() requires a function as input for func'     )
			if not isinstance(_UpperCAmelCase,     (float, int)     ):
						raise ValueError('differentiate() requires a float as input for position'     )
			if not isinstance(_UpperCAmelCase,     _UpperCAmelCase     ):
						raise ValueError('differentiate() requires an int as input for order'     )
			__lowerCAmelCase							     =     Dual(_UpperCAmelCase,     1     )
			__lowerCAmelCase							     =     func(_UpperCAmelCase     )
			if order == 0:
						return result.real
			return result.duals[order - 1] * factorial(_UpperCAmelCase     )


if __name__ == "__main__":
					import doctest

					doctest.testmod()

					def   a_   (			lowerCAmelCase_				:      Optional[Any]     ):
								return y**2 * y**4




					print(differentiate(f, 9, 2))








from functools import lru_cache

@lru_cache
def   a_   (			lowerCAmelCase_				:      int     ):
   if num < 0:
      raise ValueError('Number should not be negative.'     )

   return 1 if num in (0, 1) else num * factorial(num - 1     )


if __name__ == "__main__":
     import doctest

     doctest.testmod()

