Fixes: #3869: Optimize CI runtime of Project Euler's Problem 74's Solution 2
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 0cecae28d51d..afae5fa17542 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -205,6 +205,7 @@
   * [Heaps Algorithm](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm.py)
   * [Heaps Algorithm Iterative](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm_iterative.py)
   * [Inversions](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/inversions.py)
+  * [Kth Order Statistic](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/kth_order_statistic.py)
   * [Max Subarray Sum](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/max_subarray_sum.py)
   * [Mergesort](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/mergesort.py)
   * [Power](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/power.py)
@@ -389,6 +390,7 @@
   * [Chudnovsky Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/chudnovsky_algorithm.py)
   * [Collatz Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/collatz_sequence.py)
   * [Combinations](https://github.com/TheAlgorithms/Python/blob/master/maths/combinations.py)
+  * [Decimal Isolate](https://github.com/TheAlgorithms/Python/blob/master/maths/decimal_isolate.py)
   * [Entropy](https://github.com/TheAlgorithms/Python/blob/master/maths/entropy.py)
   * [Eulers Totient](https://github.com/TheAlgorithms/Python/blob/master/maths/eulers_totient.py)
   * [Explicit Euler](https://github.com/TheAlgorithms/Python/blob/master/maths/explicit_euler.py)
@@ -492,6 +494,7 @@
   * [Autocomplete Using Trie](https://github.com/TheAlgorithms/Python/blob/master/other/autocomplete_using_trie.py)
   * [Binary Exponentiation](https://github.com/TheAlgorithms/Python/blob/master/other/binary_exponentiation.py)
   * [Binary Exponentiation 2](https://github.com/TheAlgorithms/Python/blob/master/other/binary_exponentiation_2.py)
+  * [Davis–Putnam–Logemann–Loveland](https://github.com/TheAlgorithms/Python/blob/master/other/davis–putnam–logemann–loveland.py)
   * [Detecting English Programmatically](https://github.com/TheAlgorithms/Python/blob/master/other/detecting_english_programmatically.py)
   * [Dijkstra Bankers Algorithm](https://github.com/TheAlgorithms/Python/blob/master/other/dijkstra_bankers_algorithm.py)
   * [Doomsday](https://github.com/TheAlgorithms/Python/blob/master/other/doomsday.py)
@@ -659,6 +662,8 @@
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_048/sol1.py)
   * Problem 049
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_049/sol1.py)
+  * Problem 050
+    * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_050/sol1.py)
   * Problem 051
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_051/sol1.py)
   * Problem 052
@@ -680,6 +685,8 @@
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_062/sol1.py)
   * Problem 063
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_063/sol1.py)
+  * Problem 064
+    * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_064/sol1.py)
   * Problem 065
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_065/sol1.py)
   * Problem 067
@@ -693,6 +700,7 @@
     * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_072/sol2.py)
   * Problem 074
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol1.py)
+    * [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol2.py)
   * Problem 075
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_075/sol1.py)
   * Problem 076
@@ -717,6 +725,8 @@
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_119/sol1.py)
   * Problem 120
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_120/sol1.py)
+  * Problem 123
+    * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_123/sol1.py)
   * Problem 125
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_125/sol1.py)
   * Problem 173
@@ -725,12 +735,16 @@
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_174/sol1.py)
   * Problem 191
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_191/sol1.py)
+  * Problem 203
+    * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_203/sol1.py)
   * Problem 206
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_206/sol1.py)
   * Problem 207
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_207/sol1.py)
   * Problem 234
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_234/sol1.py)
+  * Problem 301
+    * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_301/sol1.py)
   * Problem 551
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_551/sol1.py)
 
diff --git a/project_euler/problem_074/sol2.py b/project_euler/problem_074/sol2.py
index 0348ef1a6628..689593277a81 100644
--- a/project_euler/problem_074/sol2.py
+++ b/project_euler/problem_074/sol2.py
@@ -16,9 +16,13 @@
     the chains of non repeating items.
     The generation of the chain stops before a repeating item
     or if the size of the chain is greater then the desired one.
-    After generating each chain, the length is checked and the counter increases.
+    After generating each chain, the length is checked and the
+    counter increases.
 """
 
+factorial_cache = {}
+factorial_sum_cache = {}
+
 
 def factorial(a: int) -> int:
     """Returns the factorial of the input a
