From 33d8869e6db8265ee56f97ee323cb54a203ddc30 Mon Sep 17 00:00:00 2001
From: mindaugl <mindelek@gmail.com>
Date: Sun, 6 Apr 2025 16:01:11 +0800
Subject: [PATCH 1/3] Add initial files for the euler project problem 127
 solution.

---
 project_euler/problem_127/__init__.py |  0
 project_euler/problem_127/sol1.py     | 65 +++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)
 create mode 100644 project_euler/problem_127/__init__.py
 create mode 100644 project_euler/problem_127/sol1.py

diff --git a/project_euler/problem_127/__init__.py b/project_euler/problem_127/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/project_euler/problem_127/sol1.py b/project_euler/problem_127/sol1.py
new file mode 100644
index 000000000000..b89b83ded644
--- /dev/null
+++ b/project_euler/problem_127/sol1.py
@@ -0,0 +1,65 @@
+from numpy import sqrt
+
+N = 120000
+
+
+def generate_primes(n: int):
+    primes = [True] * (n + 1)
+    primes[0] = primes[1] = False
+    for i in range(2, int(sqrt(n + 1)) + 1):
+        if primes[i]:
+            j = i * i
+            while j <= n:
+                primes[j] = False
+                j += i
+    return primes
+
+
+def rad(n: int, primes_list: list[int]):
+    f = 1
+    for p in primes_list:
+        if p > n:
+            break
+        if n % p == 0:
+            f *= p
+    return f
+
+
+def gcd(a: int, b: int):
+    while b:
+        a, b = b, a % b
+    return a
+
+
+def solution(c_less: int = 120000) -> int:
+    primes_bool = generate_primes(c_less)
+    primes_list = []
+    print("primes generated")
+    for i in range(2, len(primes_bool)):
+        if primes_bool[i]:
+            primes_list += [i]
+
+    rads = [1] * (c_less + 1)
+    for i in range(c_less + 1):
+        if i % 100 == 0:
+            print("rads", i)
+        rads[i] = rad(i, primes_list)
+
+    sum_c = 0
+    print("start main")
+    for a in range(1, c_less):
+        rad_a = rads[a]
+        if a % 2 == 1:
+            r = range(1, min(a, c_less - a))
+        else:
+            r = range(1, min(a, c_less - a), 2)
+        for b in r:
+            c = a + b
+            if rad_a * rads[b] * rads[c] < c and gcd(rad_a, rads[b]) == 1:
+                sum_c += c
+
+    return sum_c
+
+
+if __name__ == "__main__":
+    print(f"{solution() = }")

From 249109569bafc79547d2404ffeecb0905fbf34b3 Mon Sep 17 00:00:00 2001
From: mindaugl <mindelek@gmail.com>
Date: Sun, 6 Apr 2025 16:18:42 +0800
Subject: [PATCH 2/3] Add documentation for the euler project problem 127
 solution.

---
 project_euler/problem_127/sol1.py | 35 ++++++++++++++++++++++++++-----
 1 file changed, 30 insertions(+), 5 deletions(-)

diff --git a/project_euler/problem_127/sol1.py b/project_euler/problem_127/sol1.py
index b89b83ded644..1e8f91419da5 100644
--- a/project_euler/problem_127/sol1.py
+++ b/project_euler/problem_127/sol1.py
@@ -1,9 +1,24 @@
+"""
+Project Euler Problem 127: https://projecteuler.net/problem=127
+
+abc-hits
+
+It takes about 10 minutes to run.
+'Brute-force' solution that uses the following simplifications:
+- if gcd(a, b) = 1 then gcd(a, c) = 1 and gcd(b, c) = 1
+- rad(a*b*c) = rad(a) * rad(b) * rad(c), for gcd(a, b) = 1
+- if a is even, b cannot b even for gcd(a, b) = 1 to be true.
+"""
+
 from numpy import sqrt
 
 N = 120000
 
 
-def generate_primes(n: int):
+def generate_primes(n: int) -> list[bool]:
+    """
+    Generates primes boolean array up to n.
+    """
     primes = [True] * (n + 1)
     primes[0] = primes[1] = False
     for i in range(2, int(sqrt(n + 1)) + 1):
