




from math import factorial

_lowerCamelCase      			=						{str(digit): factorial(digit) for digit in range(10)}




def  SCREAMING_SNAKE_CASE     (	__UpperCamelCase      :						int				)  ->							int:
    if not isinstance(__UpperCamelCase	,					__UpperCamelCase				):
        raise TypeError('''Parameter number must be int'''				)

    if number < 0:
        raise ValueError('''Parameter number must be greater than or equal to 0'''				)

    # Converts number in string to iterate on its digits and adds its factorial.
    return sum(DIGIT_FACTORIAL[digit] for digit in str(__UpperCamelCase				)				)




def  SCREAMING_SNAKE_CASE     (	__UpperCamelCase      :						int = 60	,					__UpperCamelCase      :						int = 100_0000				)  ->							int:

    if not isinstance(__UpperCamelCase	,					__UpperCamelCase				) or not isinstance(__UpperCamelCase	,					__UpperCamelCase				):
        raise TypeError('''Parameters chain_length and number_limit must be int'''				)

    if chain_length <= 0 or number_limit <= 0:
        raise ValueError(
            '''Parameters chain_length and number_limit must be greater than 0'''				)

    # the counter for the chains with the exact desired length
    UpperCAmelCase_										=					0
    # the cached sizes of the previous chains
    UpperCAmelCase_										=					{}

    for start_chain_element in range(1	,					__UpperCamelCase				):
        # The temporary set will contain the elements of the chain
        UpperCAmelCase_										=					set()
        UpperCAmelCase_										=					0

        # Stop computing the chain when you find a cached size, a repeating item or the
        # length is greater then the desired one.
        UpperCAmelCase_										=					start_chain_element
        while (
            chain_element not in chain_sets_lengths
            and chain_element not in chain_set
            and chain_set_length <= chain_length
        ):
            chain_set.add(__UpperCamelCase				)
            chain_set_length += 1
            UpperCAmelCase_										=					digit_factorial_sum(__UpperCamelCase				)

        if chain_element in chain_sets_lengths:
            chain_set_length += chain_sets_lengths[chain_element]

        UpperCAmelCase_										=					chain_set_length

        # If chain contains the exact amount of elements increase the counter
        if chain_set_length == chain_length:
            chains_counter += 1

    return chains_counter


if __name__ == "__main__":
 import doctest

 doctest.testmod()
 print(F"{solution()}")











from __future__ import annotations

import os
from collections.abc import Mapping

_lowerCamelCase      			=						tuple[int, int]



class       a					:

     '''simple docstring'''





     def __init__(     self       :      str ,   __snake_case       :      set[int] ,   __snake_case       :      Mapping[EdgeT, int]    ):
         UpperCAmelCase_										=					vertices
         UpperCAmelCase_										=					{
             (min(__snake_case    ), max(__snake_case    )): weight for edge, weight in edges.items()
         }
     def   lowerCamelCase_       (     self       :      Any ,   __snake_case       :      EdgeT ,   __snake_case       :      int    ):
         self.vertices.add(edge[0]    )
         self.vertices.add(edge[1]    )
         UpperCAmelCase_										=					weight




     def   lowerCamelCase_       (     self       :      Union[str, Any]    ):
         UpperCAmelCase_										=					Graph({min(self.vertices    )} ,   {}    )
         UpperCAmelCase_										=					42
         UpperCAmelCase_										=					42
         UpperCAmelCase_										=					42
         UpperCAmelCase_										=					42

         while len(subgraph.vertices    ) < len(self.vertices    ):
             UpperCAmelCase_										=					max(self.edges.values()    ) + 1
             for edge, weight in self.edges.items():
                 if (edge[0] in subgraph.vertices) ^ (edge[1] in subgraph.vertices):
                     if weight < min_weight:
                         UpperCAmelCase_										=					edge
                         UpperCAmelCase_										=					weight

             subgraph.add_edge(__snake_case ,   __snake_case    )

         return subgraph




def  SCREAMING_SNAKE_CASE     (	__UpperCamelCase      :						str = "p107_network.txt"				)  ->							int:
    UpperCAmelCase_										=					os.path.abspath(os.path.dirname(__UpperCamelCase				)				)
    UpperCAmelCase_										=					os.path.join(__UpperCamelCase	,					__UpperCamelCase				)
    UpperCAmelCase_										=					{}
    UpperCAmelCase_										=					42
    UpperCAmelCase_										=					42
    UpperCAmelCase_										=					42

    with open(__UpperCamelCase				) as f:
        UpperCAmelCase_										=					f.read().strip().split('''\n'''				)

    UpperCAmelCase_										=					[line.split(''','''				) for line in data]

    for edgea in range(1	,					len(__UpperCamelCase				)				):
        for edgea in range(__UpperCamelCase				):
            if adjaceny_matrix[edgea][edgea] != "-":
                UpperCAmelCase_										=					int(adjaceny_matrix[edgea][edgea]				)

    UpperCAmelCase_										=					Graph(set(range(len(__UpperCamelCase				)				)				)	,					__UpperCamelCase				)

    UpperCAmelCase_										=					graph.prims_algorithm()

    UpperCAmelCase_										=					sum(graph.edges.values()				)
    UpperCAmelCase_										=					sum(subgraph.edges.values()				)

    return initial_total - optimal_total


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





