






import mpmath  # for roots of unity
import numpy as np


class 			SCREAMING_SNAKE_CASE      :
     '''simple docstring'''


     def __init__(					self							:						Optional[int]       ,			UpperCAmelCase_							:						int=None       ,			UpperCAmelCase_							:						List[Any]=None   ):
       SCREAMING_SNAKE_CASE							:   Dict						    =     list(poly_a or [0]   )[:]
       SCREAMING_SNAKE_CASE							:   Dict						    =     list(poly_b or [0]   )[:]

       # Remove leading zero coefficients
       while self.polyA[-1] == 0:
         self.polyA.pop()
       SCREAMING_SNAKE_CASE							:   List[Any]						    =     len(self.polyA   )

       while self.polyB[-1] == 0:
         self.polyB.pop()
       SCREAMING_SNAKE_CASE							:   Dict						    =     len(self.polyB   )

       # Add 0 to make lengths equal a power of 2
       SCREAMING_SNAKE_CASE							:   Optional[Any]						    =     int(
           2 ** np.ceil(np.loga(len(self.polyA   ) + len(self.polyB   ) - 1   )   )   )

       while len(self.polyA   ) < self.c_max_length:
         self.polyA.append(0   )
       while len(self.polyB   ) < self.c_max_length:
         self.polyB.append(0   )
       # A complex root used for the fourier transform
       SCREAMING_SNAKE_CASE							:   List[str]						    =     complex(mpmath.root(x=1       ,			n=self.c_max_length       ,			k=1   )   )

       # The product
       SCREAMING_SNAKE_CASE							:   Tuple						    =     self.__multiply()


     def 					_A							(					self							:						int       ,			UpperCAmelCase_							:						List[Any]   ):
       SCREAMING_SNAKE_CASE							:   Dict						    =     [[x] for x in self.polyA] if which == "A" else [[x] for x in self.polyB]
       # Corner case
       if len(UpperCAmelCase_   ) <= 1:
         return dft[0]
       #
       SCREAMING_SNAKE_CASE							:   Tuple						    =     self.c_max_length // 2
       while next_ncol > 0:
         SCREAMING_SNAKE_CASE							:   str						    =     [[] for i in range(UpperCAmelCase_   )]
         SCREAMING_SNAKE_CASE							:   int						    =     self.root**next_ncol

         # First half of next step
         SCREAMING_SNAKE_CASE							:   str						    =     1
         for j in range(self.c_max_length // (next_ncol * 2)   ):
           for i in range(UpperCAmelCase_   ):
             new_dft[i].append(dft[i][j] + current_root * dft[i + next_ncol][j]   )
           current_root *= root
         # Second half of next step
         SCREAMING_SNAKE_CASE							:   Tuple						    =     1
         for j in range(self.c_max_length // (next_ncol * 2)   ):
           for i in range(UpperCAmelCase_   ):
             new_dft[i].append(dft[i][j] - current_root * dft[i + next_ncol][j]   )
           current_root *= root
         # Update
         SCREAMING_SNAKE_CASE							:   int						    =     new_dft
         SCREAMING_SNAKE_CASE							:   List[Any]						    =     next_ncol // 2
       return dft[0]


     def 					_A							(					self							:						List[Any]   ):
       SCREAMING_SNAKE_CASE							:   Union[str, Any]						    =     self.__dft("A"   )
       SCREAMING_SNAKE_CASE							:   Union[str, Any]						    =     self.__dft("B"   )
       SCREAMING_SNAKE_CASE							:   Union[str, Any]						    =     [[dft_a[i] * dft_b[i] for i in range(self.c_max_length   )]]
       del dft_a
       del dft_b

       # Corner Case
       if len(inverce_c[0]   ) <= 1:
         return inverce_c[0]
       # Inverse DFT
       SCREAMING_SNAKE_CASE							:   Union[str, Any]						    =     2
       while next_ncol <= self.c_max_length:
         SCREAMING_SNAKE_CASE							:   Optional[int]						    =     [[] for i in range(UpperCAmelCase_   )]
         SCREAMING_SNAKE_CASE							:   Dict						    =     self.root ** (next_ncol // 2)
         SCREAMING_SNAKE_CASE							:   int						    =     1
         # First half of next step
         for j in range(self.c_max_length // next_ncol   ):
           for i in range(next_ncol // 2   ):
             # Even positions
             new_inverse_c[i].append(
                 (
                     inverce_c[i][j]
                     + inverce_c[i][j + self.c_max_length // next_ncol]
                 )
                 / 2   )
             # Odd positions
             new_inverse_c[i + next_ncol // 2].append(
                 (
                     inverce_c[i][j]
                     - inverce_c[i][j + self.c_max_length // next_ncol]
                 )
                 / (2 * current_root)   )
           current_root *= root
         # Update
         SCREAMING_SNAKE_CASE							:   List[Any]						    =     new_inverse_c
         next_ncol *= 2
       # Unpack
       SCREAMING_SNAKE_CASE							:   Union[str, Any]						    =     [round(x[0].real       ,			8   ) + round(x[0].imag       ,			8   ) * 1j for x in inverce_c]

       # Remove leading 0's
       while inverce_c[-1] == 0:
         inverce_c.pop()
       return inverce_c






     def __str__(					self							:						Dict   ):
       SCREAMING_SNAKE_CASE							:   str						    =     "A = " + " + ".join(
           f'''{coef}*x^{i}''' for coef, i in enumerate(self.polyA[: self.len_A]   )   )
       SCREAMING_SNAKE_CASE							:   Optional[int]						    =     "B = " + " + ".join(
           f'''{coef}*x^{i}''' for coef, i in enumerate(self.polyB[: self.len_B]   )   )
       SCREAMING_SNAKE_CASE							:   Dict						    =     "A*B = " + " + ".join(
           f'''{coef}*x^{i}''' for coef, i in enumerate(self.product   )   )

       return f'''{a}\n{b}\n{c}'''


# Unit tests
if __name__ == "__main__":
   import doctest

   doctest.testmod()














'''simple docstring'''



def  __UpperCAmelCase						(					SCREAMING_SNAKE_CASE__:						str     )	->      bool:

   """simple docstring"""
   if not all(x.isalpha() for x in string     ):
      raise ValueError('String must only contain alphabetic characters.'     )

   __a					  =     sorted(string.lower()     )
   return len(SCREAMING_SNAKE_CASE__     ) == len(set(SCREAMING_SNAKE_CASE__     )     )


if __name__ == "__main__":
 __UpperCamelCase   :							int         =   input("""Enter a string """).strip()

 __UpperCamelCase   :							Tuple         =   is_isogram(input_str)
 print(f"""{input_str} is {"an" if isogram else "not an"} isogram.""")