

#
# Sort large text files in a minimum amount of memory
#
import argparse
import os



class     lowercase_       :
      UpperCamelCase_     :						int		 =							"block_{0}.dat"



      def __init__(     self :							str     ,   A__ :							Any						)       ->	Optional[Any]:
        _snake_case		=				filename
        _snake_case		=				[]



      def 		UpperCamelCase_						(     self :							Tuple     ,   A__ :							str     ,   A__ :							Tuple						)       ->	Optional[Any]:
        _snake_case		=				self.BLOCK_FILENAME_FORMAT.format(__SCREAMING_SNAKE_CASE						)
        with open(__SCREAMING_SNAKE_CASE     ,   '''w'''						) as file:
          file.write(__SCREAMING_SNAKE_CASE						)
        self.block_filenames.append(__SCREAMING_SNAKE_CASE						)



      def 		UpperCamelCase_						(     self :							str						)       ->	int:
        return self.block_filenames



      def 		UpperCamelCase_						(     self :							Union[str, Any]     ,   A__ :							Optional[int]     ,   A__ :							str=None						)       ->	Any:
        _snake_case		=				0
        with open(self.filename						) as file:
          while True:
            _snake_case		=				file.readlines(__SCREAMING_SNAKE_CASE						)

            if lines == []:
              break

            if sort_key is None:
              lines.sort()
            else:
              lines.sort(key=__SCREAMING_SNAKE_CASE						)

            self.write_block(''''''.join(__SCREAMING_SNAKE_CASE						)     ,   __SCREAMING_SNAKE_CASE						)
            i += 1







      def 		UpperCamelCase_						(     self :							Any						)       ->	int:
        map(os.remove     ,   self.block_filenames						)



class     lowercase_       :



      def 		UpperCamelCase_						(     self :							List[str]     ,   A__ :							int						)       ->	List[Any]:
        _snake_case		=				-1
        _snake_case		=				None

        for i in range(len(__SCREAMING_SNAKE_CASE						)						):
          if min_str is None or choices[i] < min_str:
            _snake_case		=				i

        return min_index



class     lowercase_       :



      def __init__(     self :							List[Any]     ,   A__ :							Dict						)       ->	Tuple:
        _snake_case		=				files
        _snake_case		=				set()
        _snake_case		=				len(__SCREAMING_SNAKE_CASE						)
        _snake_case		=				{i: None for i in range(self.num_buffers						)}



      def 		UpperCamelCase_						(     self :							str						)       ->	Optional[Any]:
        return {
            i: self.buffers[i] for i in range(self.num_buffers						) if i not in self.empty
        }



      def 		UpperCamelCase_						(     self :							Dict						)       ->	List[str]:







        for i in range(self.num_buffers						):
          if self.buffers[i] is None and i not in self.empty:
            _snake_case		=				self.files[i].readline()

            if self.buffers[i] == "":
              self.empty.add(__SCREAMING_SNAKE_CASE						)
              self.files[i].close()

        if len(self.empty						) == self.num_buffers:
          return False

        return True







      def 		UpperCamelCase_						(     self :							Dict     ,   A__ :							Optional[Any]						)       ->	Optional[Any]:
        _snake_case		=				self.buffers[index]
        _snake_case		=				None

        return value



class     lowercase_       :



      def __init__(     self :							Optional[Any]     ,   A__ :							Any						)       ->	List[Any]:
        _snake_case		=				merge_strategy



      def 		UpperCamelCase_						(     self :							Optional[int]     ,   A__ :							str     ,   A__ :							Optional[int]     ,   A__ :							List[Any]						)       ->	Dict:
        _snake_case		=				FilesArray(self.get_file_handles(__SCREAMING_SNAKE_CASE     ,   __SCREAMING_SNAKE_CASE						)						)
        with open(__SCREAMING_SNAKE_CASE     ,   '''w'''     ,   __SCREAMING_SNAKE_CASE						) as outfile:
          while buffers.refresh():
            _snake_case		=				self.merge_strategy.select(buffers.get_dict()						)
            outfile.write(buffers.unshift(__SCREAMING_SNAKE_CASE						)						)







      def 		UpperCamelCase_						(     self :							int     ,   A__ :							Union[str, Any]     ,   A__ :							int						)       ->	Union[str, Any]:
        _snake_case		=				{}

        for i in range(len(__SCREAMING_SNAKE_CASE						)						):
          _snake_case		=				open(filenames[i]     ,   '''r'''     ,   __SCREAMING_SNAKE_CASE						)  # noqa: UP015

        return files