@@ -15,7 +30,11 @@ def generate_primes(n: int):
     return primes
 
 
-def rad(n: int, primes_list: list[int]):
+def rad(n: int, primes_list: list[int]) -> int:
+    """
+    Calculated rad - product of unique prime factors for n, using prime numbers
+    list primes_list.
+    """
     f = 1
     for p in primes_list:
         if p > n:
@@ -25,16 +44,23 @@ def rad(n: int, primes_list: list[int]):
     return f
 
 
-def gcd(a: int, b: int):
+def gcd(a: int, b: int) -> int:
+    """
+    Calculates greatest common divisor of a and b.
+
+    """
     while b:
         a, b = b, a % b
     return a
 
 
 def solution(c_less: int = 120000) -> int:
+    """
+    Calculates all primes, rads, and then loops over a, b checking the conditions.
+
+    """
     primes_bool = generate_primes(c_less)
     primes_list = []
-    print("primes generated")
     for i in range(2, len(primes_bool)):
         if primes_bool[i]:
             primes_list += [i]
@@ -46,7 +72,6 @@ def solution(c_less: int = 120000) -> int:
         rads[i] = rad(i, primes_list)
 
     sum_c = 0
-    print("start main")
     for a in range(1, c_less):
         rad_a = rads[a]
         if a % 2 == 1:

From cee612502378b36f579fec936e25e0dcdbcafeab Mon Sep 17 00:00:00 2001
From: mindaugl <mindelek@gmail.com>
Date: Sun, 6 Apr 2025 16:29:15 +0800
Subject: [PATCH 3/3] Add test case and remove print() for the euler project
 problem 127 solution.

---
 project_euler/problem_127/sol1.py | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/project_euler/problem_127/sol1.py b/project_euler/problem_127/sol1.py
index 1e8f91419da5..17e888438355 100644
--- a/project_euler/problem_127/sol1.py
+++ b/project_euler/problem_127/sol1.py
@@ -8,6 +8,9 @@
 - if gcd(a, b) = 1 then gcd(a, c) = 1 and gcd(b, c) = 1
 - rad(a*b*c) = rad(a) * rad(b) * rad(c), for gcd(a, b) = 1
 - if a is even, b cannot b even for gcd(a, b) = 1 to be true.
+
+>>> solution(1000)
+12523
 """
 
 from numpy import sqrt
@@ -18,6 +21,11 @@
 def generate_primes(n: int) -> list[bool]:
     """
     Generates primes boolean array up to n.
+
+    >>> generate_primes(2)
+    [False, False, True]
+    >>> generate_primes(5)
+    [False, False, True, True, False, True]
     """
     primes = [True] * (n + 1)
     primes[0] = primes[1] = False
@@ -34,6 +42,11 @@ def rad(n: int, primes_list: list[int]) -> int:
     """
     Calculated rad - product of unique prime factors for n, using prime numbers
     list primes_list.
+
+    >>> rad(1, [1])
+    1
+    >>> rad(12, [2, 3])
+    6
     """
     f = 1
     for p in primes_list:
@@ -48,6 +61,10 @@ def gcd(a: int, b: int) -> int:
     """
     Calculates greatest common divisor of a and b.
 
+    >>> gcd(1, 10)
+    1
+    >>> gcd(14, 48)
+    2
     """
     while b:
         a, b = b, a % b
@@ -58,6 +75,10 @@ def solution(c_less: int = 120000) -> int:
     """
     Calculates all primes, rads, and then loops over a, b checking the conditions.
 
+    >>> solution(10)
+    9
+    >>> solution(100)
+    316
     """
     primes_bool = generate_primes(c_less)
     primes_list = []
@@ -67,8 +88,6 @@ def solution(c_less: int = 120000) -> int:
 
     rads = [1] * (c_less + 1)
     for i in range(c_less + 1):
-        if i % 100 == 0:
-            print("rads", i)
         rads[i] = rad(i, primes_list)
 
     sum_c = 0