

"""simple docstring"""


a					:int    = range(2, 20 + 1)
a					:int    = [10**k for k in range(ks[-1] + 1)]
a					:dict[int, dict[int, list[list[int]]]]    = {}




def  _lowercase					(    __lowerCAmelCase  ,					__lowerCAmelCase  ,					__lowerCAmelCase  ,					__lowerCAmelCase							)       ->				List[Any]:
      SCREAMING_SNAKE_CASE__   :      Optional[int]      		=	sum(a_i[j] for j in range(snake_case_  ,					len(snake_case_							)							)							)
      SCREAMING_SNAKE_CASE__   :      Optional[Any]      		=	sum(a_i[j] * base[j] for j in range(min(len(snake_case_							)  ,					snake_case_							)							)							)

      SCREAMING_SNAKE_CASE__   :      Tuple      		=	0, 0
      SCREAMING_SNAKE_CASE__   :      Tuple      		=	n - i

      SCREAMING_SNAKE_CASE__   :      int      		=	memo.get(snake_case_							)

      if sub_memo is not None:
            SCREAMING_SNAKE_CASE__   :      Tuple      		=	sub_memo.get(snake_case_							)

            if jumps is not None and len(snake_case_							) > 0:
                  # find and make the largest jump without going over
                  SCREAMING_SNAKE_CASE__   :      Dict      		=	-1
                  for _k in range(len(snake_case_							) - 1  ,					-1  ,					-1							):
                        if jumps[_k][2] <= k and jumps[_k][1] <= max_dn:
                              SCREAMING_SNAKE_CASE__   :      Union[str, Any]      		=	_k
                              break

                  if max_jump >= 0:
                        SCREAMING_SNAKE_CASE__   :      Any      		=	jumps[max_jump]
                        # since the difference between jumps is cached, add c
                        SCREAMING_SNAKE_CASE__   :      str      		=	diff + c
                        for j in range(min(snake_case_  ,					len(snake_case_							)							)							):
                              SCREAMING_SNAKE_CASE__   :      List[Any]      		=	divmod(snake_case_  ,					10							)
                        if new_c > 0:
                              add(snake_case_  ,					snake_case_  ,					snake_case_							)

            else:
                  SCREAMING_SNAKE_CASE__   :      List[Any]      		=	[]
      else:
            SCREAMING_SNAKE_CASE__   :      str      		=	{c: []}
            SCREAMING_SNAKE_CASE__   :      str      		=	sub_memo

      if dn >= max_dn or c + diff >= base[k]:
            return diff, dn

      if k > ks[0]:
            while True:
                  # keep doing smaller jumps
                  SCREAMING_SNAKE_CASE__   :      Any      		=	next_term(snake_case_  ,					k - 1  ,					i + dn  ,					snake_case_							)
                  diff += _diff
                  dn += terms_jumped

                  if dn >= max_dn or c + diff >= base[k]:
                        break
      else:
            # would be too small a jump, just compute sequential terms instead
            SCREAMING_SNAKE_CASE__   :      List[Any]      		=	compute(snake_case_  ,					snake_case_  ,					i + dn  ,					snake_case_							)
            diff += _diff
            dn += terms_jumped

      SCREAMING_SNAKE_CASE__   :      Optional[Any]      		=	sub_memo[c]

      # keep jumps sorted by # of terms skipped
      SCREAMING_SNAKE_CASE__   :      Optional[int]      		=	0
      while j < len(snake_case_							):
            if jumps[j][1] > dn:
                  break
            j += 1

      # cache the jump for this value digitsum(b) and c
      sub_memo[c].insert(snake_case_  ,					(diff, dn, k)							)
      return (diff, dn)




def  _lowercase					(    __lowerCAmelCase  ,					__lowerCAmelCase  ,					__lowerCAmelCase  ,					__lowerCAmelCase							)       ->				Optional[int]:
      if i >= n:
            return 0, i
      if k > len(snake_case_							):
            a_i.extend([0 for _ in range(k - len(snake_case_							)							)]							)

      # note: a_i -> b * 10^k + c
      # ds_b -> digitsum(b)
      # ds_c -> digitsum(c)
      SCREAMING_SNAKE_CASE__   :      Tuple      		=	i
      SCREAMING_SNAKE_CASE__   :      List[Any]      		=	0, 0, 0
      for j in range(len(snake_case_							)							):
            if j >= k:
                  ds_b += a_i[j]
            else:
                  ds_c += a_i[j]

      while i < n:
            i += 1
            SCREAMING_SNAKE_CASE__   :      str      		=	ds_c + ds_b
            diff += addend
            SCREAMING_SNAKE_CASE__   :      Any      		=	0
            for j in range(snake_case_							):
                  SCREAMING_SNAKE_CASE__   :      Optional[int]      		=	a_i[j] + addend
                  SCREAMING_SNAKE_CASE__   :      str      		=	divmod(snake_case_  ,					10							)

                  ds_c += a_i[j]

            if addend > 0:
                  break

      if addend > 0:
            add(snake_case_  ,					snake_case_  ,					snake_case_							)
      return diff, i - start_i




