docs: def rareness2(self, password, min_word_fragment_length=3, commonness_of_non_word=50000):
          """
          A logical way to calculate rareness, but the speed is illogical for length > 40.
          (length 45: 60 sec per test)
  
          :param password:
          :param int min_word_fragment_length:
          :param int commonness_of_non_word: an arbitrary value to improve commonness of 'poison'
          :return int: in range 0-1
          >>> Complexity().rareness2('thethethe')
          0.0
          >>> Complexity().rareness2('poison')  # the last word in Google's list
          0.19998
          >>> Complexity().rareness2('asdfegu')
          1
          >>> Complexity().rareness2('helloworld')
          0.02537
          >>> Complexity().rareness2('verylongpassword')
          0.006806666666666667
          >>> Complexity().rareness2('averylongpassword')
          0.26282000000000005
          >>> Complexity().rareness2('djkhsdjkashdaslkdhas')
          0.31674
          """
          from time import time
  
          def get_min_commonness_value(commonness_list):
              nonlocal commonness_value
  
              value = sum(commonness_list)/len(commonness_list)
              if value < commonness_value:
                  commonness_value = value
  
          def recurse(previous):
              nonlocal separators, depth, used_separators
              depth += 1
  
              for current in range(previous + min_word_fragment_length, len(password) - min_word_fragment_length + 1):
                  try:
                      separators[depth] = current
                  except IndexError:
                      separators.append(current)
  
                  if depth < number_of_separators - 1:
                      recurse(current)
                  else:
                      used_separators.add(tuple(separators))
  
              depth -= 1
  
          start = time()
          subword_commonness = dict()
          for i_front in range(0, len(password) - min_word_fragment_length + 1):
              for i_back in range(i_front + min_word_fragment_length, len(password) + 1):
                  subword_commonness[(i_front, i_back)] \
                      = self.common_words.get(password[i_front:i_back], commonness_of_non_word)/commonness_of_non_word
          print('subword complete', time()-start)
  
          start = time()
          commonness_value = 1
          used_separators = set()
          for number_of_separators in range(len(password)//min_word_fragment_length):
              if number_of_separators == 0:
                  get_min_commonness_value\
                      ({self.common_words.get(password, commonness_of_non_word)/commonness_of_non_word})
              else:
                  separators = list()
                  depth = -1
                  recurse(0)
          print('tuple listing complete', time()-start)
  
          start = time()
          for sep in used_separators:
              commonness_list = set()
              commonness_list.add(subword_commonness[(0, sep[0])])
              for i in range(len(sep)-1):
                  commonness_list.add(subword_commonness[(sep[i], sep[i + 1])])
              commonness_list.add(subword_commonness[(sep[-1], len(password))])
              get_min_commonness_value(commonness_list)
          print('get min complete', time()-start)
  
          return commonness_value