class     lowercase_       :



      def __init__(     self :							Tuple     ,   A__ :							int						)       ->	Tuple:
        _snake_case		=				block_size



      def 		UpperCamelCase_						(     self :							List[Any]     ,   A__ :							Optional[Any]     ,   A__ :							Optional[int]=None						)       ->	Dict:
        _snake_case		=				self.get_number_blocks(__SCREAMING_SNAKE_CASE     ,   self.block_size						)
        _snake_case		=				FileSplitter(__SCREAMING_SNAKE_CASE						)
        splitter.split(self.block_size     ,   __SCREAMING_SNAKE_CASE						)

        _snake_case		=				FileMerger(NWayMerge()						)
        _snake_case		=				self.block_size / (num_blocks + 1)
        merger.merge(splitter.get_block_filenames()     ,   filename + '''.out'''     ,   __SCREAMING_SNAKE_CASE						)

        splitter.cleanup()







      def 		UpperCamelCase_						(     self :							List[str]     ,   A__ :							Union[str, Any]     ,   A__ :							List[str]						)       ->	Dict:
        return (os.stat(__SCREAMING_SNAKE_CASE						).st_size / block_size) + 1



def  snake_case_(_UpperCamelCase	)				->      Any:



  """simple docstring"""






  if string[-1].lower() == "k":
    return int(string[:-1]	) * 1_024
  elif string[-1].lower() == "m":
    return int(string[:-1]	) * 1_024 * 1_024
  elif string[-1].lower() == "g":
    return int(string[:-1]	) * 1_024 * 1_024 * 1_024
  else:
    return int(A_	)



def  snake_case_()				->      List[str]:



  """simple docstring"""






  _snake_case		=				argparse.ArgumentParser()
  parser.add_argument(
      '''-m'''					,			'''--mem'''					,			help='''amount of memory to use for sorting'''					,			default='''100M'''	)
  parser.add_argument(
      '''filename'''					,			metavar='''<filename>'''					,			nargs=1					,			help='''name of file to sort'''	)
  _snake_case		=				parser.parse_args()

  _snake_case		=				ExternalSort(parse_memory(args.mem	)	)
  sorter.sort(args.filename[0]	)


if __name__ == "__main__":
 main()





def 	_lowerCamelCase  (		A_  :	Union[str, Any]							,  A_  :	Optional[int]      )			->			Dict:

   '''simple docstring'''






   if len(str(A_      )      ) == 1 or len(str(A_      )      ) == 1:
      return a * b

   UpperCamelCase__ :			Any 						=max(len(str(A_      )      )							,  len(str(A_      )      )      )
   UpperCamelCase__ :			Optional[int] 						=ma // 2

   UpperCamelCase__						,	UpperCamelCase__ :			Dict 						=divmod(A_							,  1_0**ma      )
   UpperCamelCase__						,	UpperCamelCase__ :			Union[str, Any] 						=divmod(A_							,  1_0**ma      )

   UpperCamelCase__ :			List[Any] 						=karatsuba(A_							,  A_      )
   UpperCamelCase__ :			Dict 						=karatsuba((aa + aa)							,  (ba + ba)      )
   UpperCamelCase__ :			Optional[int] 						=karatsuba(A_							,  A_      )

   return (z * 1_0 ** (2 * ma)) + ((y - z - x) * 1_0 ** (ma)) + (x)
def 	_lowerCamelCase  (		)			->			Any:

   '''simple docstring'''






   print(karatsuba(1_5_4_6_3							,  2_3_4_8_9      )      )


if __name__ == "__main__":
     main()