def  _lowercase					(    __lowerCAmelCase  ,					__lowerCAmelCase  ,					__lowerCAmelCase							)       ->				List[Any]:
      for j in range(snake_case_  ,					len(snake_case_							)							):
            SCREAMING_SNAKE_CASE__   :      int      		=	digits[j] + addend
            if s >= 10:
                  SCREAMING_SNAKE_CASE__   :      List[Any]      		=	divmod(snake_case_  ,					10							)
                  SCREAMING_SNAKE_CASE__   :      Optional[int]      		=	addend // 10 + quotient
            else:
                  SCREAMING_SNAKE_CASE__   :      Optional[Any]      		=	s
                  SCREAMING_SNAKE_CASE__   :      Optional[Any]      		=	addend // 10

            if addend == 0:
                  break

      while addend > 0:
            SCREAMING_SNAKE_CASE__   :      List[str]      		=	divmod(snake_case_  ,					10							)
            digits.append(snake_case_							)




def  _lowercase					(    __lowerCAmelCase = 10**15							)       ->				str:
      SCREAMING_SNAKE_CASE__   :      List[Any]      		=	[1]
      SCREAMING_SNAKE_CASE__   :      int      		=	1
      SCREAMING_SNAKE_CASE__   :      List[Any]      		=	0
      while True:
            SCREAMING_SNAKE_CASE__   :      Optional[Any]      		=	next_term(snake_case_  ,					20  ,					i + dn  ,					snake_case_							)
            dn += terms_jumped
            if dn == n - i:
                  break

      SCREAMING_SNAKE_CASE__   :      Union[str, Any]      		=	0
      for j in range(len(snake_case_							)							):
            a_n += digits[j] * 10**j
      return a_n


if __name__ == "__main__":
  print(f'{solution() = }')







"""simple docstring"""


import os

a					:List[str]    = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1_000}




def  _lowercase					(    __lowerCAmelCase							)       ->				int:
      SCREAMING_SNAKE_CASE__   :      Any      		=	0

      SCREAMING_SNAKE_CASE__   :      Dict      		=	0
      while index < len(__lowerCAmelCase							) - 1:
            SCREAMING_SNAKE_CASE__   :      List[Any]      		=	SYMBOLS[numerals[index]]
            SCREAMING_SNAKE_CASE__   :      Dict      		=	SYMBOLS[numerals[index + 1]]
            if current_value < next_value:
                  total_value -= current_value
            else:
                  total_value += current_value
            index += 1
      total_value += SYMBOLS[numerals[index]]

      return total_value




def  _lowercase					(    __lowerCAmelCase							)       ->				str:
      SCREAMING_SNAKE_CASE__   :      Optional[int]      		=	""""""

      SCREAMING_SNAKE_CASE__   :      int      		=	num // 1000
      numerals += m_count * "M"
      num %= 1000

      SCREAMING_SNAKE_CASE__   :      List[str]      		=	num // 100
      if c_count == 9:
            numerals += "CM"
            c_count -= 9
      elif c_count == 4:
            numerals += "CD"
            c_count -= 4
      if c_count >= 5:
            numerals += "D"
            c_count -= 5
      numerals += c_count * "C"
      num %= 100

      SCREAMING_SNAKE_CASE__   :      List[Any]      		=	num // 10
      if x_count == 9:
            numerals += "XC"
            x_count -= 9
      elif x_count == 4:
            numerals += "XL"
            x_count -= 4
      if x_count >= 5:
            numerals += "L"
            x_count -= 5
      numerals += x_count * "X"
      num %= 10

      if num == 9:
            numerals += "IX"
            num -= 9
      elif num == 4:
            numerals += "IV"
            num -= 4
      if num >= 5:
            numerals += "V"
            num -= 5
      numerals += num * "I"

      return numerals




def  _lowercase					(    __lowerCAmelCase = "/p089_roman.txt"							)       ->				int:
      SCREAMING_SNAKE_CASE__   :      int      		=	0

      with open(os.path.dirname(__lowerCAmelCase							) + roman_numerals_filename							) as filea:
            SCREAMING_SNAKE_CASE__   :      str      		=	filea.readlines()

      for line in lines:
            SCREAMING_SNAKE_CASE__   :      Union[str, Any]      		=	line.strip()
            SCREAMING_SNAKE_CASE__   :      Dict      		=	parse_roman_numerals(__lowerCAmelCase							)
            SCREAMING_SNAKE_CASE__   :      str      		=	generate_roman_numerals(__lowerCAmelCase							)
            savings += len(__lowerCAmelCase							) - len(__lowerCAmelCase							)

      return savings


if __name__ == "__main__":
  print(f'{solution() = }')




