code: 
  
  
  
  
  
  from __future__ import annotations
  
  from collections.abc import Iterable
  from dataclasses import dataclass
  from typing import Any
  
  
  
  
  class   _UpperCAmelCase	:
  					__A          =   ("_front", "_back", "_len")
  
  
  
  
  					@dataclass
  					class   _UpperCAmelCase	:
  										__A          =   None
  										__A          =   None
  										__A          =   None
  
  
  
  
  					class   _UpperCAmelCase	:
  										__A          =   ("_cur",)
  
  
  
  
  										def __init__(						self    ,      __lowerCAmelCase       )						->  None:
  												UpperCamelCase__         =	cur
  
  
  
  
  										def __iter__(						self       )						->  Deque._Iterator:
  												return self
  
  
  
  
  										def 	snake_case_		(						self       )						->  Any:
  												if self._cur is None:
  														# finished iterating
  														raise StopIteration
  												UpperCamelCase__         =	self._cur.val
  												UpperCamelCase__         =	self._cur.next_node
  
  												return val
  
  
  
  
  					def __init__(						self    ,      __lowerCAmelCase = None       )						->  None:
  							UpperCamelCase__         =	None
  							UpperCamelCase__         =	None
  							UpperCamelCase__         =	0
  
  							if iterable is not None:
  									# append every value to the deque
  									for val in iterable:
  											self.append(__lowerCAmelCase       )
  
  
  
  
  					def 	snake_case_		(						self    ,      __lowerCAmelCase       )						->  None:
  							UpperCamelCase__         =	self._Node(__lowerCAmelCase    ,      __lowerCAmelCase    ,      __lowerCAmelCase       )
  							if self.is_empty():
  									# front = back
  									UpperCamelCase__         =	UpperCamelCase__         =	node
  									UpperCamelCase__         =	1
  							else:
  									# connect nodes
  									UpperCamelCase__         =	node
  									UpperCamelCase__         =	self._back
  									UpperCamelCase__         =	node  # assign new back to the new node
  
  									self._len += 1
  
  									# make sure there were no errors
  									assert not self.is_empty(), "Error on appending value."
  
  
  
  
  					def 	snake_case_		(						self    ,      __lowerCAmelCase       )						->  None:
  							UpperCamelCase__         =	self._Node(__lowerCAmelCase    ,      __lowerCAmelCase    ,      __lowerCAmelCase       )
  							if self.is_empty():
  									# front = back
  									UpperCamelCase__         =	UpperCamelCase__         =	node
  									UpperCamelCase__         =	1
  							else:
  									# connect nodes
  									UpperCamelCase__         =	self._front
  									UpperCamelCase__         =	node
  									UpperCamelCase__         =	node  # assign new front to the new node
  
  									self._len += 1
  
  									# make sure there were no errors
  									assert not self.is_empty(), "Error on appending value."
  
  
  
  
  					def 	snake_case_		(						self    ,      __lowerCAmelCase       )						->  None:
  							for val in iterable:
  									self.append(__lowerCAmelCase       )
  
  
  
  
  					def 	snake_case_		(						self    ,      __lowerCAmelCase       )						->  None:
  							for val in iterable:
  									self.appendleft(__lowerCAmelCase       )
  
  
  
  
  					def 	snake_case_		(						self       )						->  Any:
  							assert not self.is_empty(), "Deque is empty."
  
  							UpperCamelCase__         =	self._back
  							UpperCamelCase__         =	self._back.prev_node  # set new back
  							# drop the last node - python will deallocate memory automatically
  							UpperCamelCase__         =	None
  
  							self._len -= 1
  
  							return topop.val
  
  
  
  
  					def 	snake_case_		(						self       )						->  Any:
  							assert not self.is_empty(), "Deque is empty."
  
  							UpperCamelCase__         =	self._front
  							UpperCamelCase__         =	self._front.next_node  # set new front and drop the first node
  							UpperCamelCase__         =	None
  
  							self._len -= 1
  
  							return topop.val
  
  
  
  
  					def 	snake_case_		(						self       )						->  bool:
  							return self._front is None
  
  
  
  
  					def __len__(						self       )						->  int:
  							return self._len
  
  
  
  
  					def __eq__(						self    ,      __lowerCAmelCase       )						->  bool:
  
  							if not isinstance(__lowerCAmelCase    ,      __lowerCAmelCase       ):
  									return NotImplemented
  
  							UpperCamelCase__         =	self._front
  							UpperCamelCase__         =	other._front
  
  							# if the length of the dequeues are not the same, they are not equal
  							if len(self       ) != len(__lowerCAmelCase       ):
  									return False
  
  							while me is not None and oth is not None:
  									# compare every value
  									if me.val != oth.val:
  											return False
  									UpperCamelCase__         =	me.next_node
  									UpperCamelCase__         =	oth.next_node
  
  							return True
  
  
  
  
  					def __iter__(						self       )						->  Deque._Iterator:
  							return Deque._Iterator(self._front       )
  
  
  
  
  					def __repr__(						self       )						->  str:
  							UpperCamelCase__         =	[]
  							UpperCamelCase__         =	self._front
  							while aux is not None:
  									# append the values in a list to display
  									values_list.append(aux.val       )
  									UpperCamelCase__         =	aux.next_node
  
  							return F"""[{', '.join(repr(__lowerCAmelCase       ) for val in values_list       )}]"""
  
  
  if __name__ == "__main__":
  				import doctest
  
  				doctest.testmod()
  
  
  
  
  
  
style_context: 
  
  
  
  
  
  __lowerCAmelCase     =			{
      "0": 1,
      "1": 1,
      "2": 2,
      "3": 6,
      "4": 24,
      "5": 120,
      "6": 720,
      "7": 5_040,
      "8": 40_320,
      "9": 362_880,
  }
  
  __lowerCAmelCase     =			{145: 145}
  
  __lowerCAmelCase     =			{
      145: 0,
      169: 3,
      36_301: 3,
      1_454: 3,
      871: 2,
      45_361: 2,
      872: 2,
  }
  
  def     a						(      _lowercase   :     int       )     ->int:
  		if n in CACHE_SUM_DIGIT_FACTORIALS:
  				return CACHE_SUM_DIGIT_FACTORIALS[n]
  		UpperCamelCase__         =	sum(DIGIT_FACTORIALS[let] for let in str(_lowercase       )       )
  		UpperCamelCase__         =	ret
  		return ret
  
  def     a						(      _lowercase   :     int ,						_lowercase   :     set | None = None       )     ->int:
  		UpperCamelCase__         =	previous or set()
  		if n in CHAIN_LENGTH_CACHE:
  				return CHAIN_LENGTH_CACHE[n]
  		UpperCamelCase__         =	sum_digit_factorials(_lowercase       )
  		if next_number in previous:
  				UpperCamelCase__         =	0
  				return 0
  		else:
  				previous.add(_lowercase       )
  				UpperCamelCase__         =	1 + chain_length(_lowercase ,						_lowercase       )
  				UpperCamelCase__         =	ret
  				return ret
  
  def     a						(      _lowercase   :     int = 6_0 ,						_lowercase   :     int = 1_0_0_0_0_0_0       )     ->int:
  		return sum(1 for i in range(1 ,						_lowercase       ) if chain_length(_lowercase       ) == num_terms       )
  
  
  if __name__ == "__main__":
  				print(f"""{solution() = }""")
  
  
  
  
  
  