@@ -36,18 +40,23 @@ def factorial(a: int) -> int:
     if a < 0:
         raise ValueError("Invalid negative input!", a)
 
+    if a in factorial_cache:
+        return factorial_cache[a]
+
     # The case of 0! is handled separately
     if a == 0:
-        return 1
+        factorial_cache[a] = 1
     else:
         # use a temporary support variable to store the computation
+        temporary_number = a
         temporary_computation = 1
 
-        while a > 0:
-            temporary_computation *= a
-            a -= 1
+        while temporary_number > 0:
+            temporary_computation *= temporary_number
+            temporary_number -= 1
 
-        return temporary_computation
+        factorial_cache[a] = temporary_computation
+    return factorial_cache[a]
 
 
 def factorial_sum(a: int) -> int:
@@ -57,7 +66,8 @@ def factorial_sum(a: int) -> int:
     >>> factorial_sum(69)
     363600
     """
-
+    if a in factorial_sum_cache:
+        return factorial_sum_cache[a]
     # Prepare a variable to hold the computation
     fact_sum = 0
 
@@ -67,17 +77,15 @@ def factorial_sum(a: int) -> int:
     """
     for i in str(a):
         fact_sum += factorial(int(i))
-
+    factorial_sum_cache[a] = fact_sum
     return fact_sum
 
 
 def solution(chain_length: int = 60, number_limit: int = 1000000) -> int:
     """Returns the number of numbers that produce
         chains with exactly 60 non repeating elements.
-    >>> solution(60,1000000)
-    402
-    >>> solution(15,1000000)
-    17800
+    >>> solution(10, 1000)
+    26
     """
 
     # the counter for the chains with the exact desired length
@@ -86,25 +94,27 @@ def solution(chain_length: int = 60, number_limit: int = 1000000) -> int:
     for i in range(1, number_limit + 1):
 
         # The temporary list will contain the elements of the chain
-        chain_list = [i]
+        chain_set = {i}
+        len_chain_set = 1
+        last_chain_element = i
 
         # The new element of the chain
-        new_chain_element = factorial_sum(chain_list[-1])
-
-        """ Stop computing the chain when you find a repeating item
-            or the length it greater then the desired one.
-        """
-        while not (new_chain_element in chain_list) and (
-            len(chain_list) <= chain_length
-        ):
-            chain_list += [new_chain_element]
-
-            new_chain_element = factorial_sum(chain_list[-1])
-
-        """ If the while exited because the chain list contains the exact amount of elements
-            increase the counter
-        """
-        chain_counter += len(chain_list) == chain_length
+        new_chain_element = factorial_sum(last_chain_element)
+
+        # Stop computing the chain when you find a repeating item
+        # or the length it greater then the desired one.
+
+        while new_chain_element not in chain_set and len_chain_set <= chain_length:
+            chain_set.add(new_chain_element)
+
+            len_chain_set += 1
+            last_chain_element = new_chain_element
+            new_chain_element = factorial_sum(last_chain_element)
+
+        # If the while exited because the chain list contains the exact amount
+        # of elements increase the counter
+        if len_chain_set == chain_length:
+            chain_counter += 1
 
     return chain_counter
 



fixes: #3869 

### **Describe your change:**

- Optimize Project Euler's Problem 74's  Solution #2 using caches of factorials and sums of factorials of digits of a number
- Fix typo for Project Euler's Problem 74's  Solution #1 because of which it wasn't running on CI for running solutions


* [ ] Add an algorithm?
* [x] Fix a bug or typo in an existing algorithm?
* [ ] Documentation change?

### **Checklist:**
* [x] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md).
* [x] This pull request is all my own work -- I have not plagiarized.
* [x] I know that pull requests will not be merged if they fail the automated tests.
* [x] This PR only changes one algorithm file.  To ease review, please open separate PRs for separate algorithms.
* [x] All new Python files are placed inside an existing directory.
* [x] All filenames are in all lowercase characters with no spaces or dashes.
* [x] All functions and variable names follow Python naming conventions.
* [x] All function parameters and return values are annotated with Python [type hints](https://docs.python.org/3/library/typing.html).
* [x] All functions have [doctests](https://docs.python.org/3/library/doctest.html) that pass the automated testing.
* [x] All new algorithms have a URL in its comments that points to Wikipedia or other similar explanation.
* [x] If this pull request resolves one or more open issues then the commit message contains `Fixes: #{$ISSUE_NO}`.
