From e040ad2a01d2c7d7524682fb27da99aea663972b Mon Sep 17 00:00:00 2001
From: Iqrar Agalosi Nureyza <misteriqrar@gmail.com>
Date: Mon, 5 Oct 2020 09:57:09 +0700
Subject: [PATCH] Add a solution for Project Euler 49 (#2702)

* added doctests in modular_exponential.py

* added doctests in modular_exponential.py

* added URL link

* updating DIRECTORY.md

* Add problem 49 solution

* updating DIRECTORY.md

* Fix several mistakes

These fixes are intended to follow the CONTRIBUTING.md

* Move the import statements lower

* Update project_euler/problem_49/sol1.py

Co-authored-by: Dhruv <dhruvmanila@gmail.com>

Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
Co-authored-by: Dhruv <dhruvmanila@gmail.com>
---
 DIRECTORY.md                         |   2 +
 project_euler/problem_49/__init__.py |   0
 project_euler/problem_49/sol1.py     | 139 +++++++++++++++++++++++++++
 3 files changed, 141 insertions(+)
 create mode 100644 project_euler/problem_49/__init__.py
 create mode 100644 project_euler/problem_49/sol1.py

diff --git a/DIRECTORY.md b/DIRECTORY.md
index 1dd1289ab..a8d00f6cb 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -633,6 +633,8 @@
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_47/sol1.py)
   * Problem 48
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_48/sol1.py)
+  * Problem 49
+    * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_49/sol1.py)
   * Problem 52
     * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_52/sol1.py)
   * Problem 53
diff --git a/project_euler/problem_49/__init__.py b/project_euler/problem_49/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/project_euler/problem_49/sol1.py b/project_euler/problem_49/sol1.py
new file mode 100644
index 000000000..6c3d69ad0
--- /dev/null
+++ b/project_euler/problem_49/sol1.py
@@ -0,0 +1,139 @@
+"""
+Prime permutations
+
+Problem 49
+
+The arithmetic sequence, 1487, 4817, 8147, in which each of
+the terms increases by 3330, is unusual in two ways:
+(i) each of the three terms are prime,
+(ii) each of the 4-digit numbers are permutations of one another.
+
+There are no arithmetic sequences made up of three 1-, 2-, or 3-digit primes,
+exhibiting this property, but there is one other 4-digit increasing sequence.
+
+What 12-digit number do you form by concatenating the three terms in this sequence?
+
+Solution:
+
+First, we need to generate all 4 digits prime numbers. Then greedy
+all of them and use permutation to form new numbers. Use binary search
+to check if the permutated numbers is in our prime list and include
+them in a candidate list.
+
+After that, bruteforce all passed candidates sequences using
+3 nested loops since we know the answer will be 12 digits.
+The bruteforce of this solution will be about 1 sec.
+"""
+
+from itertools import permutations
+from math import floor, sqrt
+
+
+def is_prime(number: int) -> bool:
+    """
+    function to check whether the number is prime or not.
+    >>> is_prime(2)
+    True
+    >>> is_prime(6)
+    False
+    >>> is_prime(1)
+    False
+    >>> is_prime(-800)
+    False
+    >>> is_prime(104729)
+    True
+    """
+
+    if number < 2:
+        return False
+
+    for i in range(2, floor(sqrt(number)) + 1):
+        if number % i == 0:
+            return False
+
+    return True
+
+
+def search(target: int, prime_list: list) -> bool:
+    """
+    function to search a number in a list using Binary Search.
+    >>> search(3, [1, 2, 3])
+    True
+    >>> search(4, [1, 2, 3])
+    False
+    >>> search(101, list(range(-100, 100)))
+    False
+    """
+
+    left, right = 0, len(prime_list) - 1
+    while left <= right:
+        middle = (left + right) // 2
+        if prime_list[middle] == target:
+            return True
+        elif prime_list[middle] < target:
+            left = middle + 1
+        else:
+            right = middle - 1
+
+    return False
+
+
+def solution():
+    """
+    Return the solution of the problem.
+    >>> solution()
+    296962999629
+    """
+    prime_list = [n for n in range(1001, 10000, 2) if is_prime(n)]
+    candidates = []
+
+    for number in prime_list:
+        tmp_numbers = []
+
+        for prime_member in permutations(list(str(number))):
+            prime = int("".join(prime_member))
+
+            if prime % 2 == 0:
+                continue
+
+            if search(prime, prime_list):
+                tmp_numbers.append(prime)
+
+        tmp_numbers.sort()
+        if len(tmp_numbers) >= 3:
+            candidates.append(tmp_numbers)
+
+    passed = []
+    for candidate in candidates:
+        length = len(candidate)
+        found = False
+
+        for i in range(length):
+            for j in range(i + 1, length):
+                for k in range(j + 1, length):
+                    if (
+                        abs(candidate[i] - candidate[j])
+                        == abs(candidate[j] - candidate[k])
+                        and len(set([candidate[i], candidate[j], candidate[k]])) == 3
+                    ):
+                        passed.append(
+                            sorted([candidate[i], candidate[j], candidate[k]])
+                        )
+                        found = True
+
+                    if found:
+                        break
+                if found:
+                    break
+            if found:
+                break
+
+    answer = set()
+    for seq in passed:
+        answer.add("".join([str(i) for i in seq]))
+
+    return max([int(x) for x in answer])
+
+
+if __name__ == "__main__":
+    print(solution())