diff --git a/README.md b/README.md
index b7cb85220..f080a1cc9 100644
--- a/README.md
+++ b/README.md
@@ -57,38 +57,17 @@ Link to commit:(same as for the first one)
Screenshot of branch measurement:
![image](https://github.com/CatalinAnt/algorithms-SEP-95/assets/113595149/94eec9b6-3dd6-46e3-b087-40892eccc10e)
-#### Abdullah Abdelkhalik
-
-pythagoras
-
-https://github.com/CatalinAnt/algorithms-SEP-95/commit/5651abafebe8ae3a5ea63e74883bb991acf19303
-![pythagoras_hits](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/0df1fa2b-2185-4b9f-ae65-5d969edb009b)
-first_unique_char
-https://github.com/CatalinAnt/algorithms-SEP-95/commit/c16f26e952322b2c1729778a4141a57103ba7658
-![first_unique_char_hits](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/10d7c45c-398e-4408-8f11-6771f51fa95c)
-#### Abdullah Abdelkhalik
-pythagoras
-https://github.com/CatalinAnt/algorithms-SEP-95/commit/5651abafebe8ae3a5ea63e74883bb991acf19303
-
-![pythagoras_hits](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/0df1fa2b-2185-4b9f-ae65-5d969edb009b)
-
-
-first_unique_char
-
-https://github.com/CatalinAnt/algorithms-SEP-95/commit/c16f26e952322b2c1729778a4141a57103ba7658
-
-![first_unique_char_hits](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/10d7c45c-398e-4408-8f11-6771f51fa95c)
#### Almuthana Almustafa
@@ -110,6 +89,41 @@ result:
![alt text](result_image_2.png)
+#### Ayman Errahmouni
+
+##### Function 1: simplify_path_v2
+
+[Link the commit](https://github.com/CatalinAnt/algorithms-SEP-95/pull/2/commits/22ee6fa1df4785596c603af61a725c558973eb0b)
+
+Screenshot of branch measurement:
+![alt text](image-7.png)
+
+##### Function 2: insertion_sort
+
+[Link to commit](https://github.com/CatalinAnt/algorithms-SEP-95/pull/2/commits/5dae7f28036f89b7f6ff673639a922dd714aff3e)
+
+Screenshot of branch measurement:
+![alt text](image-11.png)
+
+#### Catalin Antonescu
+
+##### Function 1: strong_password
+
+Link to commit:
+[https://github.com/CatalinAnt/algorithms-SEP-95/commit/eaad6d32ecd73bb8fde876a4d4852cb522aea6f8](https://github.com/CatalinAnt/algorithms-SEP-95/commit/2b0b9187c1c040e4476b1ca14f2c2249273566b7)
+
+Screenshot of branch measurement:
+![image](https://github.com/CatalinAnt/algorithms-SEP-95/assets/113595149/e718a47f-5ea0-412c-b250-25a193412164)
+
+##### Function 2: rotate_image
+
+Link to commit:(same as for the first one)
+[https://github.com/CatalinAnt/algorithms-SEP-95/commit/eaad6d32ecd73bb8fde876a4d4852cb522aea6f8](https://github.com/CatalinAnt/algorithms-SEP-95/commit/2b0b9187c1c040e4476b1ca14f2c2249273566b7)
+
+Screenshot of branch measurement:
+![image](https://github.com/CatalinAnt/algorithms-SEP-95/assets/113595149/94eec9b6-3dd6-46e3-b087-40892eccc10e)
+
+
## Coverage improvement
### Individual tests
@@ -143,6 +157,7 @@ Old coverage:
Diff (LHS = new code, RHS = old code):
![LHS: new code, RHS: old code](image.png)
+![alt text](image-9.png)
New coverage:
![new coverage result (100%)](image-1.png)
@@ -161,6 +176,8 @@ Diff (LHS: new code, RHS: old code):
![LHS: new code, RHS: old code](image-5.png)
(Changes in imports)
![LHS: new code, RHS: old code](image-6.png)
+(Instrumentation)
+![alt text](image-8.png)
Old coverage:
![Old coverage result (4%)](image-3.png)
@@ -192,7 +209,6 @@ New coverage:
For strong_password there was a 26% coverage improvement with the existing tool and 40% with manual measurement tool.
-
Test 2:
In test_matrix:
@@ -212,27 +228,7 @@ New coverage:
For rotate_image, thre was a 33% coverage improvement with the existing tool and 25% with manual tool.
-## Abdullah Abdelkhalik
-
-test_maths
-
-https://github.com/CatalinAnt/algorithms-SEP-95/commit/60832d9c672efd586848077cc41a52630d34371b
-
-![pythagoras_before](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/cf57112b-1aef-4a10-a41f-bd4b797e2012)
-
-![pythagoras_after](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/1aa45c17-46fc-49d3-944a-03c2276d1be6)
-
-the coverage is improved by 28%, the code only hit one of the five branches and cover only one of the three cases of the pythagoras theory. I added the other two cases, i could have a fourth case where none of the cases is present.
-
-test_strings
-
-https://github.com/CatalinAnt/algorithms-SEP-95/commit/5651abafebe8ae3a5ea63e74883bb991acf19303
-![first_unique_char_before](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/9910ec69-73b0-4c87-afc8-abc01f65a423)
-
-![first_unique_char_after](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/10859fac-776c-4a48-8a1c-9531afcbfa9b)
-
-The coverage is improved by 13%, the code only hit three out of five branches and only set up two examples. I added a case where there is no unique letter.
## Almuthana Almustafa
@@ -267,6 +263,85 @@ existing tool result after:
The coverage improved by 86% due to the creation of new tests.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#### Abdullah Abdelkhalik
+
+
+pythagoras
+
+https://github.com/CatalinAnt/algorithms-SEP-95/commit/5651abafebe8ae3a5ea63e74883bb991acf19303
+
+![pythagoras_hits](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/c61bff67-be7e-4bd2-b892-0a0f2dada1f3)
+
+
+
+
+first_unique_char
+
+https://github.com/CatalinAnt/algorithms-SEP-95/commit/c16f26e952322b2c1729778a4141a57103ba7658
+
+![first_unique_char_hits (2)](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/8c1b704e-cadb-4f54-aea7-795005348538)
+
+
+
+
+
+## Improvements
+
+test_maths
+
+https://github.com/CatalinAnt/algorithms-SEP-95/commit/60832d9c672efd586848077cc41a52630d34371b
+
+![pythagoras_before](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/cf57112b-1aef-4a10-a41f-bd4b797e2012)
+
+![pythagoras_after](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/1aa45c17-46fc-49d3-944a-03c2276d1be6)
+
+the coverage is improved by 28%, the code only hit one of the five branches and cover only one of the three cases of the pythagoras theory. I added the other two cases, i could have a fourth case where none of the cases is present.
+
+test_strings
+
+https://github.com/CatalinAnt/algorithms-SEP-95/commit/5651abafebe8ae3a5ea63e74883bb991acf19303
+
+![first_unique_char_before](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/9910ec69-73b0-4c87-afc8-abc01f65a423)
+
+![first_unique_char_after](https://github.com/CatalinAnt/algorithms-SEP-95/assets/114078193/10859fac-776c-4a48-8a1c-9531afcbfa9b)
+
+The coverage is improved by 13%, the code only hit three out of five branches and only set up two examples. I added a case where there is no unique letter.
+
+
+
+
+
+
+
+
+
+
+
+
+
### Overall
diff --git a/algorithms/maths/find_order_simple.py b/algorithms/maths/find_order_simple.py
index 8f69773c7..732fcae62 100644
--- a/algorithms/maths/find_order_simple.py
+++ b/algorithms/maths/find_order_simple.py
@@ -11,17 +11,42 @@
import math
+branch_coverage = {
+ "branch_6": False,
+ "branch_7": False,
+ "branch_8": False,
+ "branch_9": False,
+ "branch_10": False
+}
+
def find_order(a, n):
"""
Find order for positive integer n and given integer a that satisfies gcd(a, n) = 1.
"""
+
if (a == 1) & (n == 1):
# Exception Handeling : 1 is the order of of 1
+ branch_coverage["branch_6"] = True
+ print("branch_6")
return 1
if math.gcd(a, n) != 1:
+ branch_coverage["branch_7"] = True
+ print("branch_7")
print ("a and n should be relative prime!")
return -1
for i in range(1, n):
+ branch_coverage["branch_8"] = True
+ print("branch_8")
if pow(a, i) % n == 1:
+ branch_coverage["branch_9"] = True
+ print("branch_9")
return i
+ branch_coverage["branch_10"] = True
+ print("branch_10")
return -1
+
+def print_coverage():
+ for branch, hit in branch_coverage.items():
+ print(f"{branch} was {'hit' if hit else 'not hit'}")
+
+print_coverage()
\ No newline at end of file
diff --git a/algorithms/maths/prime_check.py b/algorithms/maths/prime_check.py
index 60e4427ab..532f7afba 100644
--- a/algorithms/maths/prime_check.py
+++ b/algorithms/maths/prime_check.py
@@ -1,17 +1,42 @@
+branch_coverage = {
+ "branch_1": False, # n <= 1
+ "branch_2": False, # n == 2 or n == 3
+ "branch_3": False, # n % 2 == 0 or n % 3 == 0
+ "branch_4": False, # while j * j <= n
+ "branch_5": False # n % j == 0 or n % (j + 2) == 0
+}
def prime_check(n):
"""Return True if n is a prime number
Else return False.
"""
+ print(f"Checking {n}") # Debugging statement
if n <= 1:
+ branch_coverage["branch_1"] = True
+ print("branch_1")
return False
+
if n == 2 or n == 3:
+ branch_coverage["branch_2"] = True
+ print("branch_2")
return True
if n % 2 == 0 or n % 3 == 0:
+ branch_coverage["branch_3"] = True
+ print("branch_3")
return False
j = 5
while j * j <= n:
+ branch_coverage["branch_4"] = True
+ print("branch_4")
if n % j == 0 or n % (j + 2) == 0:
+ branch_coverage["branch_5"] = True
+ print("branch_5")
return False
j += 6
return True
+
+def print_coverage():
+ for branch, hit in branch_coverage.items():
+ print(f"{branch} was {'hit' if hit else 'not hit'}")
+
+print_coverage()
diff --git a/algorithms/maths/pythagoras.py b/algorithms/maths/pythagoras.py
index b24b682ac..386b821b3 100644
--- a/algorithms/maths/pythagoras.py
+++ b/algorithms/maths/pythagoras.py
@@ -2,6 +2,13 @@
Given the lengths of two of the three sides of a right angled triangle, this function returns the
length of the third side.
"""
+branch_coverage = {
+ "branch_31": False,
+ "branch_32": False,
+ "branch_33": False,
+ "branch_34": False,
+ "branch_35": False
+}
def pythagoras(opposite, adjacent, hypotenuse):
"""
@@ -10,11 +17,25 @@ def pythagoras(opposite, adjacent, hypotenuse):
"""
try:
if opposite == str("?"):
+ branch_coverage["branch_31"] = True
return ("Opposite = " + str(((hypotenuse**2) - (adjacent**2))**0.5))
if adjacent == str("?"):
+ branch_coverage["branch_32"] = True
return ("Adjacent = " + str(((hypotenuse**2) - (opposite**2))**0.5))
if hypotenuse == str("?"):
+ branch_coverage["branch_33"] = True
return ("Hypotenuse = " + str(((opposite**2) + (adjacent**2))**0.5))
+ branch_coverage["branch_34"] = True
return "You already know the answer!"
except:
+ branch_coverage["branch_35"] = True
raise ValueError("invalid argument(s) were given.")
+
+def print_coverage():
+ for branch, hit in branch_coverage.items():
+ print(f"{branch} was {'hit' if hit else 'not hit'}")
+
+pythagoras(3, 2, "?")
+
+print_coverage()
+
diff --git a/algorithms/matrix/rotate_image.py b/algorithms/matrix/rotate_image.py
index a8b5e4e77..f525e24bb 100644
--- a/algorithms/matrix/rotate_image.py
+++ b/algorithms/matrix/rotate_image.py
@@ -7,6 +7,14 @@
Could you do this in-place?
"""
+branch_coverage = {
+ "rotate_matrix_1": False, # if not branch for mat
+ "rotate_matrix_2": False, # invisible else branch
+ "rotate_matrix_3": False, # for branch
+ "rotate_matrix_4": False, # for branch
+
+}
+
# clockwise rotate
# first reverse up to down, then swap the symmetry
@@ -16,18 +24,38 @@
def rotate(mat):
if not mat:
+ branch_coverage["rotate_matrix_1"] = True
return mat
+
+ branch_coverage["rotate_matrix_2"] = True
+
mat.reverse()
for i in range(len(mat)):
+ branch_coverage["rotate_matrix_3"] = True
+
for j in range(i):
+ branch_coverage["rotate_matrix_4"] = True
+
mat[i][j], mat[j][i] = mat[j][i], mat[i][j]
return mat
-if __name__ == "__main__":
- mat = [[1, 2, 3],
- [4, 5, 6],
- [7, 8, 9]]
- print(mat)
- rotate(mat)
- print(mat)
+def print_coverage():
+ for branch, hit in branch_coverage.items():
+ print(f"{branch} was {'hit' if hit else 'not hit'}")
+ total = len(branch_coverage)
+ hit = sum(branch_coverage.values())
+ result = hit / total * 100
+
+ print("The total branch coverage is:", result, "%")
+
+
+rotate([])
+print_coverage()
+print("\n")
+print_coverage()
+rotate([[1, 2], [3, 4]])
+print("\n")
+print_coverage()
+rotate([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
+print("\n")
diff --git a/algorithms/search/interpolation_search.py b/algorithms/search/interpolation_search.py
index 5b1d00a1a..98a405431 100644
--- a/algorithms/search/interpolation_search.py
+++ b/algorithms/search/interpolation_search.py
@@ -13,6 +13,15 @@
from typing import List
+branch_coverage = {
+ "branch_60": False,
+ "branch_61": False,
+ "branch_62": False,
+ "branch_63": False,
+ "branch_64": False,
+
+}
+
def interpolation_search(array: List[int], search_key: int) -> int:
"""
@@ -38,24 +47,36 @@ def interpolation_search(array: List[int], search_key: int) -> int:
while (low <= high) and (array[low] <= search_key <= array[high]):
# calculate the search position
+ branch_coverage["branch_60"] = True
pos = low + int(((search_key - array[low]) *
(high - low) / (array[high] - array[low])))
# search_key is found
if array[pos] == search_key:
+ branch_coverage["branch_61"] = True
return pos
# if search_key is larger, search_key is in upper part
if array[pos] < search_key:
+ branch_coverage["branch_62"] = True
low = pos + 1
# if search_key is smaller, search_key is in lower part
else:
+ branch_coverage["branch_63"] = True
high = pos - 1
-
+
+ branch_coverage["branch_64"] = True
return -1
+def print_coverage():
+ for branch, hit in branch_coverage.items():
+ print(f"{branch} was {'hit' if hit else 'not hit'}")
+
+
if __name__ == "__main__":
import doctest
doctest.testmod()
+print_coverage()
+
diff --git a/algorithms/sort/insertion_sort.py b/algorithms/sort/insertion_sort.py
index 06c86228d..f1f7613e4 100644
--- a/algorithms/sort/insertion_sort.py
+++ b/algorithms/sort/insertion_sort.py
@@ -1,3 +1,10 @@
+branch_coverage = {
+ "simulation": False,
+ "for": False,
+ "while": False,
+ "simulation-nested": False,
+}
+
def insertion_sort(arr, simulation=False):
""" Insertion Sort
Complexity: O(n^2)
@@ -5,13 +12,16 @@ def insertion_sort(arr, simulation=False):
iteration = 0
if simulation:
+ branch_coverage["simulation"] = True
print("iteration",iteration,":",*arr)
for i in range(len(arr)):
+ branch_coverage["for"] = True
cursor = arr[i]
pos = i
while pos > 0 and arr[pos - 1] > cursor:
+ branch_coverage["while"] = True
# Swap the number down the list
arr[pos] = arr[pos - 1]
pos = pos - 1
@@ -19,7 +29,25 @@ def insertion_sort(arr, simulation=False):
arr[pos] = cursor
if simulation:
+ branch_coverage["simulation-nested"] = True
iteration = iteration + 1
print("iteration",iteration,":",*arr)
return arr
+
+def print_coverage():
+ covered = 0
+ print("branch coverage for `insertion_sort`:")
+ for branch, hit in branch_coverage.items():
+ print(f"{branch} was {'hit' if hit else 'not hit'}")
+ if hit: covered += 1;
+ print(f"Branch coverage: {covered / len(branch_coverage) * 100}")
+
+insertion_sort([])
+insertion_sort([1])
+insertion_sort([69, 420])
+insertion_sort([420, 69])
+insertion_sort([0, 1, 2, 3, 4, 3, 2, 1, 0])
+insertion_sort([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], True)
+insertion_sort([0, 1, 2, 3, 4, 3, 2, 1, 0], True)
+print_coverage()
diff --git a/algorithms/strings/first_unique_char.py b/algorithms/strings/first_unique_char.py
index 44ba05e49..a1a57b521 100644
--- a/algorithms/strings/first_unique_char.py
+++ b/algorithms/strings/first_unique_char.py
@@ -11,17 +11,39 @@
Reference: https://leetcode.com/problems/first-unique-character-in-a-string/description/
"""
+
+branch_coverage = {
+ "branch_26": False,
+ "branch_27": False,
+ "branch_28": False,
+ "branch_29": False,
+ "branch_30": False,
+}
+
def first_unique_char(s):
"""
:type s: str
:rtype: int
"""
if (len(s) == 1):
+ branch_coverage["branch_26"] = True
return 0
ban = []
for i in range(len(s)):
+ branch_coverage["branch_27"] = True
if all(s[i] != s[k] for k in range(i + 1, len(s))) == True and s[i] not in ban:
+ branch_coverage["branch_28"] = True
return i
else:
+ branch_coverage["branch_29"] = True
ban.append(s[i])
+ branch_coverage["branch_30"] = True
return -1
+
+def print_coverage():
+ for branch, hit in branch_coverage.items():
+ print(f"{branch} was {'hit' if hit else 'not hit'}")
+
+first_unique_char("leetcode")
+first_unique_char("loveleetcode")
+print_coverage()
diff --git a/algorithms/strings/strong_password.py b/algorithms/strings/strong_password.py
index 85acd0223..b3e9317b8 100644
--- a/algorithms/strings/strong_password.py
+++ b/algorithms/strings/strong_password.py
@@ -29,15 +29,53 @@
Output: 1 (Because the password isn't strong, but she can make it strong by adding a single digit.)
"""
+branch_coverage = {
+ "strong_password_1": False, # if branch for any(i.isdigit() for i in password) == False
+ "strong_password_2": False, # if branch for any(i.islower() for i in password) == False
+ "strong_password_3": False, # if branch for any(i.isupper() for i in password) == False
+ "strong_password_4": False, # if branch for any(i in '!@#$%^&*()-+' for i in password) == False
+ "strong_password_5": False # invisible else branch
+
+}
+counter = 0
+
def strong_password(n, password):
count_error = 0
# Return the minimum number of characters to make the password strong
if any(i.isdigit() for i in password) == False:
+ branch_coverage["strong_password_1"] = True
count_error = count_error + 1
if any(i.islower() for i in password) == False:
+ branch_coverage["strong_password_2"] = True
count_error = count_error + 1
if any(i.isupper() for i in password) == False:
+ branch_coverage["strong_password_3"] = True
count_error = count_error + 1
if any(i in '!@#$%^&*()-+' for i in password) == False:
+ branch_coverage["strong_password_4"] = True
count_error = count_error + 1
+
+ branch_coverage["strong_password_5"] = True
return max(count_error, 6 - n)
+
+
+def print_coverage():
+ for branch, hit in branch_coverage.items():
+ print(f"{branch} was {'hit' if hit else 'not hit'}")
+ total = len(branch_coverage)
+ hit = sum(branch_coverage.values())
+ result = hit / total * 100
+ print("The total branch coverage is:", result, "%" )
+
+
+strong_password(11, "#Algorithms")
+print_coverage()
+print("\n")
+strong_password(5, "12345")
+print_coverage()
+print("\n")
+strong_password(5, "abcde")
+print_coverage()
+print("\n")
+strong_password(3, "Ab1")
+print_coverage()
diff --git a/algorithms/unix/path/simplify_path.py b/algorithms/unix/path/simplify_path.py
index 8880fc0c6..8f993b763 100644
--- a/algorithms/unix/path/simplify_path.py
+++ b/algorithms/unix/path/simplify_path.py
@@ -15,6 +15,12 @@
Reference: https://leetcode.com/problems/simplify-path/description/
"""
+branch_coverage = {
+ "for": False,
+ "if": False,
+ "elif": False,
+}
+
import os
def simplify_path_v1(path):
return os.path.abspath(path)
@@ -22,8 +28,28 @@ def simplify_path_v1(path):
def simplify_path_v2(path):
stack, tokens = [], path.split("/")
for token in tokens:
+ branch_coverage["for"] = True
if token == ".." and stack:
+ branch_coverage["if"] = True
stack.pop()
elif token != ".." and token != "." and token:
+ branch_coverage["elif"] = True
stack.append(token)
+
return "/" + "/".join(stack)
+
+def print_coverage():
+ covered = 0
+ print("branch coverage for `simplify_path_v2`:")
+ for branch, hit in branch_coverage.items():
+ print(f"{branch} was {'hit' if hit else 'not hit'}")
+ if hit: covered += 1;
+ print(f"Branch coverage: {covered / len(branch_coverage) * 100}")
+
+
+# simplify_path_v2(".")
+# simplify_path_v2("/../")
+# simplify_path_v2("/home//foo/")
+# simplify_path_v2("")
+# simplify_path_v2("/home/../")
+print_coverage()
diff --git a/image-1.png b/image-1.png
new file mode 100644
index 000000000..7071337a2
Binary files /dev/null and b/image-1.png differ
diff --git a/image-10.png b/image-10.png
new file mode 100644
index 000000000..7e4ab2a58
Binary files /dev/null and b/image-10.png differ
diff --git a/image-11.png b/image-11.png
new file mode 100644
index 000000000..cebd821ad
Binary files /dev/null and b/image-11.png differ
diff --git a/image-2.png b/image-2.png
new file mode 100644
index 000000000..77702129e
Binary files /dev/null and b/image-2.png differ
diff --git a/image-3.png b/image-3.png
new file mode 100644
index 000000000..61fc9d074
Binary files /dev/null and b/image-3.png differ
diff --git a/image-4.png b/image-4.png
new file mode 100644
index 000000000..9b5c60694
Binary files /dev/null and b/image-4.png differ
diff --git a/image-5.png b/image-5.png
new file mode 100644
index 000000000..e65d38265
Binary files /dev/null and b/image-5.png differ
diff --git a/image-6.png b/image-6.png
new file mode 100644
index 000000000..78045907d
Binary files /dev/null and b/image-6.png differ
diff --git a/image-7.png b/image-7.png
new file mode 100644
index 000000000..ffd360b0f
Binary files /dev/null and b/image-7.png differ
diff --git a/image-8.png b/image-8.png
new file mode 100644
index 000000000..6e6eab6b2
Binary files /dev/null and b/image-8.png differ
diff --git a/image-9.png b/image-9.png
new file mode 100644
index 000000000..2a59acdd5
Binary files /dev/null and b/image-9.png differ
diff --git a/image.png b/image.png
new file mode 100644
index 000000000..2a9ba91c1
Binary files /dev/null and b/image.png differ
diff --git a/tests/test_maths.py b/tests/test_maths.py
index c4a54af03..8d6e5f383 100644
--- a/tests/test_maths.py
+++ b/tests/test_maths.py
@@ -1,3 +1,6 @@
+from algorithms.maths.prime_check import prime_check, print_coverage
+import unittest
+
from algorithms.maths import (
power, power_recur,
int_to_base, base_to_int,
@@ -276,17 +279,45 @@ class TestPrimeTest(unittest.TestCase):
Arguments:
unittest {[type]} -- [description]
"""
+
- def test_prime_test(self):
+ def test_prime_numbers(self):
"""
- checks all prime numbers between 2 up to 100.
- Between 2 up to 100 exists 25 prime numbers!
+ Checks specific prime numbers between 2 up to 100.
"""
- counter = 0
- for i in range(2, 101):
- if prime_check(i):
- counter += 1
- self.assertEqual(25, counter)
+ primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
+ for prime in primes:
+ with self.subTest(n=prime):
+ self.assertTrue(prime_check(prime), f"{prime} should be prime")
+
+ def test_non_prime_numbers(self):
+ """
+ Checks specific non-prime numbers between 2 up to 100.
+ """
+ non_primes = [4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28, 30, 32, 33, 34, 35, 36, 38, 39, 40, 42, 44, 45, 46, 48, 49, 50, 51, 52, 54, 55, 56, 57, 58, 60, 62, 63, 64, 65, 66, 68, 69, 70, 72, 74, 75, 76, 77, 78, 80, 81, 82, 84, 85, 86, 87, 88, 90, 91, 92, 93, 94, 95, 96, 98, 99, 100]
+ for non_prime in non_primes:
+ with self.subTest(n=non_prime):
+ self.assertFalse(prime_check(non_prime), f"{non_prime} should not be prime")
+
+ def test_prime_check_coverage(self):
+ """
+ Additional checks to cover all branches in prime_check function.
+ """
+ self.assertFalse(prime_check(-1), "-1 should not be prime") # Branch 1
+ self.assertFalse(prime_check(0), "0 should not be prime") # Branch 1
+ self.assertFalse(prime_check(1), "1 should not be prime") # Branch 1
+ self.assertTrue(prime_check(2), "2 should be prime") # Branch 2
+ self.assertTrue(prime_check(3), "3 should be prime") # Branch 2
+ self.assertFalse(prime_check(4), "4 should not be prime") # Branch 3
+ self.assertFalse(prime_check(9), "9 should not be prime") # Branch 3
+ self.assertFalse(prime_check(15), "15 should not be prime") # Branch 3, 4, 5
+ self.assertTrue(prime_check(5), "5 should be prime") # Branch 4
+ self.assertTrue(prime_check(7), "7 should be prime") # Branch 4
+ self.assertFalse(prime_check(25), "25 should not be prime") # Branch 5
+ self.assertFalse(prime_check(49), "49 should not be prime") # Branch 5
+ self.assertFalse(prime_check(50), "50 should not be prime") # Branch 3
+ self.assertTrue(prime_check(97), "97 should be prime") # Branch 4
+
class TestPythagoras(unittest.TestCase):
@@ -301,6 +332,16 @@ def test_pythagoras(self):
self.assertEqual("Hypotenuse = 3.605551275463989",
pythagoras(3, 2, "?"))
+ def test_opposite_calculation(self):
+ result = pythagoras("?", 4, 5)
+ expected = "Opposite = 3.0"
+ self.assertEqual(result, expected)
+
+ def test_adjacent_calculation(self):
+ result = pythagoras(3, "?", 5)
+ expected = "Adjacent = 4.0"
+ self.assertEqual(result, expected)
+
class TestRabinMiller(unittest.TestCase):
"""[summary]
@@ -434,10 +475,12 @@ class TestFindOrder(unittest.TestCase):
"""
def test_find_order_simple(self):
- self.assertEqual(1, find_order(1, 1))
+ self.assertEqual(1, find_order(1, 1)) # Should hit branch_1
self.assertEqual(6, find_order(3, 7))
self.assertEqual(-1, find_order(128, 256))
self.assertEqual(352, find_order(3, 353))
+ self.assertEqual(-1, find_order(10, 20)) # Should hit branches 2, 3, 5
+
class TestKrishnamurthyNumber(unittest.TestCase):
diff --git a/tests/test_matrix.py b/tests/test_matrix.py
index 262fdbe62..5961680cc 100644
--- a/tests/test_matrix.py
+++ b/tests/test_matrix.py
@@ -15,6 +15,8 @@
)
import unittest
+from algorithms.matrix.rotate_image import rotate
+
class TestBombEnemy(unittest.TestCase):
def test_3x4(self):
@@ -228,6 +230,8 @@ def test_rotate_image(self):
self.assertEqual(rotate_image.rotate(
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
[[7, 4, 1], [8, 5, 2], [9, 6, 3]])
+ self.assertEqual([],rotate_image.rotate([]))
+ self.assertEqual([[3, 1], [4, 2]],rotate([[1, 2], [3, 4]]))
class TestSparseDotVector(unittest.TestCase):
diff --git a/tests/test_search.py b/tests/test_search.py
index f515cfcb9..f414cacc1 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -139,13 +139,28 @@ def test_next_greatest_letter(self):
self.assertEqual("c", next_greatest_letter_v2(letters, target))
def test_interpolation_search(self):
- array = [0, 3, 5, 5, 9, 12, 12, 15, 16, 19, 20]
+ array = [0, 3, 5, 5, 9, 12, 12, 15, 16, 19, 20, 25]
+ #, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
+
+ # array = [0, 3, 5, 5, 9, 12, 12, 15, 16, 19, 20, 25]
self.assertEqual(1, interpolation_search(array, 3))
self.assertEqual(2, interpolation_search(array, 5))
- self.assertEqual(6, interpolation_search(array, 12))
+ self.assertEqual(5, interpolation_search(array, 12))
self.assertEqual(-1, interpolation_search(array, 22))
self.assertEqual(-1, interpolation_search(array, -10))
self.assertEqual(10, interpolation_search(array, 20))
+
+ # self.assertEqual(-1, interpolation_search(array, 1))
+ # self.assertEqual(0, interpolation_search(array, 0)) # Found at the start
+ # self.assertEqual(interpolation_search(array, 12), 5) # Found in the middle, first occurrence
+ # self.assertEqual(-1, interpolation_search(array, 110)) # Not found, above maximum
+ # self.assertEqual(interpolation_search(array, 55), 17) # Found in the middle
+ # self.assertEqual(interpolation_search(array, 70), 20) # Found, single value in range
+ # self.assertEqual(interpolation_search(array, 22), -1) # Not found, above the range
+ # self.assertEqual(interpolation_search(array, 50), 16) # Found, single value in range
+ # self.assertEqual(interpolation_search(array, 45), 15) # Found, single value in range
+
+
if __name__ == '__main__':
diff --git a/tests/test_strings.py b/tests/test_strings.py
index e7a68302a..4a4c8da90 100644
--- a/tests/test_strings.py
+++ b/tests/test_strings.py
@@ -479,6 +479,8 @@ class TestStrongPassword(unittest.TestCase):
def test_strong_password(self):
self.assertEqual(3, strong_password(3, "Ab1"))
self.assertEqual(1, strong_password(11, "#Algorithms"))
+ self.assertEqual(3,strong_password(5, "12345"))
+ self.assertEqual(3,strong_password(5, "abcde"))
class TestCaesarCipher(unittest.TestCase):
@@ -568,6 +570,7 @@ class TestFirstUniqueChar(unittest.TestCase):
def test_first_unique_char(self):
self.assertEqual(0, first_unique_char("leetcode"))
self.assertEqual(2, first_unique_char("loveleetcode"))
+ self.assertEqual(-1, first_unique_char("aabb"))
class TestRepeatSubstring(unittest.TestCase):
diff --git a/tests/test_unix.py b/tests/test_unix.py
index 3cafba98f..e53881ef1 100644
--- a/tests/test_unix.py
+++ b/tests/test_unix.py
@@ -7,6 +7,9 @@
import os
import unittest
+from algorithms.unix import (
+ print_coverage
+)
class TestUnixPath(unittest.TestCase):
def test_join_with_slash(self):
@@ -42,7 +45,26 @@ def test_split(self):
self.assertEqual("test.py", expect_result[1])
def test_simplify_path(self):
- self.assertEqual("/", simplify_path_v1("/../"))
- self.assertEqual("/home/foo", simplify_path_v1("/home//foo/"))
+ root = None
+ pathsep = None
+ drive = None
+ if os.name == 'nt':
+ root = "" # Assumed to be ran on the C drive
+ pathsep = "\\"
+ drive = "C:\\"
+ elif os.name == 'posix':
+ root = "/"
+ pathsep = "/"
+ drive = ""
+
+ self.assertEqual(drive + root, simplify_path_v1("/../"))
+ self.assertEqual(drive + root + pathsep.join(["home", "foo"]), simplify_path_v1("/home//foo/"))
+
+ self.assertEqual("/", simplify_path_v2("."))
self.assertEqual("/", simplify_path_v2("/../"))
self.assertEqual("/home/foo", simplify_path_v2("/home//foo/"))
+ self.assertEqual("/", simplify_path_v2(""))
+ self.assertEqual("/", simplify_path_v2("/home/../"))
+
+ print_coverage()
+