Repository: keon/algorithms
Pull request #819 (2021-12-19 03:35:20)

added test case


Patch:
diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml
new file mode 100644
index 0000000..1eb737e
--- /dev/null
+++ b/.github/workflows/python-app.yml
@@ -0,0 +1,36 @@
+# This workflow will install Python dependencies, run tests and lint with a single version of Python
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
+
+name: Python application
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Set up Python 3.10
+      uses: actions/setup-python@v2
+      with:
+        python-version: "3.10"
+    - name: Install dependencies
+      run: |
+        python -m pip install --upgrade pip
+        pip install flake8 pytest
+        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
+    - name: Lint with flake8
+      run: |
+        # stop the build if there are Python syntax errors or undefined names
+        flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
+        # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
+        flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
+    - name: Test with pytest
+      run: |
+        python -m pytest
diff --git a/README.md b/README.md
index d8fc9c4..0fce159 100644
--- a/README.md
+++ b/README.md
@@ -71,6 +71,8 @@ If you want to uninstall algorithms, it is as simple as:
     - [two_sum](algorithms/arrays/two_sum.py)
     - [move_zeros](algorithms/arrays/move_zeros.py)
     - [n_sum](algorithms/arrays/n_sum.py)
+- [greedy](algorithms/greedy/)
+    - [max_contiguous_subsequence_sum](algorithms/greedy/max_contiguous_subsequence_sum.py)
 - [automata](algorithms/automata)
     - [DFA](algorithms/automata/dfa.py)
 - [backtrack](algorithms/backtrack)
@@ -370,7 +372,6 @@ If you want to uninstall algorithms, it is as simple as:
         - [count_left_node](algorithms/tree/bst/count_left_node.py)
         - [num_empty](algorithms/tree/bst/num_empty.py)
         - [height](algorithms/tree/bst/height.py)
-    - [fenwick_tree](algorithms/tree/fenwick_tree]
 	- [fenwick_tree](algorithms/tree/fenwick_tree/fenwick_tree.py)
     - [red_black_tree](algorithms/tree/red_black_tree)
         - [red_black_tree](algorithms/tree/red_black_tree/red_black_tree.py)
diff --git a/algorithms/arrays/limit.py b/algorithms/arrays/limit.py
index e0cc305..57f6561 100644
--- a/algorithms/arrays/limit.py
+++ b/algorithms/arrays/limit.py
@@ -14,4 +14,12 @@ Complexity = O(n)
 
 # tl:dr -- array slicing by value
 def limit(arr, min_lim=None, max_lim=None):
+    if len(arr) == 0:
+        return arr
+
+    if min_lim is None:
+        min_lim = min(arr)
+    if max_lim is None:
+        max_lim = max(arr)
+
     return list(filter(lambda x: (min_lim <= x <= max_lim), arr))
diff --git a/algorithms/compression/elias.py b/algorithms/compression/elias.py
index bdeb7fd..974fc37 100644
--- a/algorithms/compression/elias.py
+++ b/algorithms/compression/elias.py
@@ -1,17 +1,20 @@
 """
-Elias γ code or Elias gamma code is a universal code encoding positive integers.
-It is used most commonly when coding integers whose upper-bound cannot be determined beforehand.
-Elias δ code or Elias delta code is a universal code encoding the positive integers,
+Elias γ code or Elias gamma code is a universal code
+encoding positive integers.
+It is used most commonly when coding integers whose
+upper-bound cannot be determined beforehand.
+Elias δ code or Elias delta code is a universal code
+ encoding the positive integers,
 that includes Elias γ code when calculating.
 Both were developed by Peter Elias.
 
 """
-from math import log,ceil
+from math import log
 
-log2 = lambda x: log(x,2)
+log2 = lambda x: log(x, 2)
 
 # Calculates the binary number
-def binary(x,l=1):
+def binary(x, l=1):
 	fmt = '{0:0%db}' % l
 	return fmt.format(x)
 
@@ -21,12 +24,13 @@ def unary(x):
 
 def elias_generic(lencoding, x):
 	"""
-	The compressed data is calculated in two parts. 
-	The first part is the unary number of 1 + ⌊log2(x)⌋. 
+	The compressed data is calculated in two parts.
+	The first part is the unary number of 1 + ⌊log2(x)⌋.
 	The second part is the binary number of x - 2^(⌊log2(x)⌋).
 	For the final result we add these two parts.
 	"""
-	if x == 0: return '0'
+	if x == 0:
+		return '0'
 	
 	first_part = 1 + int(log2(x))
 	
@@ -34,7 +38,7 @@ def elias_generic(lencoding, x):
 	
 	k = int(log2(x))
 
-	return lencoding(first_part) + binary(a,k)
+	return lencoding(first_part) + binary(a, k)
 
 def elias_gamma(x):
 	"""
@@ -46,4 +50,4 @@ def elias_delta(x):
 	"""
 	For the first part we put the elias_g of the number.
 	"""
-	return elias_generic(elias_gamma,x)
+	return elias_generic(elias_gamma, x)
diff --git a/algorithms/dp/__init__.py b/algorithms/dp/__init__.py
index ac56eda..4421202 100644
--- a/algorithms/dp/__init__.py
+++ b/algorithms/dp/__init__.py
@@ -20,4 +20,4 @@ from .rod_cut import *
 from .word_break import *
 from .int_divide import *
 from .k_factor import *
-from .planting_trees import *
\ No newline at end of file
+from .planting_trees import *
diff --git a/algorithms/dp/climbing_stairs.py b/algorithms/dp/climbing_stairs.py
index 0c02efe..9b90ae1 100644
--- a/algorithms/dp/climbing_stairs.py
+++ b/algorithms/dp/climbing_stairs.py
@@ -1,23 +1,23 @@
 """
 You are climbing a stair case.
-It takes n steps to reach to the top.
+It takes `steps` number of steps to reach to the top.
 
 Each time you can either climb 1 or 2 steps.
 In how many distinct ways can you climb to the top?
 
-Note: Given n will be a positive integer.
+Note: Given argument `steps` will be a positive integer.
 """
 
 
 # O(n) space
 
-def climb_stairs(n):
+def climb_stairs(steps):
     """
-    :type n: int
+    :type steps: int
     :rtype: int
     """
     arr = [1, 1]
-    for _ in range(1, n):
+    for _ in range(1, steps):
         arr.append(arr[-1] + arr[-2])
     return arr[-1]
 
@@ -25,8 +25,12 @@ def climb_stairs(n):
 # the above function can be optimized as:
 # O(1) space
 
-def climb_stairs_optimized(n):
-    a = b = 1
-    for _ in range(n):
-        a, b = b, a + b
-    return a
+def climb_stairs_optimized(steps):
+    """
+    :type steps: int
+    :rtype: int
+    """
+    a_steps = b_steps = 1
+    for _ in range(steps):
+        a_steps, b_steps = b_steps, a_steps + b_steps
+    return a_steps
diff --git a/algorithms/dp/coin_change.py b/algorithms/dp/coin_change.py
index e9a83fc..379753b 100644
--- a/algorithms/dp/coin_change.py
+++ b/algorithms/dp/coin_change.py
@@ -1,28 +1,34 @@
 """
 Problem
-Given a value n, if we want to make change for N cents, and we have infinite supply of each of 
-coins = {S1, S2, .. , Sm} valued coins, how many ways can we make the change? 
-The order of coins doesn't matter.
-For example, for n = 4 and coins = [1, 2, 3], there are four solutions: 
-[1, 1, 1, 1], [1, 1, 2], [2, 2], [1, 3]. 
-So output should be 4. 
+Given a value `value`, if we want to make change for `value` cents, and we have infinite
+supply of each of coins = {S1, S2, .. , Sm} valued `coins`, how many ways can we make the change?
+The order of `coins` doesn't matter.
+For example, for `value` = 4 and `coins` = [1, 2, 3], there are four solutions:
+[1, 1, 1, 1], [1, 1, 2], [2, 2], [1, 3].
+So output should be 4.
 
-For n = 10 and coins = [2, 5, 3, 6], there are five solutions: 
-[2, 2, 2, 2, 2], [2, 2, 3, 3], [2, 2, 6], [2, 3, 5] and [5, 5]. 
+For `value` = 10 and `coins` = [2, 5, 3, 6], there are five solutions:
+
+[2, 2, 2, 2, 2], [2, 2, 3, 3], [2, 2, 6], [2, 3, 5] and [5, 5].
 So the output should be 5.
 
-Time complexity: O(n * m) where n is the value and m is the number of coins
+Time complexity: O(n * m) where n is the `value` and m is the number of `coins`
 Space complexity: O(n)
 """
 
-def count(coins, n):
+def count(coins, value):
+    """ Find number of combination of `coins` that adds upp to `value`
+
+    Keyword arguments:
+    coins -- int[]
+    value -- int
+    """
     # initialize dp array and set base case as 1
-    dp = [1] + [0] * n
- 
+    dp_array = [1] + [0] * value
+
     # fill dp in a bottom up manner
     for coin in coins:
-        for i in range(coin, n+1):
-            dp[i] += dp[i-coin]
-
-    return dp[n]
+        for i in range(coin, value+1):
+            dp_array[i] += dp_array[i-coin]
 
+    return dp_array[value]
diff --git a/algorithms/dp/combination_sum.py b/algorithms/dp/combination_sum.py
index 57587ff..aaf0749 100644
--- a/algorithms/dp/combination_sum.py
+++ b/algorithms/dp/combination_sum.py
@@ -27,34 +27,48 @@ What limitation we need to add to the question to allow negative numbers?
 
 """
 
-dp = None
-
+DP = None
 
 def helper_topdown(nums, target):
-    global dp
-    if dp[target] != -1:
-        return dp[target]
+    """Generates DP and finds result.
+
+    Keyword arguments:
+    nums -- positive integer array without duplicates
+    target -- integer describing what a valid combination should add to
+    """
+    if DP[target] != -1:
+        return DP[target]
     res = 0
-    for i in range(0, len(nums)):
-        if target >= nums[i]:
-            res += helper_topdown(nums, target - nums[i])
-    dp[target] = res
+    for num in nums:
+        if target >= num:
+            res += helper_topdown(nums, target - num)
+    DP[target] = res
     return res
 
 
 def combination_sum_topdown(nums, target):
-    global dp
-    dp = [-1] * (target + 1)
-    dp[0] = 1
-    return helper_topdown(nums, target)
+    """Find number of possible combinations in nums that add up to target, in top-down manner.
 
+    Keyword arguments:
+    nums -- positive integer array without duplicates
+    target -- integer describing what a valid combination should add to
+    """
+    global DP
+    DP = [-1] * (target + 1)
+    DP[0] = 1
+    return helper_topdown(nums, target)
 
-# EDIT: The above solution is top-down. How about a bottom-up one?
 def combination_sum_bottom_up(nums, target):
-    comb = [0] * (target + 1)
-    comb[0] = 1
-    for i in range(0, len(comb)):
-        for j in range(len(nums)):
-            if i - nums[j] >= 0:
-                comb[i] += comb[i - nums[j]]
-    return comb[target]
+    """Find number of possible combinations in nums that add up to target, in bottom-up manner.
+
+    Keyword arguments:
+    nums -- positive integer array without duplicates
+    target -- integer describing what a valid combination should add to
+    """
+    combs = [0] * (target + 1)
+    combs[0] = 1
+    for i in range(0, len(combs)):
+        for num in nums:
+            if i - num >= 0:
+                combs[i] += combs[i - num]
+    return combs[target]
diff --git a/algorithms/dp/edit_distance.py b/algorithms/dp/edit_distance.py
index ecf6beb..caf56ee 100644
--- a/algorithms/dp/edit_distance.py
+++ b/algorithms/dp/edit_distance.py
@@ -1,54 +1,69 @@
-"""The edit distance between two words is the minimum number of letter insertions,
-letter deletions, and letter substitutions required to transform one word into another.
+"""The edit distance between two words is the minimum number
+of letter insertions, letter deletions, and letter substitutions
+required to transform one word into another.
 
-For example, the edit distance between FOOD and MONEY is at most four:
+For example, the edit distance between FOOD and MONEY is at
+most four:
 
 FOOD -> MOOD -> MOND -> MONED -> MONEY
 
-Given two words A and B, find the minimum number of operations required to transform one string into the other.
+Given two words A and B, find the minimum number of operations
+required to transform one string into the other.
 In other words, find the edit distance between A and B.
 
 Thought process:
 
-Let edit(i, j) denote the edit distance between the prefixes A[1..i] and B[1..j].
+Let edit(i, j) denote the edit distance between
+the prefixes A[1..i] and B[1..j].
 
 Then, the function satifies the following recurrence:
 
 edit(i, j) = i if j = 0
              j if i = 0
-             min(edit(i-1, j) + 1, 
+             min(edit(i-1, j) + 1,
                  edit(i, j-1), + 1,
                  edit(i-1, j-1) + cost) otherwise
 
-There are two base cases, both of which occur when one string is empty and the other is not.
-1. To convert an empty string A into a string B of length n, perform n insertions.
-2. To convert a string A of length m into an empty string B, perform m deletions.
+There are two base cases, both of which occur when one string is empty
+and the other is not.
+1. To convert an empty string A into a string B of length n,
+perform n insertions.
+2. To convert a string A of length m into an empty string B,
+perform m deletions.
 
 Here, the cost is 1 if a substitution is required,
-or 0 if both chars in words A and B are the same at indexes i and j, respectively.
+or 0 if both chars in words A and B are the same at
+indexes i and j, respectively.
 
 To find the edit distance between two words A and B,
-we need to find edit(m, n), where m is the length of A and n is the length of B.
+we need to find edit(length_a, length_b).
+
+Time: O(length_a*length_b)
+Space: O(length_a*length_b)
 """
 
 
-def edit_distance(A, B):
-    # Time: O(m*n)
-    # Space: O(m*n)
+def edit_distance(word_a, word_b):
+    """Finds edit distance between word_a and word_b
+
+    Kwyword arguments:
+    word_a -- string
+    word_b -- string
+    """
 
-    m, n = len(A) + 1, len(B) + 1
+    length_a, length_b = len(word_a) + 1, len(word_b) + 1
 
-    edit = [[0 for _ in range(n)] for _ in range(m)]
+    edit = [[0 for _ in range(length_b)] for _ in range(length_a)]
 
-    for i in range(1, m):
+    for i in range(1, length_a):
         edit[i][0] = i
 
-    for j in range(1, n):
+    for j in range(1, length_b):
         edit[0][j] = j
 
-    for i in range(1, m):
-        for j in range(1, n):
-            cost = 0 if A[i - 1] == B[j - 1] else 1
+    for i in range(1, length_a):
+        for j in range(1, length_b):
+            cost = 0 if word_a[i - 1] == word_b[j - 1] else 1
             edit[i][j] = min(edit[i - 1][j] + 1, edit[i][j - 1] + 1, edit[i - 1][j - 1] + cost)
 
-    return edit[-1][-1]  # this is the same as edit[m][n]
+    return edit[-1][-1]  # this is the same as edit[length_a][length_b]
diff --git a/algorithms/dp/egg_drop.py b/algorithms/dp/egg_drop.py
index d07bee8..dfa2320 100644
--- a/algorithms/dp/egg_drop.py
+++ b/algorithms/dp/egg_drop.py
@@ -1,21 +1,21 @@
 """
-You are given K eggs, and you have access to a building with N floors 
-from 1 to N. Each egg is identical in function, and if an egg breaks, 
-you cannot drop it again. You know that there exists a floor F with 
-0 <= F <= N such that any egg dropped at a floor higher than F will 
-break, and any egg dropped at or below floor F will not break. 
-Each move, you may take an egg (if you have an unbroken one) and drop 
-it from any floor X (with 1 <= X <= N). Your goal is to know with 
-certainty what the value of F is. What is the minimum number of moves 
-that you need to know with certainty what F is, regardless of the 
+You are given K eggs, and you have access to a building with N floors
+from 1 to N. Each egg is identical in function, and if an egg breaks,
+you cannot drop it again. You know that there exists a floor F with
+0 <= F <= N such that any egg dropped at a floor higher than F will
+break, and any egg dropped at or below floor F will not break.
+Each move, you may take an egg (if you have an unbroken one) and drop
+it from any floor X (with 1 <= X <= N). Your goal is to know with
+certainty what the value of F is. What is the minimum number of moves
+that you need to know with certainty what F is, regardless of the
 initial value of F?
 
 Example:
 Input: K = 1, N = 2
 Output: 2
-Explanation: 
+Explanation:
 Drop the egg from floor 1.  If it breaks, we know with certainty that F = 0.
-Otherwise, drop the egg from floor 2.  If it breaks, we know with 
+Otherwise, drop the egg from floor 2.  If it breaks, we know with
 certainty that F = 1.
 If it didn't break, then we know with certainty F = 2.
 Hence, we needed 2 moves in the worst case to know what F is with certainty.
@@ -24,20 +24,26 @@ Hence, we needed 2 moves in the worst case to know what F is with certainty.
 # A Dynamic Programming based Python Program for the Egg Dropping Puzzle
 INT_MAX = 32767
 
+
 def egg_drop(n, k):
+    """
+    Keyword arguments:
+    n -- number of floors
+    k -- number of eggs
+    """
     # A 2D table where entery eggFloor[i][j] will represent minimum
     # number of trials needed for i eggs and j floors.
-    egg_floor = [[0 for x in range(k+1)] for x in range(n+1)]
- 
+    egg_floor = [[0 for _ in range(k + 1)] for _ in range(n + 1)]
+
     # We need one trial for one floor and 0 trials for 0 floors
     for i in range(1, n+1):
         egg_floor[i][1] = 1
         egg_floor[i][0] = 0
- 
+
     # We always need j trials for one egg and j floors.
     for j in range(1, k+1):
         egg_floor[1][j] = j
- 
+
     # Fill rest of the entries in table using optimal substructure
     # property
     for i in range(2, n+1):
@@ -47,6 +53,6 @@ def egg_drop(n, k):
                 res = 1 + max(egg_floor[i-1][x-1], egg_floor[i][j-x])
                 if res < egg_floor[i][j]:
                     egg_floor[i][j] = res
- 
+
     # eggFloor[n][k] holds the result
     return egg_floor[n][k]
diff --git a/algorithms/dp/fib.py b/algorithms/dp/fib.py
index 7a6fd71..08fa8ea 100644
--- a/algorithms/dp/fib.py
+++ b/algorithms/dp/fib.py
@@ -1,6 +1,8 @@
 '''
-In mathematics, the Fibonacci numbers, commonly denoted Fn, form a sequence, called the Fibonacci sequence, 
-such that each number is the sum of the two preceding ones, starting from 0 and 1. 
+In mathematics, the Fibonacci numbers, commonly denoted Fn,
+form a sequence, called the Fibonacci sequence,
+such that each number is the sum of the two preceding ones,
+starting from 0 and 1.
 That is,
     F0=0 , F1=1
 and
@@ -8,10 +10,13 @@ and
 The Fibonacci numbers are the numbers in the following integer sequence.
     0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …….
 
-In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation
+In mathematical terms, the sequence Fn of Fibonacci numbers is
+defined by the recurrence relation
 
 Here, given a number n, print n-th Fibonacci Number.
 '''
+
+
 def fib_recursive(n):
     """[summary]
     Computes the n-th fibonacci number recursive.
@@ -20,7 +25,7 @@ def fib_recursive(n):
 
     Arguments:
         n {[int]} -- [description]
-    
+
     Returns:
         [int] -- [description]
     """
@@ -30,20 +35,20 @@ def fib_recursive(n):
 
     if n <= 1:
         return n
-    else:
-        return fib_recursive(n-1) + fib_recursive(n-2)
+    return fib_recursive(n-1) + fib_recursive(n-2)
 
 # print(fib_recursive(35)) # => 9227465 (slow)
 
+
 def fib_list(n):
     """[summary]
     This algorithm computes the n-th fibbonacci number
     very quick. approximate O(n)
     The algorithm use dynamic programming.
-    
+
     Arguments:
         n {[int]} -- [description]
-    
+
     Returns:
         [int] -- [description]
     """
@@ -58,13 +63,14 @@ def fib_list(n):
 
 # print(fib_list(100)) # => 354224848179261915075
 
+
 def fib_iter(n):
     """[summary]
     Works iterative approximate O(n)
 
     Arguments:
         n {[int]} -- [description]
-    
+
     Returns:
         [int] -- [description]
     """
@@ -74,13 +80,13 @@ def fib_iter(n):
 
     fib_1 = 0
     fib_2 = 1
-    sum = 0
+    res = 0
     if n <= 1:
         return n
     for _ in range(n-1):
-        sum = fib_1 + fib_2
+        res = fib_1 + fib_2
         fib_1 = fib_2
-        fib_2 = sum
-    return sum
+        fib_2 = res
+    return res
 
 # print(fib_iter(100)) # => 354224848179261915075
diff --git a/algorithms/dp/hosoya_triangle.py b/algorithms/dp/hosoya_triangle.py
index 9bf9437..a63deaf 100644
--- a/algorithms/dp/hosoya_triangle.py
+++ b/algorithms/dp/hosoya_triangle.py
@@ -8,38 +8,49 @@ This printHosoya function takes argument n which is the height of the triangle
 
 For example:
 printHosoya( 6 ) would return:
-1 
-1 1 
-2 1 2 
-3 2 2 3 
-5 3 4 3 5 
+1
+1 1
+2 1 2
+3 2 2 3
+5 3 4 3 5
 8 5 6 6 5 8
 
 The complexity is O(n^3).
 
 """
 
+def hosoya(height, width):
+    """ Calculates the hosoya triangle
 
-def hosoya(n, m): 
-    if ((n == 0 and m == 0) or (n == 1 and m == 0) or
-        (n == 1 and m == 1) or (n == 2 and m == 1)): 
+    height -- height of the triangle
+    """
+    if (width == 0) and (height in (0,1)):
         return 1
-    if n > m: 
-        return hosoya(n - 1, m) + hosoya(n - 2, m) 
-    elif m == n: 
-        return hosoya(n - 1, m - 1) + hosoya(n - 2, m - 2) 
-    else: 
-        return 0
-          
-def print_hosoya(n): 
-    for i in range(n): 
-        for j in range(i + 1): 
-            print(hosoya(i, j) , end = " ") 
+    if (width == 1) and (height in (1,2)):
+        return 1
+    if height > width:
+        return hosoya(height - 1, width) + hosoya(height - 2, width)
+    if width == height:
+        return hosoya(height - 1, width - 1) + hosoya(height - 2, width - 2)
+    return 0
+
+def print_hosoya(height):
+    """Prints the hosoya triangle
+
+    height -- height of the triangle
+    """
+    for i in range(height):
+        for j in range(i + 1):
+            print(hosoya(i, j) , end = " ")
         print ("\n", end = "")
 
-def hosoya_testing(n):
-    x = []
-    for i in range(n): 
-        for j in range(i + 1): 
-            x.append(hosoya(i, j))
-    return x
+def hosoya_testing(height):
+    """Test hosoya function
+
+    height -- height of the triangle
+    """
+    res = []
+    for i in range(height):
+        for j in range(i + 1):
+            res.append(hosoya(i, j))
+    return res
diff --git a/algorithms/dp/int_divide.py b/algorithms/dp/int_divide.py
index 86ba8cb..37c9a44 100644
--- a/algorithms/dp/int_divide.py
+++ b/algorithms/dp/int_divide.py
@@ -1,5 +1,6 @@
 """
-Given positive integer n, find an algorithm to find the number of non-negative number division, or descomposition.
+Given positive integer decompose, find an algorithm to find the number of
+non-negative number division, or decomposition.
 
 The complexity is O(n^2).
 
@@ -36,15 +37,19 @@ Explaination:
 """
 
 
-def int_divide(n):
-    arr = [[0 for i in range(n + 1)] for j in range(n + 1)]
+def int_divide(decompose):
+    """Find number of decompositions from `decompose`
+
+    decompose -- integer
+    """
+    arr = [[0 for i in range(decompose + 1)] for j in range(decompose + 1)]
     arr[1][1] = 1
-    for i in range(1, n + 1):
-        for j in range(1, n + 1):
+    for i in range(1, decompose + 1):
+        for j in range(1, decompose + 1):
             if i < j:
                 arr[i][j] = arr[i][i]
             elif i == j:
                 arr[i][j] = 1 + arr[i][j - 1]
             else:
                 arr[i][j] = arr[i][j - 1] + arr[i - j][j]
-    return arr[n][n]
+    return arr[decompose][decompose]
diff --git a/algorithms/dp/job_scheduling.py b/algorithms/dp/job_scheduling.py
index eaf98ec..b822c03 100644
--- a/algorithms/dp/job_scheduling.py
+++ b/algorithms/dp/job_scheduling.py
@@ -1,62 +1,68 @@
-# Python program for weighted job scheduling using Dynamic 
-# Programming and Binary Search
- 
-# Class to represent a job
+"""
+Python program for weighted job scheduling using Dynamic
+Programming and Binary Search
+"""
+
 class Job:
+    """
+    Class to represent a job
+    """
     def __init__(self, start, finish, profit):
-        self.start  = start
+        self.start = start
         self.finish = finish
         self.profit  = profit
- 
- 
-# A Binary Search based function to find the latest job
-# (before current job) that doesn't conflict with current
-# job.  "index" is index of the current job.  This function
-# returns -1 if all jobs before index conflict with it.
-# The array jobs[] is sorted in increasing order of finish
-# time.
+
 def binary_search(job, start_index):
- 
-    # Initialize 'lo' and 'hi' for Binary Search
-    lo = 0
-    hi = start_index - 1
- 
+    """
+    A Binary Search based function to find the latest job
+    (before current job) that doesn't conflict with current
+    job.  "index" is index of the current job.  This function
+    returns -1 if all jobs before index conflict with it.
+    The array jobs[] is sorted in increasing order of finish
+    time.
+    """
+
+    left = 0
+    right = start_index - 1
+
     # Perform binary Search iteratively
-    while lo <= hi:
-        mid = (lo + hi) // 2
+    while left <= right:
+        mid = (left + right) // 2
         if job[mid].finish <= job[start_index].start:
             if job[mid + 1].finish <= job[start_index].start:
-                lo = mid + 1
+                left = mid + 1
             else:
                 return mid
         else:
-            hi = mid - 1
+            right = mid - 1
     return -1
- 
-# The main function that returns the maximum possible
-# profit from given array of jobs
+
 def schedule(job):
-   
+    """
+    The main function that returns the maximum possible
+    profit from given array of jobs
+    """
+
     # Sort jobs according to finish time
     job = sorted(job, key = lambda j: j.finish)
- 
+
     # Create an array to store solutions of subproblems.  table[i]
     # stores the profit for jobs till arr[i] (including arr[i])
-    n = len(job) 
-    table = [0 for _ in range(n)]
- 
+    length = len(job)
+    table = [0 for _ in range(length)]
+
     table[0] = job[0].profit
- 
+
     # Fill entries in table[] using recursive property
-    for i in range(1, n):
- 
+    for i in range(1, length):
+
         # Find profit including the current job
         incl_prof = job[i].profit
-        l = binary_search(job, i)
-        if (l != -1):
-            incl_prof += table[l]
- 
+        pos = binary_search(job, i)
+        if pos != -1:
+            incl_prof += table[pos]
+
         # Store maximum of including and excluding
         table[i] = max(incl_prof, table[i - 1])
- 
-    return table[n-1]
+
+    return table[length-1]
diff --git a/algorithms/dp/k_factor.py b/algorithms/dp/k_factor.py
index 2fd23d1..c072f75 100644
--- a/algorithms/dp/k_factor.py
+++ b/algorithms/dp/k_factor.py
@@ -1,68 +1,85 @@
-'''The K factor of a string is defined as the number of times 'abba' appears as a substring.
-Given two numbers N and k,​ find the number of strings of length N with 'K factor' = k.
+'''
+The K factor of a string is defined as the number of times 'abba' appears as a
+substring. Given two numbers `length` and `k_factor`, find the number of
+strings of length `length` with 'K factor' = `k_factor`.
 
 The algorithms is as follows:
 
-dp[n][k] will be a 4 element array, wherein each element can be the number of strings of length n and 'K factor' = k which belong to the criteria represented by that index:
+dp[length][k_factor] will be a 4 element array, wherein each element can be the
+number of strings of length `length` and 'K factor' = `k_factor` which belong
+to the criteria represented by that index:
+
+    - dp[length][k_factor][0] can be the number of strings of length `length`
+      and K-factor = `k_factor` which end with substring 'a'
+
+    - dp[length][k_factor][1] can be the number of strings of length `length`
+      and K-factor = `k_factor` which end with substring 'ab'
+
+    - dp[length][k_factor][2] can be the number of strings of length `length`
+      and K-factor = `k_factor` which end with substring 'abb'
 
-    dp[n][k][0] can be the number of strings of length n and K-factor = k which end with substring 'a'
-    dp[n][k][1] can be the number of strings of length n and K-factor = k which end with substring 'ab'
-    dp[n][k][2] can be the number of strings of length n and K-factor = k which end with substring 'abb'
-    dp[n][k][3] can be the number of strings of length n and K-factor = k which end with anything other than the above substrings (anything other than 'a' 'ab' 'abb')
+    - dp[length][k_factor][3] can be the number of strings of `length` and
+      K-factor = `k_factor` which end with anything other than the above
+      substrings (anything other than 'a' 'ab' 'abb')
 
 Example inputs
 
-n=4 k=1  no of strings = 1
-n=7 k=1 no of strings = 70302
-n=10 k=2 no of strings = 74357
+length=4 k_factor=1  no of strings = 1
+length=7 k_factor=1 no of strings = 70302
+length=10 k_factor=2 no of strings = 74357
 
 '''
 
-def find_k_factor(n,k):
-    dp=[[[0 for i in range(4)]for j in range((n-1)//3+2)]for k in range(n+1)]
-    if(3*k+1>n):
+def find_k_factor(length, k_factor):
+    """Find the number of strings of length `length` with K factor = `k_factor`.
+
+    Keyword arguments:
+    length -- integer
+    k_factor -- integer
+    """
+    mat=[[[0 for i in range(4)]for j in range((length-1)//3+2)]for k in range(length+1)]
+    if 3*k_factor+1>length:
         return 0
     #base cases
-    dp[1][0][0]=1;
-    dp[1][0][1]=0;
-    dp[1][0][2]=0;
-    dp[1][0][3]=25;
-
-    for i in range(2,n+1):
-        for j in range((n-1)//3+2):
-            if(j==0):
+    mat[1][0][0]=1
+    mat[1][0][1]=0
+    mat[1][0][2]=0
+    mat[1][0][3]=25
+
+    for i in range(2,length+1):
+        for j in range((length-1)//3+2):
+            if j==0:
                 #adding a at the end
-                dp[i][j][0]=dp[i-1][j][0]+dp[i-1][j][1]+dp[i-1][j][3]
+                mat[i][j][0]=mat[i-1][j][0]+mat[i-1][j][1]+mat[i-1][j][3]
 
                 #adding b at the end
-                dp[i][j][1]=dp[i-1][j][0]
-                dp[i][j][2]=dp[i-1][j][1]
+                mat[i][j][1]=mat[i-1][j][0]
+                mat[i][j][2]=mat[i-1][j][1]
 
                 #adding any other lowercase character
-                dp[i][j][3]=dp[i-1][j][0]*24+dp[i-1][j][1]*24+dp[i-1][j][2]*25+dp[i-1][j][3]*25
+                mat[i][j][3]=mat[i-1][j][0]*24+mat[i-1][j][1]*24+mat[i-1][j][2]*25+mat[i-1][j][3]*25
 
-            elif(3*j+1<i):
+            elif 3*j+1<i:
                 #adding a at the end
-                dp[i][j][0]=dp[i-1][j][0]+dp[i-1][j][1]+dp[i-1][j][3]+dp[i-1][j-1][2]
+                mat[i][j][0]=mat[i-1][j][0]+mat[i-1][j][1]+mat[i-1][j][3]+mat[i-1][j-1][2]
 
                 #adding b at the end
-                dp[i][j][1]=dp[i-1][j][0]
-                dp[i][j][2]=dp[i-1][j][1]
+                mat[i][j][1]=mat[i-1][j][0]
+                mat[i][j][2]=mat[i-1][j][1]
 
                 #adding any other lowercase character
-                dp[i][j][3]=dp[i-1][j][0]*24+dp[i-1][j][1]*24+dp[i-1][j][2]*25+dp[i-1][j][3]*25
-
-            elif(3*j+1==i):
-                dp[i][j][0]=1
-                dp[i][j][1]=0
-                dp[i][j][2]=0
-                dp[i][j][3]=0
-            
-            else:
-                dp[i][j][0]=0
-                dp[i][j][1]=0
-                dp[i][j][2]=0
-                dp[i][j][3]=0
+                mat[i][j][3]=mat[i-1][j][0]*24+mat[i-1][j][1]*24+mat[i-1][j][2]*25+mat[i-1][j][3]*25
 
-    return sum(dp[n][k])
+            elif 3*j+1==i:
+                mat[i][j][0]=1
+                mat[i][j][1]=0
+                mat[i][j][2]=0
+                mat[i][j][3]=0
+
+            else:
+                mat[i][j][0]=0
+                mat[i][j][1]=0
+                mat[i][j][2]=0
+                mat[i][j][3]=0
 
+    return sum(mat[length][k_factor])
diff --git a/algorithms/dp/longest_common_subsequence.py b/algorithms/dp/longest_common_subsequence.py
index cdbba95..c760880 100644
--- a/algorithms/dp/longest_common_subsequence.py
+++ b/algorithms/dp/longest_common_subsequence.py
@@ -22,27 +22,25 @@ respectively.
 """
 
 
-def longest_common_subsequence(s1, s2):
+def longest_common_subsequence(s_1, s_2):
     """
     :param s1: string
     :param s2: string
     :return: int
     """
-    m = len(s1)
-    n = len(s2)
+    m = len(s_1)
+    n = len(s_2)
 
-    dp = [[0] * (n + 1) for i in range(m + 1)]
-    """
-    dp[i][j] : contains length of LCS of s1[0..i-1] and s2[0..j-1]
-    """
+    mat = [[0] * (n + 1) for i in range(m + 1)]
+    # mat[i][j] : contains length of LCS of s_1[0..i-1] and s_2[0..j-1]
 
     for i in range(m + 1):
         for j in range(n + 1):
             if i == 0 or j == 0:
-                dp[i][j] = 0
-            elif s1[i - 1] == s2[j - 1]:
-                dp[i][j] = dp[i - 1][j - 1] + 1
+                mat[i][j] = 0
+            elif s_1[i - 1] == s_2[j - 1]:
+                mat[i][j] = mat[i - 1][j - 1] + 1
             else:
-                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
+                mat[i][j] = max(mat[i - 1][j], mat[i][j - 1])
 
-    return dp[m][n]
+    return mat[m][n]
diff --git a/algorithms/dp/longest_increasing.py b/algorithms/dp/longest_increasing.py
index 6cae572..53fa515 100644
--- a/algorithms/dp/longest_increasing.py
+++ b/algorithms/dp/longest_increasing.py
@@ -1,11 +1,13 @@
 """
-Given an unsorted array of integers, find the length of longest increasing subsequence.
+Given an unsorted array of integers, find the length of
+longest increasing subsequence.
 
 Example:
 
 Input: [10,9,2,5,3,7,101,18]
-Output: 4 
-Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
+Output: 4
+Explanation: The longest increasing subsequence is [2,3,7,101], therefore the
+length is 4.
 
 Time complexity:
 First algorithm is O(n^2).
@@ -18,6 +20,7 @@ Second algorithm is O(x) where x is the max element in the list
 Third algorithm is O(n)
 """
 
+
 def longest_increasing_subsequence(sequence):
     """
     Dynamic Programming Algorithm for
@@ -34,44 +37,47 @@ def longest_increasing_subsequence(sequence):
                 print(counts)
     return max(counts)
 
+
 def longest_increasing_subsequence_optimized(sequence):
     """
     Optimized dynamic programming algorithm for
     couting the length of the longest increasing subsequence
     using segment tree data structure to achieve better complexity
-    if max element is larger than 10^5 then use 
+    if max element is larger than 10^5 then use
     longest_increasing_subsequence_optimied2() instead
     type sequence: list[int]
     rtype: int
     """
-    mx = max(sequence)
-    tree = [0] * (mx<<2)
+    max_seq = max(sequence)
+    tree = [0] * (max_seq<<2)
 
-    def update(p, l, r, i, v):
-        if l == r:
-            tree[p] = v
+    def update(pos, left, right, target, vertex):
+        if left == right:
+            tree[pos] = vertex
             return
-        mid = (l+r)>>1
-        if i <= mid:
-            update(p<<1, l, mid, i, v)
+        mid = (left+right)>>1
+        if target <= mid:
+            update(pos<<1, left, mid, target, vertex)
         else:
-            update((p<<1)|1, mid+1, r, i, v)
-        tree[p] = max(tree[p<<1], tree[(p<<1)|1])
+            update((pos<<1)|1, mid+1, right, target, vertex)
+        tree[pos] = max_seq(tree[pos<<1], tree[(pos<<1)|1])
 
-    def get_max(p, l, r, s, e):
-        if l > e or r < s:
+    def get_max(pos, left, right, start, end):
+        if left > end or right < start:
             return 0
-        if l >= s and r <= e:
-            return tree[p]
-        mid = (l+r)>>1
-        return max(get_max(p<<1, l, mid, s, e), get_max((p<<1)|1, mid+1, r, s, e))
+        if left >= start and right <= end:
+            return tree[pos]
+        mid = (left+right)>>1
+        return max_seq(get_max(pos<<1, left, mid, start, end),
+            get_max((pos<<1)|1, mid+1, right, start, end))
     ans = 0
-    for x in sequence:
-       cur = get_max(1, 0, mx, 0, x-1)+1
-       ans = max(ans, cur)
-       update(1, 0, mx, x, cur)
+    for element in sequence:
+        cur = get_max(1, 0, max_seq, 0, element-1)+1
+        ans = max_seq(ans, cur)
+        update(1, 0, max_seq, element, cur)
     return ans
 
+
 def longest_increasing_subsequence_optimized2(sequence):
     """
     Optimized dynamic programming algorithm for
@@ -80,32 +86,32 @@ def longest_increasing_subsequence_optimized2(sequence):
     type sequence: list[int]
     rtype: int
     """
-    n = len(sequence)
-    tree = [0] * (n<<2)
+    length = len(sequence)
+    tree = [0] * (length<<2)
     sorted_seq = sorted((x, -i) for i, x in enumerate(sequence))
-    def update(p, l, r, i, v):
-        if l ==r:
-            tree[p] = v
+    def update(pos, left, right, target, vertex):
+        if left == right:
+            tree[pos] = vertex
             return
-        mid = (l+r)>>1
-        if i <= mid:
-            update(p<<1, l, mid, i, v)
+        mid = (left+right)>>1
+        if target <= mid:
+            vertex(pos<<1, left, mid, target, vertex)
         else:
-            update((p<<1)|1, mid+1, r, i, v)
-        tree[p] = max(tree[p<<1], tree[(p<<1)|1])
+            vertex((pos<<1)|1, mid+1, right, target, vertex)
+        tree[pos] = max(tree[pos<<1], tree[(pos<<1)|1])
 
-    def get_max(p, l, r, s, e):
-        if l > e or r < s:
+    def get_max(pos, left, right, start, end):
+        if left > end or right < start:
             return 0
-        if l >= s and r <= e:
-            return tree[p]
-        mid = (l+r)>>1
-        return max(get_max(p<<1, l, mid, s, e), get_max((p<<1)|1, mid+1, r, s, e))
+        if left >= start and right <= end:
+            return tree[pos]
+        mid = (left+right)>>1
+        return max(get_max(pos<<1, left, mid, start, end),
+            get_max((pos<<1)|1, mid+1, right, start, end))
     ans = 0
-    for x, j in sorted_seq:
-        i = -j
-        cur = get_max(1, 0, n-1, 0, i-1)+1
+    for tup in sorted_seq:
+        i = -tup[1]
+        cur = get_max(1, 0, length-1, 0, i-1)+1
         ans = max(ans, cur)
-        update(1, 0, n-1, i, cur)
-    return ans 
-
+        update(1, 0, length-1, i, cur)
+    return ans
diff --git a/algorithms/dp/matrix_chain_order.py b/algorithms/dp/matrix_chain_order.py
index 8c1ecae..dd2ef7b 100644
--- a/algorithms/dp/matrix_chain_order.py
+++ b/algorithms/dp/matrix_chain_order.py
@@ -6,12 +6,17 @@ Space Complexity: O(n^2)
 '''
 INF = float("inf")
 
+
 def matrix_chain_order(array):
-    n=len(array)
+    """Finds optimal order to multiply matrices
+
+    array -- int[]
+    """
+    n = len(array)
     matrix = [[0 for x in range(n)] for x in range(n)]
     sol = [[0 for x in range(n)] for x in range(n)]
-    for chain_length in range(2,n):
-        for a in range(1,n-chain_length+1):
+    for chain_length in range(2, n):
+        for a in range(1, n-chain_length+1):
             b = a+chain_length-1
 
             matrix[a][b] = INF
@@ -20,26 +25,37 @@ def matrix_chain_order(array):
                 if cost < matrix[a][b]:
                     matrix[a][b] = cost
                     sol[a][b] = c
-    return matrix , sol
-#Print order of matrix with Ai as matrix
+    return matrix, sol
+# Print order of matrix with Ai as matrix
 
 def print_optimal_solution(optimal_solution,i,j):
+    """Print the solution
+
+    optimal_solution -- int[][]
+    i -- int[]
+    j -- int[]
+    """
     if i==j:
         print("A" + str(i),end = " ")
     else:
-        print("(",end = " ")
-        print_optimal_solution(optimal_solution,i,optimal_solution[i][j])
-        print_optimal_solution(optimal_solution,optimal_solution[i][j]+1,j)
-        print(")",end = " ")
+        print("(", end=" ")
+        print_optimal_solution(optimal_solution, i, optimal_solution[i][j])
+        print_optimal_solution(optimal_solution, optimal_solution[i][j]+1, j)
+        print(")", end=" ")
+
 
 def main():
+    """
+    Testing for matrix_chain_ordering
+    """
     array=[30,35,15,5,10,20,25]
-    n=len(array)
+    length=len(array)
     #Size of matrix created from above array will be
     # 30*35 35*15 15*5 5*10 10*20 20*25
-    matrix , optimal_solution = matrix_chain_order(array)
+    matrix, optimal_solution = matrix_chain_order(array)
+
+    print("No. of Operation required: "+str((matrix[1][length-1])))
+    print_optimal_solution(optimal_solution,1,length-1)
 
-    print("No. of Operation required: "+str((matrix[1][n-1])))
-    print_optimal_solution(optimal_solution,1,n-1)
 if __name__ == '__main__':
     main()
diff --git a/algorithms/dp/max_product_subarray.py b/algorithms/dp/max_product_subarray.py
index 592e98f..7a9beac 100644
--- a/algorithms/dp/max_product_subarray.py
+++ b/algorithms/dp/max_product_subarray.py
@@ -14,15 +14,15 @@ def max_product(nums):
     :rtype: int
     """
     lmin = lmax = gmax = nums[0]
-    for i in range(len(nums)):
-        t1 = nums[i] * lmax
-        t2 = nums[i] * lmin
-        lmax = max(max(t1, t2), nums[i])
-        lmin = min(min(t1, t2), nums[i])
+    for num in nums:
+        t_1 = num * lmax
+        t_2 = num * lmin
+        lmax = max(max(t_1, t_2), num)
+        lmin = min(min(t_1, t_2), num)
         gmax = max(gmax, lmax)
 
 
-'''
+"""
 Another approach that would print max product and the subarray
 
 Examples:
@@ -34,18 +34,18 @@ subarray_with_max_product([-4,-3,-2,-1])
     #=> max_product_so_far: 24, [-4, -3, -2, -1]
 subarray_with_max_product([-3,0,1])
     #=> max_product_so_far: 1, [1]
-'''
+"""
 
 
 def subarray_with_max_product(arr):
     ''' arr is list of positive/negative numbers '''
-    l = len(arr)
+    length = len(arr)
     product_so_far = max_product_end = 1
     max_start_i = 0
     so_far_start_i = so_far_end_i = 0
     all_negative_flag = True
 
-    for i in range(l):
+    for i in range(length):
         max_product_end *= arr[i]
         if arr[i] > 0:
             all_negative_flag = False
@@ -60,8 +60,7 @@ def subarray_with_max_product(arr):
             so_far_start_i = max_start_i
 
     if all_negative_flag:
-        print("max_product_so_far: %s, %s" %
-              (reduce(lambda x, y: x * y, arr), arr))
+        print(f"max_product_so_far: {reduce(lambda x, y: x * y, arr)}, {arr}")
+
     else:
-        print("max_product_so_far: %s, %s" %
-              (product_so_far, arr[so_far_start_i:so_far_end_i + 1]))
+        print(f"max_product_so_far: {product_so_far},{arr[so_far_start_i:so_far_end_i + 1]}")
diff --git a/algorithms/dp/min_cost_path.py b/algorithms/dp/min_cost_path.py
index 8af9470..7771e1e 100644
--- a/algorithms/dp/min_cost_path.py
+++ b/algorithms/dp/min_cost_path.py
@@ -1,7 +1,7 @@
 """
 author @goswami-rahul
 
-To find minimum cost path 
+To find minimum cost path
 from station 0 to station N-1,
 where cost of moving from ith station to jth station is given as:
 
@@ -9,11 +9,11 @@ Matrix of size (N x N)
 where Matrix[i][j] denotes the cost of moving from
 station i --> station j   for i < j
 
-NOTE that values where Matrix[i][j] and i > j does not 
+NOTE that values where Matrix[i][j] and i > j does not
 mean anything, and hence represented by -1 or INF
 
-For the input below (cost matrix), 
-Minimum cost is obtained as from  { 0 --> 1 --> 3} 
+For the input below (cost matrix),
+Minimum cost is obtained as from  { 0 --> 1 --> 3}
                                   = cost[0][1] + cost[1][3] = 65
 the Output will be:
 
@@ -21,33 +21,38 @@ The Minimum cost to reach station 4 is 65
 
 Time Complexity: O(n^2)
 Space Complexity: O(n)
-""" 
+"""
 
 INF = float("inf")
 
+
 def min_cost(cost):
- 
-    n = len(cost)
+    """Find minimum cost.
+
+    Keyword arguments:
+    cost -- matrix containing costs
+    """
+    length = len(cost)
     # dist[i] stores minimum cost from 0 --> i.
-    dist = [INF] * n
+    dist = [INF] * length
 
     dist[0] = 0   # cost from 0 --> 0 is zero.
-  
-    for i in range(n):
-        for j in range(i+1,n):
+
+    for i in range(length):
+        for j in range(i+1,length):
             dist[j] = min(dist[j], dist[i] + cost[i][j])
-  
-    return dist[n-1]
+
+    return dist[length-1]
+
 
 if __name__ == '__main__':
-    
-    cost = [ [ 0, 15, 80, 90],         # cost[i][j] is the cost of
+    costs = [ [ 0, 15, 80, 90],         # cost[i][j] is the cost of
              [-1,  0, 40, 50],         # going from i --> j
-             [-1, -1,  0, 70],         
+             [-1, -1,  0, 70],
              [-1, -1, -1,  0] ]        # cost[i][j] = -1 for i > j
-    total_len = len(cost)
-    
-    mcost = min_cost(cost)
+    TOTAL_LEN = len(costs)
+
+    mcost = min_cost(costs)
     assert mcost == 65
-    
-    print("The Minimum cost to reach station %d is %d" % (total_len, mcost))
+
+    print(f"The minimum cost to reach station {TOTAL_LEN} is {mcost}")
diff --git a/algorithms/dp/num_decodings.py b/algorithms/dp/num_decodings.py
index 541db6e..87cd3e3 100644
--- a/algorithms/dp/num_decodings.py
+++ b/algorithms/dp/num_decodings.py
@@ -17,33 +17,37 @@ The number of ways decoding "12" is 2.
 """
 
 
-def num_decodings(s):
+def num_decodings(enc_mes):
     """
     :type s: str
     :rtype: int
     """
-    if not s or s[0] == "0":
+    if not enc_mes or enc_mes[0] == "0":
         return 0
-    wo_last, wo_last_two = 1, 1
-    for i in range(1, len(s)):
-        x = wo_last if s[i] != "0" else 0
-        y = wo_last_two if int(s[i-1:i+1]) < 27 and s[i-1] != "0" else 0
-        wo_last_two = wo_last
-        wo_last = x+y
-    return wo_last
+    last_char, last_two_chars = 1, 1
+    for i in range(1, len(enc_mes)):
+        last = last_char if enc_mes[i] != "0" else 0
+        last_two = last_two_chars if int(enc_mes[i-1:i+1]) < 27 and enc_mes[i-1] != "0" else 0
+        last_two_chars = last_char
+        last_char = last+last_two
+    return last_char
 
 
-def num_decodings2(s):
-    if not s or s.startswith('0'):
+def num_decodings2(enc_mes):
+    """
+    :type s: str
+    :rtype: int
+    """
+    if not enc_mes or enc_mes.startswith('0'):
         return 0
     stack = [1, 1]
-    for i in range(1, len(s)):
-        if s[i] == '0':
-            if s[i-1] == '0' or s[i-1] > '2':
+    for i in range(1, len(enc_mes)):
+        if enc_mes[i] == '0':
+            if enc_mes[i-1] == '0' or enc_mes[i-1] > '2':
                 # only '10', '20' is valid
                 return 0
             stack.append(stack[-2])
-        elif 9 < int(s[i-1:i+1]) < 27:
+        elif 9 < int(enc_mes[i-1:i+1]) < 27:
             # '01 - 09' is not allowed
             stack.append(stack[-2]+stack[-1])
         else:
diff --git a/algorithms/dp/planting_trees.py b/algorithms/dp/planting_trees.py
index c1efd4e..ee8394b 100644
--- a/algorithms/dp/planting_trees.py
+++ b/algorithms/dp/planting_trees.py
@@ -1,22 +1,25 @@
 """
-An even number of trees are left along one side of a country road. You've been assigned the job to
-plant these trees at an even interval on both sides of the road. The length L and width W of the road
-are variable, and a pair of trees must be planted at the beginning (at 0) and at the end (at L) of
-the road. Only one tree can be moved at a time. The goal is to calculate the lowest amount of
-distance that the trees have to be moved before they are all in a valid position.
+An even number of trees are left along one side of a country road. You've been
+assigned the job to plant these trees at an even interval on both sides of the
+road. The length and width of the road are variable, and a pair of trees must
+be planted at the beginning (at 0) and at the end (at length) of the road. Only
+one tree can be moved at a time. The goal is to calculate the lowest amount of
+distance that the trees have to be moved before they are all in a valid
+position.
 """
 
 from math import sqrt
-import sys
 
-def planting_trees(trees, L, W):
+def planting_trees(trees, length, width):
     """
-    Returns the minimum distance that trees have to be moved before they are all in a valid state.
+    Returns the minimum distance that trees have to be moved before they
+    are all in a valid state.
 
         Parameters:
-            tree (list<int>): A sorted list of integers with all trees' position along the road.
-            L (int): An integer with the length of the road.
-            W (int): An integer with the width of the road.
+            tree (list<int>): A sorted list of integers with all trees'
+                              position along the road.
+            length (int): An integer with the length of the road.
+            width (int): An integer with the width of the road.
 
         Returns:
             A float number with the total distance trees have been moved.
@@ -25,21 +28,22 @@ def planting_trees(trees, L, W):
 
     n_pairs = int(len(trees)/2)
 
-    space_between_pairs = L/(n_pairs-1)
+    space_between_pairs = length/(n_pairs-1)
 
     target_locations = [location*space_between_pairs for location in range(n_pairs)]
 
     cmatrix = [[0 for _ in range(n_pairs+1)] for _ in range(n_pairs+1)]
-    for ri in range(1, n_pairs+1):
-        cmatrix[ri][0] = cmatrix[ri-1][0] + sqrt(W + abs(trees[ri]-target_locations[ri-1])**2)
-    for li in range(1, n_pairs+1):
-        cmatrix[0][li] = cmatrix[0][li-1] + abs(trees[li]-target_locations[li-1])
-
-    for ri in range(1, n_pairs+1):
-        for li in range(1, n_pairs+1):
-            cmatrix[ri][li] = min(
-                cmatrix[ri-1][li] + sqrt(W + (trees[li + ri]-target_locations[ri-1])**2),
-                cmatrix[ri][li-1] + abs(trees[li + ri]-target_locations[li-1])
+    for r_i in range(1, n_pairs+1):
+        cmatrix[r_i][0] = cmatrix[r_i-1][0] + sqrt(
+                width + abs(trees[r_i]-target_locations[r_i-1])**2)
+    for l_i in range(1, n_pairs+1):
+        cmatrix[0][l_i] = cmatrix[0][l_i-1] + abs(trees[l_i]-target_locations[l_i-1])
+
+    for r_i in range(1, n_pairs+1):
+        for l_i in range(1, n_pairs+1):
+            cmatrix[r_i][l_i] = min(
+                cmatrix[r_i-1][l_i] + sqrt(width + (trees[l_i + r_i]-target_locations[r_i-1])**2),
+                cmatrix[r_i][l_i-1] + abs(trees[l_i + r_i]-target_locations[l_i-1])
             )
 
-    return cmatrix[n_pairs][n_pairs]
\ No newline at end of file
+    return cmatrix[n_pairs][n_pairs]
diff --git a/algorithms/dp/regex_matching.py b/algorithms/dp/regex_matching.py
index 72311d5..3b65e35 100644
--- a/algorithms/dp/regex_matching.py
+++ b/algorithms/dp/regex_matching.py
@@ -18,91 +18,44 @@ is_match("aa", ".*") → true
 is_match("ab", ".*") → true
 is_match("aab", "c*a*b") → true
 """
-import unittest
 
-class Solution(object):
-    def is_match(self, s, p):
-        m, n = len(s) + 1, len(p) + 1
-        matches = [[False] * n  for _ in range(m)]
-
-        # Match empty string with empty pattern
-        matches[0][0] = True
-
-        # Match empty string with .*
-        for i, element in enumerate(p[1:], 2):
-            matches[0][i] = matches[0][i - 2] and element == '*'
-
-        for i, ss in enumerate(s, 1):
-            for j, pp in enumerate(p, 1):
-                if pp != '*':
-                    # The previous character has matched and the current one
-                    # has to be matched. Two possible matches: the same or .
-                    matches[i][j] = matches[i - 1][j - 1] and \
-                                    (ss == pp or pp == '.')
-                else:
-                    # Horizontal look up [j - 2].
-                    # Not use the character before *.
-                    matches[i][j] |= matches[i][j - 2]
-
-                    # Vertical look up [i - 1].
-                    # Use at least one character before *.
-                    #   p a b *
-                    # s 1 0 0 0
-                    # a 0 1 0 1
-                    # b 0 0 1 1
-                    # b 0 0 0 ?
-                    if ss == p[j - 2] or p[j - 2] == '.':
-                        matches[i][j] |= matches[i - 1][j]
-
-        return matches[-1][-1]
-
-class TestSolution(unittest.TestCase):
-    def test_none_0(self):
-        s = ""
-        p = ""
-        self.assertTrue(Solution().is_match(s, p))
-
-    def test_none_1(self):
-        s = ""
-        p = "a"
-        self.assertFalse(Solution().is_match(s, p))
-
-    def test_no_symbol_equal(self):
-        s = "abcd"
-        p = "abcd"
-        self.assertTrue(Solution().is_match(s, p))
-
-    def test_no_symbol_not_equal_0(self):
-        s = "abcd"
-        p = "efgh"
-        self.assertFalse(Solution().is_match(s, p))
-
-    def test_no_symbol_not_equal_1(self):
-        s = "ab"
-        p = "abb"
-        self.assertFalse(Solution().is_match(s, p))
-
-    def test_symbol_0(self):
-        s = ""
-        p = "a*"
-        self.assertTrue(Solution().is_match(s, p))
-
-    def test_symbol_1(self):
-        s = "a"
-        p = "ab*"
-        self.assertTrue(Solution().is_match(s, p))
-
-    def test_symbol_2(self):
-        # E.g.
-        #   s a b b
-        # p 1 0 0 0
-        # a 0 1 0 0
-        # b 0 0 1 0
-        # * 0 1 1 1
-        s = "abb"
-        p = "ab*"
-        self.assertTrue(Solution().is_match(s, p))
-
-
-if __name__ == "__main__":
-    unittest.main()
+def is_match(str_a, str_b):
+    """Finds if `str_a` matches `str_b`
+
+    Keyword arguments:
+    str_a -- string
+    str_b -- string
+    """
+    len_a, len_b = len(str_a) + 1, len(str_b) + 1
+    matches = [[False] * len_b  for _ in range(len_a)]
+
+    # Match empty string with empty pattern
+    matches[0][0] = True
+
+    # Match empty string with .*
+    for i, element in enumerate(str_b[1:], 2):
+        matches[0][i] = matches[0][i - 2] and element == '*'
+
+    for i, char_a in enumerate(str_a, 1):
+        for j, char_b in enumerate(str_b, 1):
+            if char_b != '*':
+                # The previous character has matched and the current one
+                # has to be matched. Two possible matches: the same or .
+                matches[i][j] = matches[i - 1][j - 1] and \
+                                char_b in (char_a, '.')
+            else:
+                # Horizontal look up [j - 2].
+                # Not use the character before *.
+                matches[i][j] |= matches[i][j - 2]
+
+                # Vertical look up [i - 1].
+                # Use at least one character before *.
+                #   p a b *
+                # s 1 0 0 0
+                # a 0 1 0 1
+                # b 0 0 1 1
+                # b 0 0 0 ?
+                if char_a == str_b[j - 2] or str_b[j - 2] == '.':
+                    matches[i][j] |= matches[i - 1][j]
+
+    return matches[-1][-1]
diff --git a/algorithms/dp/rod_cut.py b/algorithms/dp/rod_cut.py
index b4a8224..d9259e8 100644
--- a/algorithms/dp/rod_cut.py
+++ b/algorithms/dp/rod_cut.py
@@ -1,24 +1,28 @@
-# A Dynamic Programming solution for Rod cutting problem
+"""A Dynamic Programming solution for Rod cutting problem
+"""
+
 INT_MIN = -32767
- 
-# Returns the best obtainable price for a rod of length n and
-# price[] as prices of different pieces
+
 def cut_rod(price):
+    """
+    Returns the best obtainable price for a rod of length n and
+    price[] as prices of different pieces
+    """
     n = len(price)
     val = [0]*(n+1)
- 
+
     # Build the table val[] in bottom up manner and return
     # the last entry from the table
     for i in range(1, n+1):
         max_val = INT_MIN
         for j in range(i):
-             max_val = max(max_val, price[j] + val[i-j-1])
+            max_val = max(max_val, price[j] + val[i-j-1])
         val[i] = max_val
- 
+
     return val[n]
- 
+
 # Driver program to test above functions
 arr = [1, 5, 8, 9, 10, 17, 17, 20]
 print("Maximum Obtainable Value is " + str(cut_rod(arr)))
- 
+
 # This code is contributed by Bhavya Jain
diff --git a/algorithms/dp/word_break.py b/algorithms/dp/word_break.py
index ea244dc..f520456 100644
--- a/algorithms/dp/word_break.py
+++ b/algorithms/dp/word_break.py
@@ -1,44 +1,41 @@
 """
 Given a non-empty string s and a dictionary wordDict
 containing a list of non-empty words,
-determine if s can be segmented into a space-separated
+determine if word can be segmented into a space-separated
 sequence of one or more dictionary words.
 You may assume the dictionary does not contain duplicate words.
 
 For example, given
-s = "leetcode",
+word = "leetcode",
 dict = ["leet", "code"].
 
 Return true because "leetcode" can be segmented as "leet code".
-"""
-
 
-"""
-s = abc word_dict = ["a","bc"]
+word = abc word_dict = ["a","bc"]
 True False False False
 
 """
 
 
 # TC: O(N^2)  SC: O(N)
-def word_break(s, word_dict):
+def word_break(word, word_dict):
     """
-    :type s: str
+    :type word: str
     :type word_dict: Set[str]
     :rtype: bool
     """
-    dp = [False] * (len(s)+1)
-    dp[0] = True
-    for i in range(1, len(s)+1):
+    dp_array = [False] * (len(word)+1)
+    dp_array[0] = True
+    for i in range(1, len(word)+1):
         for j in range(0, i):
-            if dp[j] and s[j:i] in word_dict:
-                dp[i] = True
+            if dp_array[j] and word[j:i] in word_dict:
+                dp_array[i] = True
                 break
-    return dp[-1]
+    return dp_array[-1]
 
 
 if __name__ == "__main__":
-    s = "keonkim"
+    STR = "keonkim"
     dic = ["keon", "kim"]
 
-    print(word_break(s, dic))
+    print(word_break(str, dic))
diff --git a/algorithms/graph/__init__.py b/algorithms/graph/__init__.py
index 3bf3a1c..1f52f9b 100644
--- a/algorithms/graph/__init__.py
+++ b/algorithms/graph/__init__.py
@@ -1,3 +1,7 @@
+"""
+Collection of algorithms on graphs.
+"""
+
 from .tarjan import *
 from .check_bipartite import *
 from .maximum_flow import *
diff --git a/algorithms/graph/bellman_ford.py b/algorithms/graph/bellman_ford.py
index 518f75c..ea1e046 100644
--- a/algorithms/graph/bellman_ford.py
+++ b/algorithms/graph/bellman_ford.py
@@ -1,26 +1,29 @@
-'''
-This Bellman-Ford Code is for determination whether we can get
-shortest path from given graph or not for single-source shortest-paths problem.
-In other words, if given graph has any negative-weight cycle that is reachable
-from the source, then it will give answer False for "no solution exits".
-For argument graph, it should be a dictionary type
-such as
-graph = {
-    'a': {'b': 6, 'e': 7},
-    'b': {'c': 5, 'd': -4, 'e': 8},
-    'c': {'b': -2},
-    'd': {'a': 2, 'c': 7},
-    'e': {'b': -3}
-}
-'''
+"""
+Determination of single-source shortest-path.
+"""
 
 def bellman_ford(graph, source):
+    """
+    This Bellman-Ford Code is for determination whether we can get
+    shortest path from given graph or not for single-source shortest-paths problem.
+    In other words, if given graph has any negative-weight cycle that is reachable
+    from the source, then it will give answer False for "no solution exits".
+    For argument graph, it should be a dictionary type
+    such as
+    graph = {
+        'a': {'b': 6, 'e': 7},
+        'b': {'c': 5, 'd': -4, 'e': 8},
+        'c': {'b': -2},
+        'd': {'a': 2, 'c': 7},
+        'e': {'b': -3}
+    }
+    """
     weight = {}
     pre_node = {}
 
     initialize_single_source(graph, source, weight, pre_node)
 
-    for i in range(1, len(graph)):
+    for _ in range(1, len(graph)):
         for node in graph:
             for adjacent in graph[node]:
                 if weight[adjacent] > weight[node] + graph[node][adjacent]:
@@ -35,10 +38,11 @@ def bellman_ford(graph, source):
     return True
 
 def initialize_single_source(graph, source, weight, pre_node):
-
+    """
+    Initialize data structures for Bellman-Ford algorithm.
+    """
     for node in graph:
         weight[node] = float('inf')
         pre_node[node] = None
 
     weight[source] = 0
-    
diff --git a/algorithms/graph/check_bipartite.py b/algorithms/graph/check_bipartite.py
index dacc003..51a84ab 100644
--- a/algorithms/graph/check_bipartite.py
+++ b/algorithms/graph/check_bipartite.py
@@ -1,39 +1,40 @@
 """
-
 Bipartite graph is a graph whose vertices can be divided into two disjoint and independent sets.
 (https://en.wikipedia.org/wiki/Bipartite_graph)
-
-Time complexity is O(|E|)
-Space complexity is O(|V|)
-
 """
 
 def check_bipartite(adj_list):
+    """
+    Determine if the given graph is bipartite.
 
-    V = len(adj_list)
+    Time complexity is O(|E|)
+    Space complexity is O(|V|)
+    """
 
-    # Divide vertexes in the graph into set_type 1 and 2
+    vertices = len(adj_list)
+
+    # Divide vertexes in the graph into set_type 0 and 1
     # Initialize all set_types as -1
-    set_type = [-1 for v in range(V)]
+    set_type = [-1 for v in range(vertices)]
     set_type[0] = 0
 
-    q = [0]
+    queue = [0]
 
-    while q:
-        v = q.pop(0)
+    while queue:
+        current = queue.pop(0)
 
         # If there is a self-loop, it cannot be bipartite
-        if adj_list[v][v]:
+        if adj_list[current][current]:
             return False
 
-        for u in range(V):
-            if adj_list[v][u]:
-                if set_type[u] == set_type[v]:
+        for adjacent in range(vertices):
+            if adj_list[current][adjacent]:
+                if set_type[adjacent] == set_type[current]:
                     return False
-                elif set_type[u] == -1:
+
+                if set_type[adjacent] == -1:
                     # set type of u opposite of v
-                    set_type[u] = 1 - set_type[v]
-                    q.append(u)
+                    set_type[adjacent] = 1 - set_type[current]
+                    queue.append(adjacent)
 
     return True
-
diff --git a/algorithms/graph/check_digraph_strongly_connected.py b/algorithms/graph/check_digraph_strongly_connected.py
index 25ae80c..03dd6ab 100644
--- a/algorithms/graph/check_digraph_strongly_connected.py
+++ b/algorithms/graph/check_digraph_strongly_connected.py
@@ -1,53 +1,69 @@
+"""
+In a directed graph, a strongly connected component is a set of vertices such
+that for any pairs of vertices u and v there exists a path (u-...-v) that
+connects them. A graph is strongly connected if it is a single strongly
+connected component.
+"""
+
 from collections import defaultdict
 
 class Graph:
-	def __init__(self,v):
-		self.v = v
-		self.graph = defaultdict(list)
-
-	def add_edge(self,u,v):
-		self.graph[u].append(v)
-
-	def dfs(self):
-		visited = [False] * self.v
-		self.dfs_util(0,visited)
-		if visited == [True]*self.v:
-			return True
-		return False
-
-	def dfs_util(self,i,visited):
-		visited[i] = True
-		for u in self.graph[i]:
-			if not(visited[u]):
-				self.dfs_util(u,visited)
-
-	def reverse_graph(self):
-		g = Graph(self.v)
-		for i in range(len(self.graph)):
-			for j in self.graph[i]:
-				g.add_edge(j,i)
-		return g
-
-
-	def is_sc(self):
-		if self.dfs():
-			gr = self.reverse_graph()
-			if gr.dfs():
-				return True
-		return False
-
-
-g1 = Graph(5)
-g1.add_edge(0, 1)
-g1.add_edge(1, 2)
-g1.add_edge(2, 3)
-g1.add_edge(3, 0)
-g1.add_edge(2, 4)
-g1.add_edge(4, 2)
-print ("Yes") if g1.is_sc() else print("No")
- 
-g2 = Graph(4)
-g2.add_edge(0, 1)
-g2.add_edge(1, 2)
-g2.add_edge(2, 3)
-print ("Yes") if g2.is_sc() else print("No")
+    """
+    A directed graph where edges are one-way (a two-way edge can be represented by using two edges).
+    """
+
+    def __init__(self,vertex_count):
+        """
+        Create a new graph with vertex_count vertices.
+        """
+
+        self.vertex_count = vertex_count
+        self.graph = defaultdict(list)
+
+    def add_edge(self,source,target):
+        """
+        Add an edge going from source to target
+        """
+        self.graph[source].append(target)
+
+    def dfs(self):
+        """
+        Determine if all nodes are reachable from node 0
+        """
+        visited = [False] * self.vertex_count
+        self.dfs_util(0,visited)
+        if visited == [True]*self.vertex_count:
+            return True
+        return False
+
+    def dfs_util(self,source,visited):
+        """
+        Determine if all nodes are reachable from the given node
+        """
+        visited[source] = True
+        for adjacent in self.graph[source]:
+            if not visited[adjacent]:
+                self.dfs_util(adjacent,visited)
+
+    def reverse_graph(self):
+        """
+        Create a new graph where every edge a->b is replaced with an edge b->a
+        """
+        reverse_graph = Graph(self.vertex_count)
+        for source, adjacent in self.graph.items():
+            for target in adjacent:
+                # Note: we reverse the order of arguments
+                # pylint: disable=arguments-out-of-order
+                reverse_graph.add_edge(target,source)
+        return reverse_graph
+
+
+    def is_strongly_connected(self):
+        """
+        Determine if the graph is strongly connected.
+        """
+        if self.dfs():
+            reversed_graph = self.reverse_graph()
+            if reversed_graph.dfs():
+                return True
+        return False
diff --git a/algorithms/graph/clone_graph.py b/algorithms/graph/clone_graph.py
index 0fbae1d..84d0324 100644
--- a/algorithms/graph/clone_graph.py
+++ b/algorithms/graph/clone_graph.py
@@ -1,4 +1,4 @@
-"""
+r"""
 Clone an undirected graph. Each node in the graph contains a label and a list
 of its neighbors.
 
@@ -29,69 +29,95 @@ Visually, the graph looks like the following:
 import collections
 
 
-# Definition for a undirected graph node
 class UndirectedGraphNode:
-    def __init__(self, x):
-        self.label = x
+    """
+    A node in an undirected graph. Contains a label and a list of neighbouring
+    nodes (initially empty).
+    """
+
+    def __init__(self, label):
+        self.label = label
         self.neighbors = []
 
+    def shallow_copy(self):
+        """
+        Return a shallow copy of this node (ignoring any neighbors)
+        """
+        return UndirectedGraphNode(self.label)
+
+    def add_neighbor(self, node):
+        """
+        Adds a new neighbor
+        """
+        self.neighbors.append(node)
+
 
-# BFS
 def clone_graph1(node):
+    """
+    Returns a new graph as seen from the given node using a breadth first search (BFS).
+    """
     if not node:
-        return
-    node_copy = UndirectedGraphNode(node.label)
+        return None
+    node_copy = node.shallow_copy()
     dic = {node: node_copy}
     queue = collections.deque([node])
     while queue:
         node = queue.popleft()
         for neighbor in node.neighbors:
             if neighbor not in dic:  # neighbor is not visited
-                neighbor_copy = UndirectedGraphNode(neighbor.label)
+                neighbor_copy = neighbor.shallow_copy()
                 dic[neighbor] = neighbor_copy
-                dic[node].neighbors.append(neighbor_copy)
+                dic[node].add_neighbor(neighbor_copy)
                 queue.append(neighbor)
             else:
-                dic[node].neighbors.append(dic[neighbor])
+                dic[node].add_neighbor(dic[neighbor])
     return node_copy
 
 
-# DFS iteratively
 def clone_graph2(node):
+    """
+    Returns a new graph as seen from the given node using an iterative depth first search (DFS).
+    """
     if not node:
-        return
-    node_copy = UndirectedGraphNode(node.label)
+        return None
+    node_copy = node.shallow_copy()
     dic = {node: node_copy}
     stack = [node]
     while stack:
         node = stack.pop()
         for neighbor in node.neighbors:
             if neighbor not in dic:
-                neighbor_copy = UndirectedGraphNode(neighbor.label)
+                neighbor_copy = neighbor.shallow_copy()
                 dic[neighbor] = neighbor_copy
-                dic[node].neighbors.append(neighbor_copy)
+                dic[node].add_neighbor(neighbor_copy)
                 stack.append(neighbor)
             else:
-                dic[node].neighbors.append(dic[neighbor])
+                dic[node].add_neighbor(dic[neighbor])
     return node_copy
 
 
-# DFS recursively
 def clone_graph(node):
+    """
+    Returns a new graph as seen from the given node using a recursive depth first search (DFS).
+    """
     if not node:
-        return
-    node_copy = UndirectedGraphNode(node.label)
+        return None
+    node_copy = node.shallow_copy()
     dic = {node: node_copy}
     dfs(node, dic)
     return node_copy
 
 
 def dfs(node, dic):
+    """
+    Clones a graph using a recursive depth first search. Stores the clones in
+    the dictionary, keyed by the original nodes.
+    """
     for neighbor in node.neighbors:
         if neighbor not in dic:
-            neighbor_copy = UndirectedGraphNode(neighbor.label)
+            neighbor_copy = neighbor.shallow_copy()
             dic[neighbor] = neighbor_copy
-            dic[node].neighbors.append(neighbor_copy)
+            dic[node].add_neighbor(neighbor_copy)
             dfs(neighbor, dic)
         else:
-            dic[node].neighbors.append(dic[neighbor])
+            dic[node].add_neighbor(dic[neighbor])
diff --git a/algorithms/graph/count_connected_number_of_component.py b/algorithms/graph/count_connected_number_of_component.py
index a944cf0..a58eda6 100644
--- a/algorithms/graph/count_connected_number_of_component.py
+++ b/algorithms/graph/count_connected_number_of_component.py
@@ -1,7 +1,7 @@
 #count connected no of component using DFS
 '''
-In graph theory, a component, sometimes called a connected component, 
-of an undirected graph is a subgraph in which any 
+In graph theory, a component, sometimes called a connected component,
+of an undirected graph is a subgraph in which any
 two vertices are connected to each other by paths.
 
 Example:
@@ -19,16 +19,16 @@ Example:
 
 # Code is Here
 
-def dfs(source,visited,l):
+def dfs(source,visited,adjacency_list):
     ''' Function that performs DFS '''
 
     visited[source] = True
-    for child in l[source]:
+    for child in adjacency_list[source]:
         if not visited[child]:
-            dfs(child,visited,l)
-            
-def count_components(l,size):
-    ''' 
+            dfs(child,visited,adjacency_list)
+
+def count_components(adjacency_list,size):
+    '''
     Function that counts the Connected components on bases of DFS.
     return type : int
     '''
@@ -37,18 +37,23 @@ def count_components(l,size):
     visited = [False]*(size+1)
     for i in range(1,size+1):
         if not visited[i]:
-            dfs(i,visited,l)
+            dfs(i,visited,adjacency_list)
             count+=1
-    return count   
+    return count
+
+def main():
+    """
+    Example application
+    """
+    node_count,edge_count = map(int, input("Enter the Number of Nodes and Edges \n").split(' '))
+    adjacency = [[] for _ in range(node_count+1)]
+    for _ in range(edge_count):
+        print("Enter the edge's Nodes in form of `source target`\n")
+        source,target = map(int,input().split(' '))
+        adjacency[source].append(target)
+        adjacency[target].append(source)
+    print("Total number of Connected Components are : ", count_components(adjacency,node_count))
 
-    
 # Driver code
 if __name__ == '__main__':
-    n,m = map(int, input("Enter the Number of Nodes and Edges \n").split(' '))
-    l = [[] for _ in range(n+1)]
-    for i in range(m):
-        print("Enter the edge's Nodes in form of a b\n")
-        a,b = map(int,input().split(' '))
-        l[a].append(b)
-        l[b].append(a)
-    print("Total number of Connected Components are : ", count_components(l,n))
+    main()
diff --git a/algorithms/graph/cycle_detection.py b/algorithms/graph/cycle_detection.py
index 61cf61c..0821b1c 100644
--- a/algorithms/graph/cycle_detection.py
+++ b/algorithms/graph/cycle_detection.py
@@ -9,27 +9,22 @@ from enum import Enum
 
 
 class TraversalState(Enum):
+    """
+    For a given node:
+        - WHITE: has not been visited yet
+        - GRAY: is currently being investigated for a cycle
+        - BLACK: is not part of a cycle
+    """
     WHITE = 0
     GRAY = 1
     BLACK = 2
 
-
-example_graph_with_cycle = {'A': ['B', 'C'],
-                            'B': ['D'],
-                            'C': ['F'],
-                            'D': ['E', 'F'],
-                            'E': ['B'],
-                            'F': []}
-
-example_graph_without_cycle = {'A': ['B', 'C'],
-                               'B': ['D', 'E'],
-                               'C': ['F'],
-                               'D': ['E'],
-                               'E': [],
-                               'F': []}
-                               
-
 def is_in_cycle(graph, traversal_states, vertex):
+    """
+    Determines if the given vertex is in a cycle.
+
+    :param: traversal_states: for each vertex, the state it is in
+    """
     if traversal_states[vertex] == TraversalState.GRAY:
         return True
     traversal_states[vertex] = TraversalState.GRAY
@@ -41,12 +36,20 @@ def is_in_cycle(graph, traversal_states, vertex):
 
 
 def contains_cycle(graph):
+    """
+    Determines if there is a cycle in the given graph.
+    The graph should be given as a dictionary:
+
+        graph = {'A': ['B', 'C'],
+                 'B': ['D'],
+                 'C': ['F'],
+                 'D': ['E', 'F'],
+                 'E': ['B'],
+                 'F': []}
+    """
     traversal_states = {vertex: TraversalState.WHITE for vertex in graph}
     for vertex, state in traversal_states.items():
         if (state == TraversalState.WHITE and
            is_in_cycle(graph, traversal_states, vertex)):
             return True
     return False
-
-print(contains_cycle(example_graph_with_cycle))
-print(contains_cycle(example_graph_without_cycle))
diff --git a/algorithms/graph/dijkstra.py b/algorithms/graph/dijkstra.py
index 2cf0430..e5022e3 100644
--- a/algorithms/graph/dijkstra.py
+++ b/algorithms/graph/dijkstra.py
@@ -1,36 +1,49 @@
-#Dijkstra's single source shortest path algorithm
+"""
+Dijkstra's single-source shortest-path algorithm
+"""
 
 class Dijkstra():
+    """
+    A fully connected directed graph with edge weights
+    """
 
-    def __init__(self, vertices):
-        self.vertices = vertices
-        self.graph = [[0 for column in range(vertices)] for row in range(vertices)]
+    def __init__(self, vertex_count):
+        self.vertex_count = vertex_count
+        self.graph = [[0 for _ in range(vertex_count)] for _ in range(vertex_count)]
 
     def min_distance(self, dist, min_dist_set):
+        """
+        Find the vertex that is closest to the visited set
+        """
         min_dist = float("inf")
-        for v in range(self.vertices):
-            if dist[v] < min_dist and min_dist_set[v] == False:
-                min_dist = dist[v]
-                min_index = v
+        for target in range(self.vertex_count):
+            if min_dist_set[target]:
+                continue
+            if dist[target] < min_dist:
+                min_dist = dist[target]
+                min_index = target
         return min_index
 
     def dijkstra(self, src):
-
-        dist = [float("inf")] * self.vertices
+        """
+        Given a node, returns the shortest distance to every other node
+        """
+        dist = [float("inf")] * self.vertex_count
         dist[src] = 0
-        min_dist_set = [False] * self.vertices
-
-        for count in range(self.vertices):
+        min_dist_set = [False] * self.vertex_count
 
+        for _ in range(self.vertex_count):
             #minimum distance vertex that is not processed
-            u = self.min_distance(dist, min_dist_set)
+            source = self.min_distance(dist, min_dist_set)
 
             #put minimum distance vertex in shortest tree
-            min_dist_set[u] = True
+            min_dist_set[source] = True
 
             #Update dist value of the adjacent vertices
-            for v in range(self.vertices):
-                if self.graph[u][v] > 0 and min_dist_set[v] == False and dist[v] > dist[u] + self.graph[u][v]:
-                    dist[v] = dist[u] + self.graph[u][v]
+            for target in range(self.vertex_count):
+                if self.graph[source][target] <= 0 or min_dist_set[target]:
+                    continue
+                if dist[target] > dist[source] + self.graph[source][target]:
+                    dist[target] = dist[source] + self.graph[source][target]
 
         return dist
diff --git a/algorithms/graph/find_all_cliques.py b/algorithms/graph/find_all_cliques.py
index 10f7a24..f1db16e 100644
--- a/algorithms/graph/find_all_cliques.py
+++ b/algorithms/graph/find_all_cliques.py
@@ -1,12 +1,19 @@
-# takes dict of sets
-# each key is a vertex
-# value is set of all edges connected to vertex
-# returns list of lists (each sub list is a maximal clique)
-# implementation of the basic algorithm described in:
-# Bron, Coen; Kerbosch, Joep (1973), "Algorithm 457: finding all cliques of an undirected graph",
-
+"""
+Finds all cliques in an undirected graph. A clique is a set of vertices in the
+graph such that the subgraph is fully connected (ie. for any pair of nodes in
+the subgraph there is an edge between them).
+"""
 
 def find_all_cliques(edges):
+    """
+    takes dict of sets
+    each key is a vertex
+    value is set of all edges connected to vertex
+    returns list of lists (each sub list is a maximal clique)
+    implementation of the basic algorithm described in:
+    Bron, Coen; Kerbosch, Joep (1973), "Algorithm 457: finding all cliques of an undirected graph",
+    """
+
     def expand_clique(candidates, nays):
         nonlocal compsub
         if not candidates and not nays:
diff --git a/algorithms/graph/find_path.py b/algorithms/graph/find_path.py
index a188005..253e43c 100644
--- a/algorithms/graph/find_path.py
+++ b/algorithms/graph/find_path.py
@@ -1,14 +1,14 @@
-myGraph = {'A': ['B', 'C'],
-         'B': ['C', 'D'],
-         'C': ['D', 'F'],
-         'D': ['C'],
-         'E': ['F'],
-         'F': ['C']}
+"""
+Functions for finding paths in graphs.
+"""
 
-# find path from start to end using recursion with backtracking
+# pylint: disable=dangerous-default-value
 def find_path(graph, start, end, path=[]):
+    """
+    Find a path between two nodes using recursion and backtracking.
+    """
     path = path + [start]
-    if (start == end):
+    if start == end:
         return path
     if not start in graph:
         return None
@@ -18,13 +18,16 @@ def find_path(graph, start, end, path=[]):
             return newpath
     return None
 
-# find all path
+# pylint: disable=dangerous-default-value
 def find_all_path(graph, start, end, path=[]):
+    """
+    Find all paths between two nodes using recursion and backtracking
+    """
     path = path + [start]
-    if (start == end):
+    if start == end:
         return [path]
     if not start in graph:
-        return None
+        return []
     paths = []
     for node in graph[start]:
         if node not in path:
@@ -34,6 +37,9 @@ def find_all_path(graph, start, end, path=[]):
     return paths
 
 def find_shortest_path(graph, start, end, path=[]):
+    """
+    find the shortest path between two nodes
+    """
     path = path + [start]
     if start == end:
         return path
@@ -47,6 +53,3 @@ def find_shortest_path(graph, start, end, path=[]):
                 if not shortest or len(newpath) < len(shortest):
                     shortest = newpath
     return shortest
-
-print(find_all_path(myGraph, 'A', 'F'))
-# print(find_shortest_path(myGraph, 'A', 'D'))
diff --git a/algorithms/graph/graph.py b/algorithms/graph/graph.py
index 31e5645..5d43059 100644
--- a/algorithms/graph/graph.py
+++ b/algorithms/graph/graph.py
@@ -3,24 +3,31 @@ These are classes to represent a Graph and its elements.
 It can be shared across graph algorithms.
 """
 
-class Node(object):
+class Node:
+    """
+    A node/vertex in a graph.
+    """
+
     def __init__(self, name):
         self.name = name
 
     @staticmethod
     def get_name(obj):
+        """
+        Return the name of the node
+        """
         if isinstance(obj, Node):
             return obj.name
-        elif isinstance(obj, str):
+        if isinstance(obj, str):
             return obj
         return''
-    
+
     def __eq__(self, obj):
         return self.name == self.get_name(obj)
 
     def __repr__(self):
         return self.name
-    
+
     def __hash__(self):
         return hash(self.name)
 
@@ -42,72 +49,63 @@ class Node(object):
     def __bool__(self):
         return self.name
 
-class DirectedEdge(object):
+class DirectedEdge:
+    """
+    A directed edge in a directed graph.
+    Stores the source and target node of the edge.
+    """
+
     def __init__(self, node_from, node_to):
-        self.nf = node_from
-        self.nt = node_to
+        self.source = node_from
+        self.target = node_to
 
     def __eq__(self, obj):
         if isinstance(obj, DirectedEdge):
-            return obj.nf == self.nf and obj.nt == self.nt
+            return obj.source == self.source and obj.target == self.target
         return False
-    
+
     def __repr__(self):
-        return '({0} -> {1})'.format(self.nf, self.nt)
+        return f"({self.source} -> {self.target})"
+
+class DirectedGraph:
+    """
+    A directed graph.
+    Stores a set of nodes, edges and adjacency matrix.
+    """
 
-class DirectedGraph(object):
+    # pylint: disable=dangerous-default-value
     def __init__(self, load_dict={}):
         self.nodes = []
         self.edges = []
-        self.adjmt = {}
+        self.adjacency_list = {}
 
-        if load_dict and type(load_dict) == dict:
-            for v in load_dict:
-                node_from = self.add_node(v)
-                self.adjmt[node_from] = []
-                for w in load_dict[v]:
-                    node_to = self.add_node(w)
-                    self.adjmt[node_from].append(node_to)
-                    self.add_edge(v, w)
+        if load_dict and isinstance(load_dict, dict):
+            for vertex in load_dict:
+                node_from = self.add_node(vertex)
+                self.adjacency_list[node_from] = []
+                for neighbor in load_dict[vertex]:
+                    node_to = self.add_node(neighbor)
+                    self.adjacency_list[node_from].append(node_to)
+                    self.add_edge(vertex, neighbor)
 
     def add_node(self, node_name):
+        """
+        Add a new named node to the graph.
+        """
         try:
             return self.nodes[self.nodes.index(node_name)]
         except ValueError:
             node = Node(node_name)
             self.nodes.append(node)
             return node
-    
+
     def add_edge(self, node_name_from, node_name_to):
+        """
+        Add a new edge to the graph between two nodes.
+        """
         try:
             node_from = self.nodes[self.nodes.index(node_name_from)]
             node_to = self.nodes[self.nodes.index(node_name_to)]
             self.edges.append(DirectedEdge(node_from, node_to))
         except ValueError:
             pass
-
-class Graph:
-    def __init__(self, vertices):
-        # No. of vertices
-        self.V = vertices
-
-        # default dictionary to store graph
-        self.graph = {}
-
-        # To store transitive closure
-        self.tc = [[0 for j in range(self.V)] for i in range(self.V)]
-
-    # function to add an edge to graph
-    def add_edge(self, u, v):
-        if u in self.graph:
-            self.graph[u].append(v)
-        else:
-            self.graph[u] = [v]
-            
-#g = Graph(4)
-#g.add_edge(0, 1)
-#g.add_edge(0, 2)
-#g.add_edge(1, 2)
-#g.add_edge(2, 0)
-#g.add_edge(2, 3)
-#g.add_edge(3, 3)
diff --git a/algorithms/graph/markov_chain.py b/algorithms/graph/markov_chain.py
index c588311..78c50bd 100644
--- a/algorithms/graph/markov_chain.py
+++ b/algorithms/graph/markov_chain.py
@@ -1,26 +1,39 @@
-import random
+"""
+Implements a markov chain. Chains are described using a dictionary:
+
+    my_chain = {
+        'A': {'A': 0.6,
+              'E': 0.4},
+        'E': {'A': 0.7,
+              'E': 0.3}
+    }
+"""
 
-my_chain = {
-    'A': {'A': 0.6,
-          'E': 0.4},
-    'E': {'A': 0.7,
-          'E': 0.3}
-}
+import random
 
 def __choose_state(state_map):
+    """
+    Choose the next state randomly
+    """
     choice = random.random()
     probability_reached = 0
     for state, probability in state_map.items():
         probability_reached += probability
         if probability_reached > choice:
             return state
+    return None
 
 def next_state(chain, current_state):
+    """
+    Given a markov-chain, randomly chooses the next state given the current state.
+    """
     next_state_map = chain.get(current_state)
-    next_state = __choose_state(next_state_map)
-    return next_state
+    return __choose_state(next_state_map)
 
 def iterating_markov_chain(chain, state):
+    """
+    Yield a sequence of states given a markov chain and the initial state
+    """
     while True:
         state = next_state(chain, state)
         yield state
diff --git a/algorithms/graph/maximum_flow.py b/algorithms/graph/maximum_flow.py
index ca78244..b46e707 100644
--- a/algorithms/graph/maximum_flow.py
+++ b/algorithms/graph/maximum_flow.py
@@ -8,16 +8,22 @@ capacity[i][j] implies the capacity of the edge from i to j.
 If there is no edge from i to j, capacity[i][j] should be zero.
 """
 
-import queue
+from queue import Queue
 
+# pylint: disable=too-many-arguments
 def dfs(capacity, flow, visit, vertices, idx, sink, current_flow = 1 << 63):
+    """
+    Depth First Search implementation for Ford-Fulkerson algorithm.
+    """
+
     # DFS function for ford_fulkerson algorithm.
-    if idx == sink: 
+    if idx == sink:
         return current_flow
     visit[idx] = True
     for nxt in range(vertices):
         if not visit[nxt] and flow[idx][nxt] < capacity[idx][nxt]:
-            tmp = dfs(capacity, flow, visit, vertices, nxt, sink, min(current_flow, capacity[idx][nxt]-flow[idx][nxt]))
+            available_flow = min(current_flow, capacity[idx][nxt]-flow[idx][nxt])
+            tmp = dfs(capacity, flow, visit, vertices, nxt, sink, available_flow)
             if tmp:
                 flow[idx][nxt] += tmp
                 flow[nxt][idx] -= tmp
@@ -25,38 +31,42 @@ def dfs(capacity, flow, visit, vertices, idx, sink, current_flow = 1 << 63):
     return 0
 
 def ford_fulkerson(capacity, source, sink):
-    # Computes maximum flow from source to sink using DFS.
-    # Time Complexity : O(Ef)
-    # E is the number of edges and f is the maximum flow in the graph.
+    """
+    Computes maximum flow from source to sink using DFS.
+    Time Complexity : O(Ef)
+    E is the number of edges and f is the maximum flow in the graph.
+    """
     vertices = len(capacity)
     ret = 0
-    flow = [[0]*vertices for i in range(vertices)]
+    flow = [[0]*vertices for _ in range(vertices)]
     while True:
-        visit = [False for i in range(vertices)]
+        visit = [False for _ in range(vertices)]
         tmp = dfs(capacity, flow, visit, vertices, source, sink)
-        if tmp: 
+        if tmp:
             ret += tmp
-        else: 
+        else:
             break
     return ret
 
 def edmonds_karp(capacity, source, sink):
-    # Computes maximum flow from source to sink using BFS.
-    # Time complexity : O(V*E^2)
-    # V is the number of vertices and E is the number of edges.
+    """
+    Computes maximum flow from source to sink using BFS.
+    Time complexity : O(V*E^2)
+    V is the number of vertices and E is the number of edges.
+    """
     vertices = len(capacity)
     ret = 0
-    flow = [[0]*vertices for i in range(vertices)]
+    flow = [[0]*vertices for _ in range(vertices)]
     while True:
         tmp = 0
-        q = queue.Queue()
-        visit = [False for i in range(vertices)]
-        par = [-1 for i in range(vertices)]
+        queue = Queue()
+        visit = [False for _ in range(vertices)]
+        par = [-1 for _ in range(vertices)]
         visit[source] = True
-        q.put((source, 1 << 63))
+        queue.put((source, 1 << 63))
         # Finds new flow using BFS.
-        while q.qsize():
-            front = q.get()
+        while queue.qsize():
+            front = queue.get()
             idx, current_flow = front
             if idx == sink:
                 tmp = current_flow
@@ -65,8 +75,8 @@ def edmonds_karp(capacity, source, sink):
                 if not visit[nxt] and flow[idx][nxt] < capacity[idx][nxt]:
                     visit[nxt] = True
                     par[nxt] = idx
-                    q.put((nxt, min(current_flow, capacity[idx][nxt]-flow[idx][nxt])))
-        if par[sink] == -1: 
+                    queue.put((nxt, min(current_flow, capacity[idx][nxt]-flow[idx][nxt])))
+        if par[sink] == -1:
             break
         ret += tmp
         parent = par[sink]
@@ -80,31 +90,35 @@ def edmonds_karp(capacity, source, sink):
     return ret
 
 def dinic_bfs(capacity, flow, level, source, sink):
-    # BFS function for Dinic algorithm.
-    # Check whether sink is reachable only using edges that is not full.
-
+    """
+    BFS function for Dinic algorithm.
+    Check whether sink is reachable only using edges that is not full.
+    """
     vertices = len(capacity)
-    q = queue.Queue()
-    q.put(source)
+    queue = Queue()
+    queue.put(source)
     level[source] = 0
-    while q.qsize():
-        front = q.get()
+    while queue.qsize():
+        front = queue.get()
         for nxt in range(vertices):
             if level[nxt] == -1 and flow[front][nxt] < capacity[front][nxt]:
                 level[nxt] = level[front] + 1
-                q.put(nxt)
+                queue.put(nxt)
     return level[sink] != -1
 
 def dinic_dfs(capacity, flow, level, idx, sink, work, current_flow = 1 << 63):
-    # DFS function for Dinic algorithm.
-    # Finds new flow using edges that is not full.
+    """
+    DFS function for Dinic algorithm.
+    Finds new flow using edges that is not full.
+    """
     if idx == sink:
         return current_flow
     vertices = len(capacity)
     while work[idx] < vertices:
         nxt = work[idx]
         if level[nxt] == level[idx] + 1 and flow[idx][nxt] < capacity[idx][nxt]:
-            tmp = dinic_dfs(capacity, flow, level, nxt, sink, work, min(current_flow, capacity[idx][nxt] - flow[idx][nxt])) 
+            available_flow = min(current_flow, capacity[idx][nxt] - flow[idx][nxt])
+            tmp = dinic_dfs(capacity, flow, level, nxt, sink, work, available_flow)
             if tmp > 0:
                 flow[idx][nxt] += tmp
                 flow[nxt][idx] -= tmp
@@ -113,9 +127,11 @@ def dinic_dfs(capacity, flow, level, idx, sink, work, current_flow = 1 << 63):
     return 0
 
 def dinic(capacity, source, sink):
-    # Computes maximum flow from source to sink using Dinic algorithm.
-    # Time complexity : O(V^2*E)
-    # V is the number of vertices and E is the number of edges.
+    """
+    Computes maximum flow from source to sink using Dinic algorithm.
+    Time complexity : O(V^2*E)
+    V is the number of vertices and E is the number of edges.
+    """
     vertices = len(capacity)
     flow = [[0]*vertices for i in range(vertices)]
     ret = 0
@@ -131,4 +147,3 @@ def dinic(capacity, source, sink):
             else:
                 break
     return ret
-
diff --git a/algorithms/graph/maximum_flow_bfs.py b/algorithms/graph/maximum_flow_bfs.py
index 4d2d032..bd056c8 100644
--- a/algorithms/graph/maximum_flow_bfs.py
+++ b/algorithms/graph/maximum_flow_bfs.py
@@ -9,12 +9,12 @@ Time complexity - O(Ef)
 
 example
 
-graph = [[0, 16, 13, 0, 0, 0], 
-        [0, 0, 10, 12, 0, 0], 
-        [0, 4, 0, 0, 14, 0], 
-        [0, 0, 9, 0, 0, 20], 
-        [0, 0, 0, 7, 0, 4], 
-        [0, 0, 0, 0, 0, 0]] 
+graph = [[0, 16, 13, 0, 0, 0],
+        [0, 0, 10, 12, 0, 0],
+        [0, 4, 0, 0, 14, 0],
+        [0, 0, 9, 0, 0, 20],
+        [0, 0, 0, 7, 0, 4],
+        [0, 0, 0, 0, 0, 0]]
 
 answer should be
 
@@ -26,27 +26,30 @@ import queue
 import math
 
 def maximum_flow_bfs(adjacency_matrix):
+    """
+    Get the maximum flow through a graph using a breadth first search
+    """
     #initial setting
     new_array = copy.deepcopy(adjacency_matrix)
     total = 0
 
-    while(1):
+    while True:
         #setting min to max_value
-        min = math.inf
+        min_flow = math.inf
         #save visited nodes
         visited = [0]*len(new_array)
         #save parent nodes
         path = [0]*len(new_array)
-        
+
         #initialize queue for BFS
         bfs = queue.Queue()
 
-        #initial setting 
+        #initial setting
         visited[0] = 1
         bfs.put(0)
 
         #BFS to find path
-        while(bfs.qsize() > 0):
+        while bfs.qsize() > 0:
             #pop from queue
             src = bfs.get()
             for k in range(len(new_array)):
@@ -56,29 +59,29 @@ def maximum_flow_bfs(adjacency_matrix):
                     visited[k] = 1
                     bfs.put(k)
                     path[k] = src
-            
+
         #if there is no path from src to sink
-        if(visited[len(new_array) - 1] == 0):
+        if visited[len(new_array) - 1] == 0:
             break
-        
+
         #initial setting
         tmp = len(new_array) - 1
 
         #Get minimum flow
-        while(tmp != 0):
+        while tmp != 0:
             #find minimum flow
-            if(min > new_array[path[tmp]][tmp]):
-                min = new_array[path[tmp]][tmp]
+            if min_flow > new_array[path[tmp]][tmp]:
+                min_flow = new_array[path[tmp]][tmp]
             tmp = path[tmp]
 
         #initial setting
         tmp = len(new_array) - 1
 
         #reduce capacity
-        while(tmp != 0):
-            new_array[path[tmp]][tmp] = new_array[path[tmp]][tmp] - min
+        while tmp != 0:
+            new_array[path[tmp]][tmp] = new_array[path[tmp]][tmp] - min_flow
             tmp = path[tmp]
 
-        total = total + min
-    
+        total = total + min_flow
+
     return total
diff --git a/algorithms/graph/maximum_flow_dfs.py b/algorithms/graph/maximum_flow_dfs.py
index 2d89d6b..e27c4e8 100644
--- a/algorithms/graph/maximum_flow_dfs.py
+++ b/algorithms/graph/maximum_flow_dfs.py
@@ -9,12 +9,12 @@ Time complexity - O(Ef)
 
 example
 
-graph = [[0, 16, 13, 0, 0, 0], 
-        [0, 0, 10, 12, 0, 0], 
-        [0, 4, 0, 0, 14, 0], 
-        [0, 0, 9, 0, 0, 20], 
-        [0, 0, 0, 7, 0, 4], 
-        [0, 0, 0, 0, 0, 0]] 
+graph = [[0, 16, 13, 0, 0, 0],
+        [0, 0, 10, 12, 0, 0],
+        [0, 4, 0, 0, 14, 0],
+        [0, 0, 9, 0, 0, 20],
+        [0, 0, 0, 7, 0, 4],
+        [0, 0, 0, 0, 0, 0]]
 
 answer should be
 
@@ -25,48 +25,52 @@ import copy
 import math
 
 def maximum_flow_dfs(adjacency_matrix):
+    """
+    Get the maximum flow through a graph using a depth first search
+    """
+
     #initial setting
     new_array = copy.deepcopy(adjacency_matrix)
     total = 0
 
-    while(1):
+    while True:
         #setting min to max_value
         min = math.inf
         #save visited nodes
         visited = [0]*len(new_array)
         #save parent nodes
         path = [0]*len(new_array)
-        
+
         #initialize stack for DFS
         stack = []
 
-        #initial setting 
+        #initial setting
         visited[0] = 1
         stack.append(0)
 
         #DFS to find path
-        while(len(stack) > 0):
+        while len(stack) > 0:
             #pop from queue
             src = stack.pop()
             for k in range(len(new_array)):
                 #checking capacity and visit
-                if(new_array[src][k] > 0 and visited[k] == 0 ):
+                if new_array[src][k] > 0 and visited[k] == 0:
                     #if not, put into queue and chage to visit and save path
                     visited[k] = 1
                     stack.append(k)
                     path[k] = src
-            
+
         #if there is no path from src to sink
-        if(visited[len(new_array) - 1] == 0):
+        if visited[len(new_array) - 1] == 0:
             break
-        
+
         #initial setting
         tmp = len(new_array) - 1
 
         #Get minimum flow
-        while(tmp != 0):
+        while tmp != 0:
             #find minimum flow
-            if(min > new_array[path[tmp]][tmp]):
+            if min > new_array[path[tmp]][tmp]:
                 min = new_array[path[tmp]][tmp]
             tmp = path[tmp]
 
@@ -74,11 +78,11 @@ def maximum_flow_dfs(adjacency_matrix):
         tmp = len(new_array) - 1
 
         #reduce capacity
-        while(tmp != 0):
+        while tmp != 0:
             new_array[path[tmp]][tmp] = new_array[path[tmp]][tmp] - min
             tmp = path[tmp]
 
         total = total + min
-    
+
     return total
-    
\ No newline at end of file
+
diff --git a/algorithms/graph/minimum_spanning_tree.py b/algorithms/graph/minimum_spanning_tree.py
index dcc6898..d53a957 100644
--- a/algorithms/graph/minimum_spanning_tree.py
+++ b/algorithms/graph/minimum_spanning_tree.py
@@ -1,130 +1,151 @@
-# Minimum spanning tree (MST) is going to use an undirected graph
-#
-# The disjoint set is represented with an list <n> of integers where 
-# <n[i]> is the parent of the node at position <i>.
-# If <n[i]> = <i>, <i> it's a root, or a head, of a set
+"""
+Minimum spanning tree (MST) is going to use an undirected graph
+"""
 
+import sys
 
+# pylint: disable=too-few-public-methods
 class Edge:
-    def __init__(self, u, v, weight):
-        self.u = u
-        self.v = v
+    """
+    An edge of an undirected graph
+    """
+
+    def __init__(self, source, target, weight):
+        self.source = source
+        self.target = target
         self.weight = weight
 
 
 class DisjointSet:
-    def __init__(self, n):
-        # Args:
-        #   n (int): Number of vertices in the graph
-
-        self.parent = [None] * n # Contains wich node is the parent of the node at poisition <i>
-        self.size = [1] * n # Contains size of node at index <i>, used to optimize merge
-        for i in range(n):
+    """
+    The disjoint set is represented with an list <n> of integers where
+    <n[i]> is the parent of the node at position <i>.
+    If <n[i]> = <i>, <i> it's a root, or a head, of a set
+    """
+
+    def __init__(self, size):
+        """
+        Args:
+            n (int): Number of vertices in the graph
+        """
+
+        self.parent = [None] * size # Contains wich node is the parent of the node at poisition <i>
+        self.size = [1] * size # Contains size of node at index <i>, used to optimize merge
+        for i in range(size):
             self.parent[i] = i # Make all nodes his own parent, creating n sets.
 
-    def merge_set(self, a, b):
-        # Args:
-        #   a, b (int): Indexes of nodes whose sets will be merged.
+    def merge_set(self, node1, node2):
+        """
+        Args:
+            node1, node2 (int): Indexes of nodes whose sets will be merged.
+        """
 
         # Get the set of nodes at position <a> and <b>
         # If <a> and <b> are the roots, this will be constant O(1)
-        a = self.find_set(a)
-        b = self.find_set(b)
+        node1 = self.find_set(node1)
+        node2 = self.find_set(node2)
 
         # Join the shortest node to the longest, minimizing tree size (faster find)
-        if self.size[a] < self.size[b]:
-            self.parent[a] = b # Merge set(a) and set(b)
-            self.size[b] += self.size[a] # Add size of old set(a) to set(b)
+        if self.size[node1] < self.size[node2]:
+            self.parent[node1] = node2 # Merge set(a) and set(b)
+            self.size[node2] += self.size[node1] # Add size of old set(a) to set(b)
         else:
-            self.parent[b] = a # Merge set(b) and set(a)
-            self.size[a] += self.size[b] # Add size of old set(b) to set(a)
-
-    def find_set(self, a):
-        if self.parent[a] != a: 
-            # Very important, memoize result of the 
+            self.parent[node2] = node1 # Merge set(b) and set(a)
+            self.size[node1] += self.size[node2] # Add size of old set(b) to set(a)
+
+    def find_set(self, node):
+        """
+        Get the root element of the set containing <a>
+        """
+        if self.parent[node] != node:
+            # Very important, memoize result of the
             # recursion in the list to optimize next
             # calls and make this operation practically constant, O(1)
-            self.parent[a] = self.find_set(self.parent[a])
+            self.parent[node] = self.find_set(self.parent[node])
 
         # node <a> it's the set root, so we can return that index
-        return self.parent[a]
-
-
-def kruskal(n, edges, ds):
-    # Args:
-    #   n (int): Number of vertices in the graph
-    #   edges (list of Edge): Edges of the graph
-    #   ds (DisjointSet): DisjointSet of the vertices
-    # Returns:
-    #   int: sum of weights of the minnimum spanning tree 
-    #
-    # Kruskal algorithm:
-    #   This algorithm will find the optimal graph with less edges and less
-    #   total weight to connect all vertices (MST), the MST will always contain
-    #   n-1 edges because it's the minimum required to connect n vertices.
-    #
-    # Procedure:
-    #   Sort the edges (criteria: less weight).
-    #   Only take edges of nodes in different sets.
-    #   If we take a edge, we need to merge the sets to discard these.
-    #   After repeat this until select n-1 edges, we will have the complete MST.
+        return self.parent[node]
+
+
+def kruskal(vertex_count, edges, forest):
+    """
+    Args:
+        vertex_count (int): Number of vertices in the graph
+        edges (list of Edge): Edges of the graph
+        forest (DisjointSet): DisjointSet of the vertices
+    Returns:
+        int: sum of weights of the minnimum spanning tree
+
+    Kruskal algorithm:
+        This algorithm will find the optimal graph with less edges and less
+        total weight to connect all vertices (MST), the MST will always contain
+        n-1 edges because it's the minimum required to connect n vertices.
+
+    Procedure:
+        Sort the edges (criteria: less weight).
+        Only take edges of nodes in different sets.
+        If we take a edge, we need to merge the sets to discard these.
+        After repeat this until select n-1 edges, we will have the complete MST.
+    """
     edges.sort(key=lambda edge: edge.weight)
 
     mst = [] # List of edges taken, minimum spanning tree
 
     for edge in edges:
-        set_u = ds.find_set(edge.u) # Set of the node <u>
-        set_v = ds.find_set(edge.v) # Set of the node <v>
+        set_u = forest.find_set(edge.u) # Set of the node <u>
+        set_v = forest.find_set(edge.v) # Set of the node <v>
         if set_u != set_v:
-            ds.merge_set(set_u, set_v)
+            forest.merge_set(set_u, set_v)
             mst.append(edge)
-            if len(mst) == n-1: 
-                # If we have selected n-1 edges, all the other 
+            if len(mst) == vertex_count-1:
+                # If we have selected n-1 edges, all the other
                 # edges will be discarted, so, we can stop here
                 break
 
     return sum([edge.weight for edge in mst])
 
 
-
-
-if __name__ == "__main__":
-    # Test. How input works:
-    # Input consists of different weighted, connected, undirected graphs. 
-    # line 1: 
-    #   integers n, m
-    # lines 2..m+2:
-    #   edge with the format -> node index u, node index v, integer weight
-    #
-    # Samples of input:
-    #
-    # 5 6
-    # 1 2 3
-    # 1 3 8
-    # 2 4 5
-    # 3 4 2
-    # 3 5 4
-    # 4 5 6
-    # 
-    # 3 3
-    # 2 1 20
-    # 3 1 20
-    # 2 3 100
-    #
-    # Sum of weights of the optimal paths:
-    # 14, 40
-    import sys
-    for n_m in sys.stdin:
-        n, m = map(int, n_m.split())
-        ds = DisjointSet(m)
-        edges = [None] * m # Create list of size <m>
+def main():
+    """
+    Test. How input works:
+    Input consists of different weighted, connected, undirected graphs.
+    line 1:
+      integers n, m
+    lines 2..m+2:
+      edge with the format -> node index u, node index v, integer weight
+
+    Samples of input:
+
+    5 6
+    1 2 3
+    1 3 8
+    2 4 5
+    3 4 2
+    3 5 4
+    4 5 6
+
+    3 3
+    2 1 20
+    3 1 20
+    2 3 100
+
+    Sum of weights of the optimal paths:
+    14, 40
+    """
+    for size in sys.stdin:
+        vertex_count, edge_count = map(int, size.split())
+        forest = DisjointSet(edge_count)
+        edges = [None] * edge_count # Create list of size <m>
 
         # Read <m> edges from input
-        for i in range(m):
-            u, v, weight = map(int, input().split())
-            u -= 1 # Convert from 1-indexed to 0-indexed
-            v -= 1 # Convert from 1-indexed to 0-indexed
-            edges[i] = Edge(u, v, weight)
+        for i in range(edge_count):
+            source, target, weight = map(int, input().split())
+            source -= 1 # Convert from 1-indexed to 0-indexed
+            target -= 1 # Convert from 1-indexed to 0-indexed
+            edges[i] = Edge(source, target, weight)
 
         # After finish input and graph creation, use Kruskal algorithm for MST:
-        print("MST weights sum:", kruskal(n, edges, ds))
+        print("MST weights sum:", kruskal(vertex_count, edges, forest))
+
+if __name__ == "__main__":
+    main()
diff --git a/algorithms/graph/path_between_two_vertices_in_digraph.py b/algorithms/graph/path_between_two_vertices_in_digraph.py
index ee6ac41..4bf2902 100644
--- a/algorithms/graph/path_between_two_vertices_in_digraph.py
+++ b/algorithms/graph/path_between_two_vertices_in_digraph.py
@@ -1,51 +1,51 @@
+"""
+Determine if there is a path between nodes in a graph
+"""
+
 from collections import defaultdict
 
+
 class Graph:
-	def __init__(self,v):
-		self.v = v
-		self.graph = defaultdict(list)
-		self.has_path = False
-
-	def add_edge(self,u,v):
-		self.graph[u].append(v)
-
-	def dfs(self,x,y):
-		visited = [False] * self.v
-		self.dfsutil(visited,x,y,)
-
-	def dfsutil(self,visited,x,y):
-		visited[x] = True
-		for i in self.graph[x]:
-			if y in self.graph[x]:
-				self.has_path = True
-				return
-			if(not(visited[i])):
-				self.dfsutil(visited,x,i)
-
-	def is_reachable(self,x,y):
-		self.has_path = False
-		self.dfs(x,y)
-		return self.has_path
-
-
-# Create a graph given in the above diagram
-g = Graph(4)
-g.add_edge(0, 1)
-g.add_edge(0, 2)
-g.add_edge(1, 2)
-g.add_edge(2, 0)
-g.add_edge(2, 3)
-g.add_edge(3, 3)
- 
-u =1; v = 3
- 
-if g.is_reachable(u, v):
-    print("There is a path from %d to %d" % (u,v))
-else :
-    print("There is no path from %d to %d" % (u,v))
- 
-u = 3; v = 1
-if g.is_reachable(u, v) :
-    print("There is a path from %d to %d" % (u,v))
-else :
-    print("There is no path from %d to %d" % (u,v))
+    """
+    A directed graph
+    """
+
+    def __init__(self,vertex_count):
+        self.vertex_count = vertex_count
+        self.graph = defaultdict(list)
+        self.has_path = False
+
+    def add_edge(self,source,target):
+        """
+        Add a new directed edge to the graph
+        """
+        self.graph[source].append(target)
+
+    def dfs(self,source,target):
+        """
+        Determine if there is a path from source to target using a depth first search
+        """
+        visited = [False] * self.vertex_count
+        self.dfsutil(visited,source,target,)
+
+    def dfsutil(self,visited,source,target):
+        """
+        Determine if there is a path from source to target using a depth first search.
+        :param: visited should be an array of booleans determining if the
+        corresponding vertex has been visited already
+        """
+        visited[source] = True
+        for i in self.graph[source]:
+            if target in self.graph[source]:
+                self.has_path = True
+                return
+            if not visited[i]:
+                self.dfsutil(visited,source,i)
+
+    def is_reachable(self,source,target):
+        """
+        Determine if there is a path from source to target
+        """
+        self.has_path = False
+        self.dfs(source,target)
+        return self.has_path
diff --git a/algorithms/graph/prims_minimum_spanning.py b/algorithms/graph/prims_minimum_spanning.py
index 02295c4..af7cb43 100644
--- a/algorithms/graph/prims_minimum_spanning.py
+++ b/algorithms/graph/prims_minimum_spanning.py
@@ -1,15 +1,15 @@
 '''
 This Prim's Algorithm Code is for finding weight of minimum spanning tree
 of a connected graph.
-For argument graph, it should be a dictionary type
-such as
-graph = {
-    'a': [ [3, 'b'], [8,'c'] ],
-    'b': [ [3, 'a'], [5, 'd'] ],
-    'c': [ [8, 'a'], [2, 'd'], [4, 'e'] ],
-    'd': [ [5, 'b'], [2, 'c'], [6, 'e'] ],
-    'e': [ [4, 'c'], [6, 'd'] ]
-}
+For argument graph, it should be a dictionary type such as:
+
+    graph = {
+        'a': [ [3, 'b'], [8,'c'] ],
+        'b': [ [3, 'a'], [5, 'd'] ],
+        'c': [ [8, 'a'], [2, 'd'], [4, 'e'] ],
+        'd': [ [5, 'b'], [2, 'c'], [6, 'e'] ],
+        'e': [ [4, 'c'], [6, 'd'] ]
+    }
 
 where 'a','b','c','d','e' are nodes (these can be 1,2,3,4,5 as well)
 '''
@@ -17,26 +17,26 @@ where 'a','b','c','d','e' are nodes (these can be 1,2,3,4,5 as well)
 
 import heapq  # for priority queue
 
-# prim's algo. to find weight of minimum spanning tree
 def prims_minimum_spanning(graph_used):
+    """
+    Prim's algorithm to find weight of minimum spanning tree
+    """
     vis=[]
-    s=[[0,1]]
-    prim = []
+    heap=[[0,1]]
+    prim = set()
     mincost=0
-    
-    while(len(s)>0):
-        v=heapq.heappop(s)
-        x=v[1]
-        if(x in vis):
+
+    while len(heap) > 0:
+        cost, node = heapq.heappop(heap)
+        if node in vis:
             continue
 
-        mincost += v[0]
-        prim.append(x)
-        vis.append(x)
+        mincost += cost
+        prim.add(node)
+        vis.append(node)
 
-        for j in graph_used[x]:
-            i=j[-1]
-            if(i not in vis):
-                heapq.heappush(s,j)
+        for distance, adjacent in graph_used[node]:
+            if adjacent not in vis:
+                heapq.heappush(heap, [distance, adjacent])
 
     return mincost
diff --git a/algorithms/graph/satisfiability.py b/algorithms/graph/satisfiability.py
index bc1d189..0cae8ee 100644
--- a/algorithms/graph/satisfiability.py
+++ b/algorithms/graph/satisfiability.py
@@ -1,45 +1,49 @@
-'''
+"""
 Given a formula in conjunctive normal form (2-CNF), finds a way to assign
 True/False values to all variables to satisfy all clauses, or reports there
 is no solution.
 
 https://en.wikipedia.org/wiki/2-satisfiability
-'''
 
 
-''' Format:
+Format:
         - each clause is a pair of literals
         - each literal in the form (name, is_neg)
           where name is an arbitrary identifier,
           and is_neg is true if the literal is negated
-'''
-formula = [(('x', False), ('y', False)),
-           (('y', True), ('y', True)),
-           (('a', False), ('b', False)),
-           (('a', True), ('c', True)),
-           (('c', False), ('b', True))]
+"""
 
+def dfs_transposed(vertex, graph, order, visited):
+    """
+    Perform a depth first search traversal of the graph starting at the given vertex.
+    Stores the order in which nodes were visited to the list, in transposed order.
+    """
+    visited[vertex] = True
 
-def dfs_transposed(v, graph, order, vis):
-    vis[v] = True
+    for adjacent in graph[vertex]:
+        if not visited[adjacent]:
+            dfs_transposed(adjacent, graph, order, visited)
 
-    for u in graph[v]:
-        if not vis[u]:
-            dfs_transposed(u, graph, order, vis)
+    order.append(vertex)
 
-    order.append(v)
 
+def dfs(vertex, current_comp, vertex_scc, graph, visited):
+    """
+    Perform a depth first search traversal of the graph starting at the given vertex.
+    Records all visited nodes as being of a certain strongly connected component.
+    """
+    visited[vertex] = True
+    vertex_scc[vertex] = current_comp
 
-def dfs(v, current_comp, vertex_scc, graph, vis):
-    vis[v] = True
-    vertex_scc[v] = current_comp
-
-    for u in graph[v]:
-        if not vis[u]:
-            dfs(u, current_comp, vertex_scc, graph, vis)
+    for adjacent in graph[vertex]:
+        if not visited[adjacent]:
+            dfs(adjacent, current_comp, vertex_scc, graph, visited)
 
 
 def add_edge(graph, vertex_from, vertex_to):
+    """
+    Add a directed edge to the graph.
+    """
     if vertex_from not in graph:
         graph[vertex_from] = []
 
@@ -49,26 +53,26 @@ def add_edge(graph, vertex_from, vertex_to):
 def scc(graph):
     ''' Computes the strongly connected components of a graph '''
     order = []
-    vis = {vertex: False for vertex in graph}
+    visited = {vertex: False for vertex in graph}
 
     graph_transposed = {vertex: [] for vertex in graph}
 
-    for (v, neighbours) in graph.iteritems():
-        for u in neighbours:
-            add_edge(graph_transposed, u, v)
+    for (source, neighbours) in graph.iteritems():
+        for target in neighbours:
+            add_edge(graph_transposed, target, source)
 
-    for v in graph:
-        if not vis[v]:
-            dfs_transposed(v, graph_transposed, order, vis)
+    for vertex in graph:
+        if not visited[vertex]:
+            dfs_transposed(vertex, graph_transposed, order, visited)
 
-    vis = {vertex: False for vertex in graph}
+    visited = {vertex: False for vertex in graph}
     vertex_scc = {}
 
     current_comp = 0
-    for v in reversed(order):
-        if not vis[v]:
+    for vertex in reversed(order):
+        if not visited[vertex]:
             # Each dfs will visit exactly one component
-            dfs(v, current_comp, vertex_scc, graph, vis)
+            dfs(vertex, current_comp, vertex_scc, graph, visited)
             current_comp += 1
 
     return vertex_scc
@@ -91,6 +95,9 @@ def build_graph(formula):
 
 
 def solve_sat(formula):
+    """
+    Solves the 2-SAT problem
+    """
     graph = build_graph(formula)
     vertex_scc = scc(graph)
 
@@ -119,8 +126,20 @@ def solve_sat(formula):
     return value
 
 
-if __name__ == '__main__':
+def main():
+    """
+    Entry point for testing
+    """
+    formula = [(('x', False), ('y', False)),
+               (('y', True), ('y', True)),
+               (('a', False), ('b', False)),
+               (('a', True), ('c', True)),
+               (('c', False), ('b', True))]
+
     result = solve_sat(formula)
 
-    for (variable, assign) in result.iteritems():
-        print("{}:{}".format(variable, assign))
+    for (variable, assign) in result.items():
+        print(f"{variable}:{assign}")
+
+if __name__ == '__main__':
+    main()
diff --git a/algorithms/graph/tarjan.py b/algorithms/graph/tarjan.py
index 399a39d..ebc6932 100644
--- a/algorithms/graph/tarjan.py
+++ b/algorithms/graph/tarjan.py
@@ -6,7 +6,11 @@ https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
 from algorithms.graph.graph import DirectedGraph
 
 
-class Tarjan(object):
+# pylint: disable=too-few-public-methods
+class Tarjan:
+    """
+    A directed graph used for finding strongly connected components
+    """
     def __init__(self, dict_graph):
         self.graph = DirectedGraph(dict_graph)
         self.index = 0
@@ -14,44 +18,48 @@ class Tarjan(object):
 
         # Runs Tarjan
         # Set all node index to None
-        for v in self.graph.nodes:
-            v.index = None
+        for vertex in self.graph.nodes:
+            vertex.index = None
 
         self.sccs = []
-        for v in self.graph.nodes:
-            if v.index is None:
-                self.strongconnect(v, self.sccs)
+        for vertex in self.graph.nodes:
+            if vertex.index is None:
+                self.strongconnect(vertex, self.sccs)
 
-    def strongconnect(self, v, sccs):
+    def strongconnect(self, vertex, sccs):
+        """
+        Given a vertex, adds all successors of the given vertex to the same connected component
+        """
         # Set the depth index for v to the smallest unused index
-        v.index = self.index
-        v.lowlink = self.index
+        vertex.index = self.index
+        vertex.lowlink = self.index
         self.index += 1
-        self.stack.append(v)
-        v.on_stack = True
+        self.stack.append(vertex)
+        vertex.on_stack = True
 
         # Consider successors of v
-        for w in self.graph.adjmt[v]:
-            if w.index is None:
+        for adjacent in self.graph.adjacency_list[vertex]:
+            if adjacent.index is None:
                 # Successor w has not yet been visited; recurse on it
-                self.strongconnect(w, sccs)
-                v.lowlink = min(v.lowlink, w.lowlink)
-            elif w.on_stack:
+                self.strongconnect(adjacent, sccs)
+                vertex.lowlink = min(vertex.lowlink, adjacent.lowlink)
+            elif adjacent.on_stack:
                 # Successor w is in stack S and hence in the current SCC
-                # If w is not on stack, then (v, w) is a cross-edge in the DFS tree and must be ignored
+                # If w is not on stack, then (v, w) is a cross-edge in the DFS
+                # tree and must be ignored
                 # Note: The next line may look odd - but is correct.
                 # It says w.index not w.lowlink; that is deliberate and from the original paper
-                v.lowlink = min(v.lowlink, w.index)
+                vertex.lowlink = min(vertex.lowlink, adjacent.index)
 
         # If v is a root node, pop the stack and generate an SCC
-        if v.lowlink == v.index:
+        if vertex.lowlink == vertex.index:
             # start a new strongly connected component
             scc = []
             while True:
-                w = self.stack.pop()
-                w.on_stack = False
-                scc.append(w)
-                if w == v:
+                adjacent = self.stack.pop()
+                adjacent.on_stack = False
+                scc.append(adjacent)
+                if adjacent == vertex:
                     break
             scc.sort()
             sccs.append(scc)
diff --git a/algorithms/graph/transitive_closure_dfs.py b/algorithms/graph/transitive_closure_dfs.py
index 655c75c..ca7e43a 100644
--- a/algorithms/graph/transitive_closure_dfs.py
+++ b/algorithms/graph/transitive_closure_dfs.py
@@ -1,52 +1,55 @@
-# This class represents a directed graph using adjacency
+"""
+Finds the transitive closure of a graph.
+
+reference: https://en.wikipedia.org/wiki/Transitive_closure#In_graph_theory
+"""
+
 class Graph:
+    """
+    This class represents a directed graph using adjacency lists
+    """
     def __init__(self, vertices):
         # No. of vertices
-        self.V = vertices
+        self.vertex_count = vertices
 
         # default dictionary to store graph
         self.graph = {}
 
         # To store transitive closure
-        self.tc = [[0 for j in range(self.V)] for i in range(self.V)]
-
-    # function to add an edge to graph
-    def add_edge(self, u, v):
-        if u in self.graph:
-            self.graph[u].append(v)
+        self.closure = [[0 for j in range(vertices)] for i in range(vertices)]
+
+    def add_edge(self, source, target):
+        """
+        Adds a directed edge to the graph
+        """
+        if source in self.graph:
+            self.graph[source].append(target)
         else:
-            self.graph[u] = [v]
+            self.graph[source] = [target]
 
-    # A recursive DFS traversal function that finds
-    # all reachable vertices for s
-    def dfs_util(self, s, v):
+    def dfs_util(self, source, target):
+        """
+        A recursive DFS traversal function that finds
+        all reachable vertices for source
+        """
 
-        # Mark reachability from s to v as true.
-        self.tc[s][v] = 1
+        # Mark reachability from source to target as true.
+        self.closure[source][target] = 1
 
-        # Find all the vertices reachable through v
-        for i in self.graph[v]:
-            if self.tc[s][i] == 0:
-                self.dfs_util(s, i)
+        # Find all the vertices reachable through target
+        for adjacent in self.graph[target]:
+            if self.closure[source][adjacent] == 0:
+                self.dfs_util(source, adjacent)
 
-    # The function to find transitive closure. It uses
-    # recursive dfs_util()
     def transitive_closure(self):
+        """
+        The function to find transitive closure. It uses
+        recursive dfs_util()
+        """
 
         # Call the recursive helper function to print DFS
         # traversal starting from all vertices one by one
-        for i in range(self.V):
+        for i in range(self.vertex_count):
             self.dfs_util(i, i)
-        print(self.tc)
-
-
-# g = Graph(4)
-# g.add_edge(0, 1)
-# g.add_edge(0, 2)
-# g.add_edge(1, 2)
-# g.add_edge(2, 0)
-# g.add_edge(2, 3)
-# g.add_edge(3, 3)
 
-# print("Transitive closure matrix is")
-# g.transitive_closure()
+        return self.closure
diff --git a/algorithms/graph/traversal.py b/algorithms/graph/traversal.py
index cbfc65f..19ae141 100644
--- a/algorithms/graph/traversal.py
+++ b/algorithms/graph/traversal.py
@@ -1,9 +1,6 @@
-graph = {'A': set(['B', 'C', 'F']),
-         'B': set(['A', 'D', 'E']),
-         'C': set(['A', 'F']),
-         'D': set(['B']),
-         'E': set(['B', 'F']),
-         'F': set(['A', 'C', 'E'])}
+"""
+Different ways to traverse a graph
+"""
 
 # dfs and bfs are the ultimately same except that they are visiting nodes in
 # different order. To simulate this ordering we would use stack for dfs and
@@ -11,56 +8,41 @@ graph = {'A': set(['B', 'C', 'F']),
 #
 
 def dfs_traverse(graph, start):
+    """
+    Traversal by depth first search.
+    """
     visited, stack = set(), [start]
     while stack:
         node = stack.pop()
         if node not in visited:
             visited.add(node)
-            for nextNode in graph[node]:
-                if nextNode not in visited:
-                    stack.append(nextNode)
+            for next_node in graph[node]:
+                if next_node not in visited:
+                    stack.append(next_node)
     return visited
 
-# print(dfs_traverse(graph, 'A'))
-
-
 def bfs_traverse(graph, start):
+    """
+    Traversal by breadth first search.
+    """
     visited, queue = set(), [start]
     while queue:
         node = queue.pop(0)
         if node not in visited:
             visited.add(node)
-            for nextNode in graph[node]:
-                if nextNode not in visited:
-                    queue.append(nextNode)
+            for next_node in graph[node]:
+                if next_node not in visited:
+                    queue.append(next_node)
     return visited
 
-# print(bfs_traverse(graph, 'A'))
-
 def dfs_traverse_recursive(graph, start, visited=None):
+    """
+    Traversal by recursive depth first search.
+    """
     if visited is None:
         visited = set()
     visited.add(start)
-    for nextNode in graph[start]:
-        if nextNode not in visited:
-            dfs_traverse_recursive(graph, nextNode, visited)
+    for next_node in graph[start]:
+        if next_node not in visited:
+            dfs_traverse_recursive(graph, next_node, visited)
     return visited
-
-# print(dfs_traverse_recursive(graph, 'A'))
-
-# def find_path(graph, start, end, visited=[]):
-    # # basecase
-    # visitied = visited + [start]
-    # if start == end:
-        # return visited
-    # if start not in graph:
-        # return None
-    # for node in graph[start]:
-        # if node not in visited:
-            # new_visited = find_path(graph, node, end, visited)
-            # return new_visited
-    # return None
-
-# print(find_path(graph, 'A', 'F'))
-
-
diff --git a/algorithms/greedy/__init__.py b/algorithms/greedy/__init__.py
new file mode 100644
index 0000000..6618478
--- /dev/null
+++ b/algorithms/greedy/__init__.py
@@ -0,0 +1,1 @@
+from .max_contiguous_subsequence_sum import *
diff --git a/algorithms/greedy/max_contiguous_subsequence_sum.py b/algorithms/greedy/max_contiguous_subsequence_sum.py
new file mode 100644
index 0000000..c5eae3d
--- /dev/null
+++ b/algorithms/greedy/max_contiguous_subsequence_sum.py
@@ -0,0 +1,42 @@
+'''
+Algorithm used => Kadane's Algorithm
+
+kadane's algorithm is used for finding the maximum sum of contiguous subsequence in a sequence.
+It is considered a greedy/dp algorithm but I think they more greedy than dp
+here are some of the examples to understand the use case more clearly
+Example1 => [-2, 3, 8, -1, 4]
+result =>  {3, 8, -1, 4} => 14
+Example2 => [-1, 1, 0]
+result => {1} => 1
+Example3 => [-1, -3, -4]
+result => -1
+Example1 => [-2, 3, 8, -12, 8, 4]
+result =>  {8, 4} => 12
+Basic Algorithm Idea
+    If the sum of the current contiguous subsequence after adding the value at the current position is less than the value
+    at the current position then we know that it will be better if we start the current contiguous subsequence from this position.
+    Else we add the value at the current position to the current contiguous subsequence.
+Note
+    In the implementation, the contiguous subsequence has at least one element.
+    If it can have 0 elements then the result will be max(max_till_now, 0)
+'''
+
+
+def max_contiguous_subsequence_sum(arr) -> int:
+    arr_size = len(arr)
+
+    if arr_size == 0:
+        return 0
+
+    max_till_now = arr[0]
+    curr_sub_sum = 0
+
+    for i in range(0, arr_size):
+        if curr_sub_sum + arr[i] < arr[i]:
+            curr_sub_sum = arr[i]
+        else:
+            curr_sub_sum += arr[i]
+
+        max_till_now = max(max_till_now, curr_sub_sum)
+
+    return max_till_now
diff --git a/algorithms/heap/binary_heap.py b/algorithms/heap/binary_heap.py
index ac7ff63..776e315 100644
--- a/algorithms/heap/binary_heap.py
+++ b/algorithms/heap/binary_heap.py
@@ -1,4 +1,4 @@
-"""
+r"""
 Binary Heap. A min heap is a complete binary tree where each node is smaller than
 its children. The root, therefore, is the minimum element in the tree. The min
 heap uses an array to represent the data and operation. For example a min heap:
@@ -31,28 +31,39 @@ For example remove_min() in a min heap:
 """
 from abc import ABCMeta, abstractmethod
 
+
 class AbstractHeap(metaclass=ABCMeta):
     """Abstract Class for Binary Heap."""
+
     def __init__(self):
-        pass
+        """Pass."""
+
     @abstractmethod
     def perc_up(self, i):
-        pass
+        """Pass."""
+
     @abstractmethod
     def insert(self, val):
-        pass
+        """Pass."""
+
     @abstractmethod
-    def perc_down(self,i):
-        pass
+    def perc_down(self, i):
+        """Pass."""
+
     @abstractmethod
-    def min_child(self,i):
-        pass
+    def min_child(self, i):
+        """Pass."""
+
     @abstractmethod
     def remove_min(self):
-        pass
+        """Pass."""
+
+
 class BinaryHeap(AbstractHeap):
+    """Binary Heap Class"""
+
     def __init__(self):
-        self.currentSize = 0
+        self.current_size = 0
         self.heap = [(0)]
 
     def perc_up(self, i):
@@ -62,34 +73,32 @@ class BinaryHeap(AbstractHeap):
                 self.heap[i], self.heap[i//2] = self.heap[i//2], self.heap[i]
             i = i // 2
 
-    """
+    def insert(self, val):
+        """
         Method insert always start by inserting the element at the bottom.
         It inserts rightmost spot so as to maintain the complete tree property.
         Then, it fixes the tree by swapping the new element with its parent,
         until it finds an appropriate spot for the element. It essentially
         perc_up the minimum element
         Complexity: O(logN)
-    """
-    def insert(self, val):
+        """
         self.heap.append(val)
-        self.currentSize = self.currentSize + 1
-        self.perc_up(self.currentSize)
+        self.current_size = self.current_size + 1
+        self.perc_up(self.current_size)
 
-    """
+        """
         Method min_child returns the index of smaller of 2 children of parent at index i
-    """
+        """
+
     def min_child(self, i):
-        if 2 * i + 1 > self.currentSize:  # No right child
+        if 2 * i + 1 > self.current_size:  # No right child
             return 2 * i
-        else:
-            # left child > right child
-            if self.heap[2 * i] > self.heap[2 * i +1]:
-                return 2 * i + 1
-            else:
-                return 2 * i
+        if self.heap[2 * i] > self.heap[2 * i + 1]:
+            return 2 * i + 1
+        return 2 * i
 
     def perc_down(self, i):
-        while 2 * i < self.currentSize:
+        while 2 * i < self.current_size:
             min_child = self.min_child(i)
             if self.heap[min_child] < self.heap[i]:
                 # Swap min child with parent
@@ -102,10 +111,12 @@ class BinaryHeap(AbstractHeap):
         min heap property is restored
         Complexity: O(logN)
     """
+
     def remove_min(self):
         ret = self.heap[1]      # the smallest value at beginning
-        self.heap[1] = self.heap[self.currentSize] # Replace it by the last value
-        self.currentSize = self.currentSize - 1
+        # Replace it by the last value
+        self.heap[1] = self.heap[self.current_size]
+        self.current_size = self.current_size - 1
         self.heap.pop()
         self.perc_down(1)
         return ret
diff --git a/algorithms/heap/k_closest_points.py b/algorithms/heap/k_closest_points.py
index 8e38e05..6a4e036 100644
--- a/algorithms/heap/k_closest_points.py
+++ b/algorithms/heap/k_closest_points.py
@@ -2,8 +2,10 @@
 
 Idea: Maintain a max heap of k elements.
 We can iterate through all points.
-If a point p has a smaller distance to the origin than the top element of a heap, we add point p to the heap and remove the top element.
-After iterating through all points, our heap contains the k closest points to the origin.
+If a point p has a smaller distance to the origin than the top element of a
+heap, we add point p to the heap and remove the top element.
+After iterating through all points, our heap contains the k closest points to
+the origin.
 """
 
 
@@ -14,7 +16,8 @@ def k_closest(points, k, origin=(0, 0)):
     # Time: O(k+(n-k)logk)
     # Space: O(k)
     """Initialize max heap with first k points.
-    Python does not support a max heap; thus we can use the default min heap where the keys (distance) are negated.
+    Python does not support a max heap; thus we can use the default min heap
+    where the keys (distance) are negated.
     """
     heap = [(-distance(p, origin), p) for p in points[:k]]
     heapify(heap)
@@ -24,10 +27,10 @@ def k_closest(points, k, origin=(0, 0)):
     check if p is smaller than the root of the max heap;
     if it is, add p to heap and remove root. Reheapify.
     """
-    for p in points[k:]:
-        d = distance(p, origin)
+    for point in points[k:]:
+        dist = distance(point, origin)
 
-        heappushpop(heap, (-d, p))  # heappushpop does conditional check
+        heappushpop(heap, (-dist, point))  # heappushpop does conditional check
         """Same as:
             if d < -heap[0][0]:
                 heappush(heap, (-d,p))
@@ -37,8 +40,9 @@ def k_closest(points, k, origin=(0, 0)):
         Each heappushpop call takes O(logk) time.
         """
 
-    return [p for nd, p in heap]  # return points in heap
+    return [point for nd, point in heap]  # return points in heap
 
 
 def distance(point, origin=(0, 0)):
+    """ Calculates the distance for a point from origo"""
     return (point[0] - origin[0])**2 + (point[1] - origin[1])**2
diff --git a/algorithms/heap/merge_sorted_k_lists.py b/algorithms/heap/merge_sorted_k_lists.py
index 2fbfe1d..f3600c4 100644
--- a/algorithms/heap/merge_sorted_k_lists.py
+++ b/algorithms/heap/merge_sorted_k_lists.py
@@ -9,28 +9,32 @@ from queue import PriorityQueue
 
 # Definition for singly-linked list.
 class ListNode(object):
-    def __init__(self, x):
-        self.val = x
+    """ ListNode Class"""
+
+    def __init__(self, val):
+        self.val = val
         self.next = None
 
 
 def merge_k_lists(lists):
+    """ Merge Lists """
     dummy = node = ListNode(0)
-    h = [(n.val, n) for n in lists if n]
-    heapify(h)
-    while h:
-        v, n = h[0]
-        if n.next is None:
-            heappop(h)  # only change heap size when necessary
+    list_h = [(n.val, n) for n in lists if n]
+    heapify(list_h)
+    while list_h:
+        _, n_val = list_h[0]
+        if n_val.next is None:
+            heappop(list_h)  # only change heap size when necessary
         else:
-            heapreplace(h, (n.next.val, n.next))
-        node.next = n
+            heapreplace(list_h, (n_val.next.val, n_val.next))
+        node.next = n_val
         node = node.next
 
     return dummy.next
 
 
 def merge_k_lists(lists):
+    """ Merge List """
     dummy = ListNode(None)
     curr = dummy
     q = PriorityQueue()
diff --git a/algorithms/maths/__init__.py b/algorithms/maths/__init__.py
index ab58af9..8a3a9e6 100644
--- a/algorithms/maths/__init__.py
+++ b/algorithms/maths/__init__.py
@@ -1,3 +1,6 @@
+"""
+Collection of mathematical algorithms and functions.
+"""
 from .base_conversion import *
 from .decimal_to_binary_ip import *
 from .euler_totient import *
@@ -22,4 +25,3 @@ from .num_digits import *
 from .power import *
 from .magic_number import *
 from .krishnamurthy_number import *
-
diff --git a/algorithms/maths/base_conversion.py b/algorithms/maths/base_conversion.py
index 5d2a221..6badf74 100644
--- a/algorithms/maths/base_conversion.py
+++ b/algorithms/maths/base_conversion.py
@@ -1,50 +1,49 @@
 """
 Integer base conversion algorithm
 
-int2base(5, 2) return '101'.
-base2int('F', 16) return 15.
+int_to_base(5, 2) return '101'.
+base_to_int('F', 16) return 15.
 
 """
 
 import string
 
-def int_to_base(n, base):
+def int_to_base(num, base):
     """
-        :type n: int
+        :type num: int
         :type base: int
         :rtype: str
     """
     is_negative = False
-    if n == 0:
+    if num == 0:
         return '0'
-    elif n < 0:
+    if num < 0:
         is_negative = True
-        n *= -1
+        num *= -1
     digit = string.digits + string.ascii_uppercase
     res = ''
-    while n > 0:
-        res += digit[n % base]
-        n //= base
+    while num > 0:
+        res += digit[num % base]
+        num //= base
     if is_negative:
         return '-' + res[::-1]
-    else:
-        return res[::-1]
+    return res[::-1]
 
 
-def base_to_int(s, base):
+def base_to_int(str_to_convert, base):
     """
         Note : You can use int() built-in function instead of this.
-        :type s: str
+        :type str_to_convert: str
         :type base: int
         :rtype: int
     """
-    
+
     digit = {}
-    for i,c in enumerate(string.digits + string.ascii_uppercase):
-        digit[c] = i
+    for ind, char in enumerate(string.digits + string.ascii_uppercase):
+        digit[char] = ind
     multiplier = 1
     res = 0
-    for c in s[::-1]:
-        res += digit[c] * multiplier
+    for char in str_to_convert[::-1]:
+        res += digit[char] * multiplier
         multiplier *= base
     return res
diff --git a/algorithms/maths/chinese_remainder_theorem.py b/algorithms/maths/chinese_remainder_theorem.py
index 91d9d1d..256e60f 100644
--- a/algorithms/maths/chinese_remainder_theorem.py
+++ b/algorithms/maths/chinese_remainder_theorem.py
@@ -1,46 +1,46 @@
-from algorithms.maths.gcd import gcd
+"""
+Solves system of equations using the chinese remainder theorem if possible.
+"""
 from typing import List
+from algorithms.maths.gcd import gcd
 
-def solve_chinese_remainder(num : List[int], rem : List[int]):
+def solve_chinese_remainder(nums : List[int], rems : List[int]):
     """
     Computes the smallest x that satisfies the chinese remainder theorem
     for a system of equations.
     The system of equations has the form:
-    x % num[0] = rem[0]
-    x % num[1] = rem[1]
+    x % nums[0] = rems[0]
+    x % nums[1] = rems[1]
     ...
-    x % num[k - 1] = rem[k - 1]
-    Where k is the number of elements in num and rem, k > 0.
-    All numbers in num needs to be pariwise coprime otherwise an exception is raised
+    x % nums[k - 1] = rems[k - 1]
+    Where k is the number of elements in nums and rems, k > 0.
+    All numbers in nums needs to be pariwise coprime otherwise an exception is raised
     returns x: the smallest value for x that satisfies the system of equations
     """
-    if not len(num) == len(rem):
-        raise Exception("num and rem should have equal length")
-    if not len(num) > 0:
-        raise Exception("Lists num and rem need to contain at least one element")
-    for n in num:
-        if not n > 1:
-            raise Exception("All numbers in num needs to be > 1")
-    if not _check_coprime(num):
-        raise Exception("All pairs of numbers in num are not coprime")
-    k = len(num)
+    if not len(nums) == len(rems):
+        raise Exception("nums and rems should have equal length")
+    if not len(nums) > 0:
+        raise Exception("Lists nums and rems need to contain at least one element")
+    for num in nums:
+        if not num > 1:
+            raise Exception("All numbers in nums needs to be > 1")
+    if not _check_coprime(nums):
+        raise Exception("All pairs of numbers in nums are not coprime")
+    k = len(nums)
     x = 1
     while True:
         i = 0
         while i < k:
-            if x % num[i] != rem[i]:
+            if x % nums[i] != rems[i]:
                 break
             i += 1
         if i == k:
             return x
-        else:
-            x += 1
+        x += 1
 
-def _check_coprime(l : List[int]):
-    for i in range(len(l)):
-        for j in range(len(l)):
-            if i == j:
-                continue
-            if gcd(l[i], l[j]) != 1:
+def _check_coprime(list_to_check : List[int]):
+    for ind, num in enumerate(list_to_check):
+        for num2 in list_to_check[ind + 1:]:
+            if gcd(num, num2) != 1:
                 return False
     return True
diff --git a/algorithms/maths/combination.py b/algorithms/maths/combination.py
index 308b0bc..9985360 100644
--- a/algorithms/maths/combination.py
+++ b/algorithms/maths/combination.py
@@ -1,9 +1,11 @@
+"""
+Functions to calculate nCr (ie how many ways to choose r items from n items)
+"""
 def combination(n, r):
     """This function calculates nCr."""
     if n == r or r == 0:
         return 1
-    else:
-        return combination(n-1, r-1) + combination(n-1, r)
+    return combination(n-1, r-1) + combination(n-1, r)
 
 def combination_memo(n, r):
     """This function calculates nCr using memoization method."""
diff --git a/algorithms/maths/cosine_similarity.py b/algorithms/maths/cosine_similarity.py
index 831e344..3ee7fcd 100644
--- a/algorithms/maths/cosine_similarity.py
+++ b/algorithms/maths/cosine_similarity.py
@@ -13,29 +13,30 @@ def _l2_distance(vec):
     Calculate l2 distance from two given vectors.
     """
     norm = 0.
-    for e in vec:
-        norm += e * e
+    for element in vec:
+        norm += element * element
     norm = math.sqrt(norm)
     return norm
 
 
-def cosine_similarity(a, b):
+def cosine_similarity(vec1, vec2):
     """
     Calculate cosine similarity between given two vectors
-    :type a: list
-    :type b: list
+    :type vec1: list
+    :type vec2: list
     """
-    if len(a) != len(b):
-        raise ValueError("The two vectors must be the same length. Got shape " + str(len(a)) + " and " + str(len(b)))
+    if len(vec1) != len(vec2):
+        raise ValueError("The two vectors must be the same length. Got shape " + str(len(vec1))
+                        + " and " + str(len(vec2)))
 
-    norm_a = _l2_distance(a)
-    norm_b = _l2_distance(b)
+    norm_a = _l2_distance(vec1)
+    norm_b = _l2_distance(vec2)
 
     similarity = 0.
 
     # Calculate the dot product of two vectors
-    for ae, be in zip(a, b):
-        similarity += ae * be
+    for vec1_element, vec2_element in zip(vec1, vec2):
+        similarity += vec1_element * vec2_element
 
     similarity /= (norm_a * norm_b)
 
diff --git a/algorithms/maths/decimal_to_binary_ip.py b/algorithms/maths/decimal_to_binary_ip.py
index 579e340..04e65e8 100644
--- a/algorithms/maths/decimal_to_binary_ip.py
+++ b/algorithms/maths/decimal_to_binary_ip.py
@@ -7,6 +7,11 @@ returns string
 """
 
 def decimal_to_binary_util(val):
+    """
+    Convert 8-bit decimal number to binary representation
+    :type val: str
+    :rtype: str
+    """
     bits = [128, 64, 32, 16, 8, 4, 2, 1]
     val = int(val)
     binary_rep = ''
@@ -20,6 +25,9 @@ def decimal_to_binary_util(val):
     return binary_rep
 
 def decimal_to_binary_ip(ip):
+    """
+    Convert dotted-decimal ip address to binary representation with help of decimal_to_binary_util
+    """
     values = ip.split('.')
     binary_list = []
     for val in values:
diff --git a/algorithms/maths/diffie_hellman_key_exchange.py b/algorithms/maths/diffie_hellman_key_exchange.py
index 5fed8ef..0d8b751 100644
--- a/algorithms/maths/diffie_hellman_key_exchange.py
+++ b/algorithms/maths/diffie_hellman_key_exchange.py
@@ -1,24 +1,28 @@
+"""
+Algorithms for performing diffie-hellman key exchange.
+"""
 import math
 from random import randint
 
+
 """
 Code from /algorithms/maths/prime_check.py,
 written by 'goswami-rahul' and 'Hai Honag Dang'
 """
-def prime_check(n):
-    """Return True if n is a prime number
+def prime_check(num):
+    """Return True if num is a prime number
     Else return False.
     """
 
-    if n <= 1:
+    if num <= 1:
         return False
-    if n == 2 or n == 3:
+    if num == 2 or num == 3:
         return True
-    if n % 2 == 0 or n % 3 == 0:
+    if num % 2 == 0 or num % 3 == 0:
         return False
     j = 5
-    while j * j <= n:
-        if n % j == 0 or n % (j + 2) == 0:
+    while j * j <= num:
+        if num % j == 0 or num % (j + 2) == 0:
             return False
         j += 6
     return True
@@ -28,22 +32,20 @@ def prime_check(n):
 For positive integer n and given integer a that satisfies gcd(a, n) = 1,
 the order of a modulo n is the smallest positive integer k that satisfies
 pow (a, k) % n = 1. In other words, (a^k) ≡ 1 (mod n).
-Order of certain number may or may not be exist. If so, return -1.
+Order of certain number may or may not exist. If not, return -1.
 """
 def find_order(a, n):
-    if ((a == 1) & (n == 1)):
+    if (a == 1) & (n == 1):
+        # Exception Handeling : 1 is the order of of 1
         return 1
-        """ Exception Handeling :
-        1 is the order of of 1 """
-    else:
-        if (math.gcd(a, n) != 1):
-            print ("a and n should be relative prime!")
-            return -1
-        else:
-            for i in range(1, n):
-                if (pow(a, i) % n == 1):
-                    return i
-            return -1
+    if math.gcd(a, n) != 1:
+        print ("a and n should be relative prime!")
+        return -1
+    for i in range(1, n):
+        if pow(a, i) % n == 1:
+            return i
+    return -1
+
 
 """
 Euler's totient function, also known as phi-function ϕ(n),
@@ -55,15 +57,15 @@ Code from /algorithms/maths/euler_totient.py, written by 'goswami-rahul'
 def euler_totient(n):
     """Euler's totient function or Phi function.
     Time Complexity: O(sqrt(n))."""
-    result = n;
+    result = n
     for i in range(2, int(n ** 0.5) + 1):
         if n % i == 0:
             while n % i == 0:
                 n //= i
             result -= result // i
     if n > 1:
-        result -= result // n;
-    return result;
+        result -= result // n
+    return result
 
 """
 For positive integer n and given integer a that satisfies gcd(a, n) = 1,
@@ -73,26 +75,20 @@ If so, return empty list.
 """
 
 def find_primitive_root(n):
-    if (n == 1):
+    """ Returns all primitive roots of n. """
+    if n == 1:
+        # Exception Handeling : 0 is the only primitive root of 1
         return [0]
-        """ Exception Handeling :
-        0 is the only primitive root of 1 """
-    else:
-        phi = euler_totient(n)
-        p_root_list = []
-        """ It will return every primitive roots of n. """
-        for i in range (1, n):
-            if (math.gcd(i, n) != 1):
-                continue
-                """ To have order, a and n must be
-                relative prime with each other. """
-            else:
-                order = find_order(i, n)
-                if (order == phi):
-                    p_root_list.append(i)
-                else:
-                    continue
-        return p_root_list
+    phi = euler_totient(n)
+    p_root_list = []
+    for i in range (1, n):
+        if math.gcd(i, n) != 1:
+            # To have order, a and n must be relative prime with each other.
+            continue
+        order = find_order(i, n)
+        if order == phi:
+            p_root_list.append(i)
+    return p_root_list
 
 
 """
@@ -103,7 +99,8 @@ This method use the property of one-way function (discrete logarithm)
 For example, given a, b and n, it is easy to calculate x
 that satisfies (a^b) ≡ x (mod n).
 However, it is very hard to calculate x that satisfies (a^x) ≡ b (mod n).
-For using this method, large prime number p and its primitive root a must be given.
+For using this method, large prime number p and its primitive root a
+must be given.
 """
 
 def alice_private_key(p):
@@ -132,7 +129,7 @@ def bob_public_key(b_pr_k, a, p):
     with his private key.
     This is open to public"""
     return pow(a, b_pr_k) % p
-    
+
 
 def alice_shared_key(b_pu_k, a_pr_k, p):
     """ Alice calculate secret key shared with Bob,
@@ -149,42 +146,39 @@ def bob_shared_key(a_pu_k, b_pr_k, p):
 
 
 def diffie_hellman_key_exchange(a, p, option = None):
-    if (option != None):
+    """ Perform diffie-helmman key exchange. """
+    if option is not None:
+        # Print explanation of process when option parameter is given
         option = 1
-        """ Print explanation of process
-        when option parameter is given """
-    if (prime_check(p) == False):
-        print("%d is not a prime number" % p)
+    if prime_check(p) is False:
+        print(f"{p} is not a prime number")
+        # p must be large prime number
         return False
-        """p must be large prime number"""
-    else:
-        try:
-            p_root_list = find_primitive_root(p)
-            p_root_list.index(a)
-        except ValueError:
-            print("%d is not a primitive root of %d" % (a, p))
-            return False
-            """ a must be primitive root of p """
-        
-        a_pr_k = alice_private_key(p)
-        a_pu_k = alice_public_key(a_pr_k, a, p)
-        
-        
-        b_pr_k = bob_private_key(p)
-        b_pu_k = bob_public_key(b_pr_k, a, p)
-        
-        if (option == 1):
-            print ("Private key of Alice = %d" % a_pr_k)
-            print ("Public key of Alice = %d" % a_pu_k)
-            print ("Private key of Bob = %d" % b_pr_k)
-            print ("Public key of Bob = %d" % b_pu_k)
-
-        """ In here, Alice send her public key to Bob,
-        and Bob also send his public key to Alice."""
-
-        a_sh_k = alice_shared_key(b_pu_k, a_pr_k, p)
-        b_sh_k = bob_shared_key(a_pu_k, b_pr_k, p)
-        print ("Shared key calculated by Alice = %d" % a_sh_k)
-        print ("Shared key calculated by Bob = %d" % b_sh_k)
-        
-        return (a_sh_k == b_sh_k)
+    try:
+        p_root_list = find_primitive_root(p)
+        p_root_list.index(a)
+    except ValueError:
+        print(f"{a} is not a primitive root of {p}")
+        # a must be primitive root of p
+        return False
+
+    a_pr_k = alice_private_key(p)
+    a_pu_k = alice_public_key(a_pr_k, a, p)
+
+    b_pr_k = bob_private_key(p)
+    b_pu_k = bob_public_key(b_pr_k, a, p)
+
+    if option == 1:
+        print(f"Alice's private key: {a_pr_k}")
+        print(f"Alice's public key: {a_pu_k}")
+        print(f"Bob's private key: {b_pr_k}")
+        print(f"Bob's public key: {b_pu_k}")
+
+    # In here, Alice send her public key to Bob, and Bob also send his public key to Alice.
+
+    a_sh_k = alice_shared_key(b_pu_k, a_pr_k, p)
+    b_sh_k = bob_shared_key(a_pu_k, b_pr_k, p)
+    print (f"Shared key calculated by Alice = {a_sh_k}")
+    print ("Shared key calculated by Bob = {b_sh_k}")
+
+    return a_sh_k == b_sh_k
diff --git a/algorithms/maths/euler_totient.py b/algorithms/maths/euler_totient.py
index 047b728..f29d382 100644
--- a/algorithms/maths/euler_totient.py
+++ b/algorithms/maths/euler_totient.py
@@ -7,12 +7,12 @@ which are coprime to n.
 def euler_totient(n):
     """Euler's totient function or Phi function.
     Time Complexity: O(sqrt(n))."""
-    result = n;
+    result = n
     for i in range(2, int(n ** 0.5) + 1):
         if n % i == 0:
             while n % i == 0:
                 n //= i
             result -= result // i
     if n > 1:
-        result -= result // n;
-    return result;
+        result -= result // n
+    return result
diff --git a/algorithms/maths/extended_gcd.py b/algorithms/maths/extended_gcd.py
index 83b6578..a0e9cbc 100644
--- a/algorithms/maths/extended_gcd.py
+++ b/algorithms/maths/extended_gcd.py
@@ -1,19 +1,24 @@
-def extended_gcd(a, b):
+"""
+Provides extended GCD functionality for finding co-prime numbers s and t such that:
+num1 * s + num2 * t = GCD(num1, num2).
+Ie the coefficients of Bézout's identity.
+"""
+def extended_gcd(num1, num2):
     """Extended GCD algorithm.
     Return s, t, g
-    such that a * s + b * t = GCD(a, b)
+    such that num1 * s + num2 * t = GCD(num1, num2)
     and s and t are co-prime.
     """
 
     old_s, s = 1, 0
     old_t, t = 0, 1
-    old_r, r = a, b
-    
+    old_r, r = num1, num2
+
     while r != 0:
         quotient = old_r / r
-        
+
         old_r, r = r, old_r - quotient * r
         old_s, s = s, old_s - quotient * s
         old_t, t = t, old_t - quotient * t
-    
+
     return old_s, old_t, old_r
diff --git a/algorithms/maths/factorial.py b/algorithms/maths/factorial.py
index 23e1f53..f5e3ea5 100644
--- a/algorithms/maths/factorial.py
+++ b/algorithms/maths/factorial.py
@@ -1,3 +1,6 @@
+"""
+Calculates the factorial with the added functionality of calculating it modulo mod.
+"""
 def factorial(n, mod=None):
     """Calculates factorial iteratively.
     If mod is not None, then return (n! % mod)
diff --git a/algorithms/maths/find_order_simple.py b/algorithms/maths/find_order_simple.py
index d4866ee..8f69773 100644
--- a/algorithms/maths/find_order_simple.py
+++ b/algorithms/maths/find_order_simple.py
@@ -1,27 +1,27 @@
-import math
-
 """
 For positive integer n and given integer a that satisfies gcd(a, n) = 1,
 the order of a modulo n is the smallest positive integer k that satisfies
 pow (a, k) % n = 1. In other words, (a^k) ≡ 1 (mod n).
-Order of certain number may or may not be exist. If so, return -1.
+Order of a certain number may or may not be exist. If not, return -1.
+
+Total time complexity O(nlog(n)):
+O(n) for iteration loop, 
+O(log(n)) for built-in power function
 """
+
+import math
+
 def find_order(a, n):
-    if ((a == 1) & (n == 1)):
+    """
+    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
         return 1
-        """ Exception Handeling :
-        1 is the order of of 1 """
-    else:
-        if (math.gcd(a, n) != 1):
-            print ("a and n should be relative prime!")
-            return -1
-        else:
-            for i in range(1, n):
-                if (pow(a, i) % n == 1):
-                    return i
-            return -1
-
-"""
-Time complexity only for calculating order = O(nlog(n))
-O(n) for iteration loop, O(log(n)) for built-in power function
-"""
+    if math.gcd(a, n) != 1:
+        print ("a and n should be relative prime!")
+        return -1
+    for i in range(1, n):
+        if pow(a, i) % n == 1:
+            return i
+    return -1
diff --git a/algorithms/maths/find_primitive_root_simple.py b/algorithms/maths/find_primitive_root_simple.py
index a5b74f6..366f401 100644
--- a/algorithms/maths/find_primitive_root_simple.py
+++ b/algorithms/maths/find_primitive_root_simple.py
@@ -1,3 +1,6 @@
+"""
+Function to find the primitive root of a number.
+"""
 import math
 
 """
@@ -7,19 +10,20 @@ pow (a, k) % n = 1. In other words, (a^k) ≡ 1 (mod n).
 Order of certain number may or may not be exist. If so, return -1.
 """
 def find_order(a, n):
-    if ((a == 1) & (n == 1)):
+    """
+    Find order for positive integer n and given integer a that satisfies gcd(a, n) = 1.
+    Time complexity O(nlog(n))
+    """
+    if (a == 1) & (n == 1):
+        # Exception Handeling : 1 is the order of of 1
         return 1
-        """ Exception Handeling :
-        1 is the order of of 1 """
-    else:
-        if (math.gcd(a, n) != 1):
-            print ("a and n should be relative prime!")
-            return -1
-        else:
-            for i in range(1, n):
-                if (pow(a, i) % n == 1):
-                    return i
-            return -1
+    if math.gcd(a, n) != 1:
+        print ("a and n should be relative prime!")
+        return -1
+    for i in range(1, n):
+        if pow(a, i) % n == 1:
+            return i
+    return -1
 
 """
 Euler's totient function, also known as phi-function ϕ(n),
@@ -31,41 +35,33 @@ Code from /algorithms/maths/euler_totient.py, written by 'goswami-rahul'
 def euler_totient(n):
     """Euler's totient function or Phi function.
     Time Complexity: O(sqrt(n))."""
-    result = n;
+    result = n
     for i in range(2, int(n ** 0.5) + 1):
         if n % i == 0:
             while n % i == 0:
                 n //= i
             result -= result // i
     if n > 1:
-        result -= result // n;
-    return result;
+        result -= result // n
+    return result
 
 """
 For positive integer n and given integer a that satisfies gcd(a, n) = 1,
 a is the primitive root of n, if a's order k for n satisfies k = ϕ(n).
-Primitive roots of certain number may or may not be exist.
+Primitive roots of certain number may or may not exist.
 If so, return empty list.
 """
-
 def find_primitive_root(n):
-    if (n == 1):
+    if n == 1:
+        # Exception Handeling : 0 is the only primitive root of 1
         return [0]
-        """ Exception Handeling :
-        0 is the only primitive root of 1 """
-    else:
-        phi = euler_totient(n)
-        p_root_list = []
-        """ It will return every primitive roots of n. """
-        for i in range (1, n):
-            if (math.gcd(i, n) != 1):
-                continue
-                """ To have order, a and n must be
-                relative prime with each other. """
-            else:
-                order = find_order(i, n)
-                if (order == phi):
-                    p_root_list.append(i)
-                else:
-                    continue
-        return p_root_list
+    phi = euler_totient(n)
+    p_root_list = []
+    """ It will return every primitive roots of n. """
+    for i in range (1, n):
+        #To have order, a and n must be relative prime with each other.
+        if math.gcd(i, n) == 1:
+            order = find_order(i, n)
+            if order == phi:
+                p_root_list.append(i)
+    return p_root_list
diff --git a/algorithms/maths/gcd.py b/algorithms/maths/gcd.py
index 35af7f1..189eae1 100644
--- a/algorithms/maths/gcd.py
+++ b/algorithms/maths/gcd.py
@@ -1,3 +1,8 @@
+"""
+Functions for calculating the greatest common divisor of two integers or
+their least common multiple.
+"""
+
 def gcd(a, b):
     """Computes the greatest common divisor of integers a and b using
     Euclid's Algorithm.
@@ -18,12 +23,10 @@ def gcd(a, b):
         a, b = b, a % b
     return a
 
-
 def lcm(a, b):
     """Computes the lowest common multiple of integers a and b."""
     return abs(a) * abs(b) / gcd(a, b)
 
-
 """
 Given a positive integer x, computes the number of trailing zero of x.
 Example
@@ -35,20 +38,19 @@ Input : 40(101000)
            ~~~^^^
 Output : 3
 """
-
 def trailing_zero(x):
-    cnt = 0
+    count = 0
     while x and not x & 1:
-        cnt += 1
+        count += 1
         x >>= 1
-    return cnt
+    return count
 
 """
 Given two non-negative integer a and b,
 computes the greatest common divisor of a and b using bitwise operator.
 """
-
 def gcd_bit(a, b):
+    """ Similar to gcd but uses bitwise operators and less error handling."""
     tza = trailing_zero(a)
     tzb = trailing_zero(b)
     a >>= tza
@@ -59,5 +61,3 @@ def gcd_bit(a, b):
         a -= b
         a >>= trailing_zero(a)
     return a << min(tza, tzb)
-
-
diff --git a/algorithms/maths/generate_strobogrammtic.py b/algorithms/maths/generate_strobogrammtic.py
index dd0c400..d051865 100644
--- a/algorithms/maths/generate_strobogrammtic.py
+++ b/algorithms/maths/generate_strobogrammtic.py
@@ -8,15 +8,14 @@ For example,
 Given n = 2, return ["11","69","88","96"].
 """
 
-
 def gen_strobogrammatic(n):
     """
+    Given n, generate all strobogrammatic numbers of length n.
     :type n: int
     :rtype: List[str]
     """
     return helper(n, n)
 
-
 def helper(n, length):
     if n == 0:
         return [""]
@@ -33,7 +32,6 @@ def helper(n, length):
         result.append("6" + middle + "9")
     return result
 
-
 def strobogrammatic_in_range(low, high):
     """
     :type low: str
@@ -49,13 +47,11 @@ def strobogrammatic_in_range(low, high):
     for perm in res:
         if len(perm) == low_len and int(perm) < int(low):
             continue
-        elif len(perm) == high_len and int(perm) > int(high):
+        if len(perm) == high_len and int(perm) > int(high):
             continue
-        else:
-            count += 1
+        count += 1
     return count
 
-
 def helper2(n, length):
     if n == 0:
         return [""]
diff --git a/algorithms/maths/hailstone.py b/algorithms/maths/hailstone.py
index 2232123..77261ac 100644
--- a/algorithms/maths/hailstone.py
+++ b/algorithms/maths/hailstone.py
@@ -1,13 +1,21 @@
+"""
+Implementation of hailstone function which generates a sequence for some n by following these rules:
+* n == 1    : done
+* n is even : the next n = n/2
+* n is odd  : the next n = 3n + 1
+"""
+
 def hailstone(n):
-  """Return the 'hailstone sequence' from n to 1
-     n: The starting point of the hailstone sequence
-  """
+    """
+    Return the 'hailstone sequence' from n to 1
+    n: The starting point of the hailstone sequence
+    """
 
-  sequence = [n]
-  while n > 1:
-    if n%2 != 0:
-      n = 3*n + 1
-    else: 
-      n = int(n/2)
-    sequence.append(n)
-  return sequence
\ No newline at end of file
+    sequence = [n]
+    while n > 1:
+        if n%2 != 0:
+            n = 3*n + 1
+        else:
+            n = int(n/2)
+        sequence.append(n)
+    return sequence
diff --git a/algorithms/maths/is_strobogrammatic.py b/algorithms/maths/is_strobogrammatic.py
index 018e695..b849dda 100644
--- a/algorithms/maths/is_strobogrammatic.py
+++ b/algorithms/maths/is_strobogrammatic.py
@@ -18,8 +18,7 @@ def is_strobogrammatic(num):
     i = 0
     j = len(num) - 1
     while i <= j:
-        x = comb.find(num[i]+num[j])
-        if x == -1:
+        if comb.find(num[i]+num[j]) == -1:
             return False
         i += 1
         j -= 1
diff --git a/algorithms/maths/krishnamurthy_number.py b/algorithms/maths/krishnamurthy_number.py
index a0a451e..1d41721 100644
--- a/algorithms/maths/krishnamurthy_number.py
+++ b/algorithms/maths/krishnamurthy_number.py
@@ -1,7 +1,8 @@
 """
-A Krishnamurthy number is a number whose sum total of the factorials of each digit is equal to the number itself.
+A Krishnamurthy number is a number whose sum total of the factorials of each digit is equal to the
+number itself.
 
-Here's what I mean by that:
+The following are some examples of Krishnamurthy numbers:
 
 "145" is a Krishnamurthy Number because,
 1! + 4! + 5! = 1 + 24 + 120 = 145
@@ -12,11 +13,13 @@ Here's what I mean by that:
 "357" or "25965" is NOT a Krishnamurthy Number
 3! + 5! + 7! = 6 + 120 + 5040 != 357
 
-The following function will check if a number is a Krishnamurthy Number or not and return a boolean value.
+The following function will check if a number is a Krishnamurthy Number or not and return a
+boolean value.
 """
 
 
 def find_factorial(n):
+    """ Calculates the factorial of a given number n """
     fact = 1
     while n != 0:
         fact *= n
@@ -40,4 +43,4 @@ def krishnamurthy_number(n):
         temp //= 10
 
     # returns True if number is krishnamurthy
-    return (sum_of_digits == n)
+    return sum_of_digits == n
diff --git a/algorithms/maths/magic_number.py b/algorithms/maths/magic_number.py
index fe62bc6..6107753 100644
--- a/algorithms/maths/magic_number.py
+++ b/algorithms/maths/magic_number.py
@@ -1,8 +1,8 @@
-"""Magic Number
+"""
+Magic Number
 A number is said to be a magic number,
-if the sum of its digits are calculated till a single digit recursively
-by adding the sum of the digits after every addition.
-If the single digit comes out to be 1,then the number is a magic number.
+if summing the digits of the number and then recursively repeating this process for the given sum
+untill the number becomes a single digit number equal to 1.
 
 Example:
     Number = 50113 => 5+0+1+1+3=10 => 1+0=1 [This is a Magic Number]
@@ -13,15 +13,14 @@ Example:
 The following function checks for Magic numbers and returns a Boolean accordingly.
 """
 
-
 def magic_number(n):
+    """ Checks if n is a magic number """
     total_sum = 0
 
     # will end when n becomes 0
     # AND
     # sum becomes single digit.
     while n > 0 or total_sum > 9:
-        
         # when n becomes 0 but we have a total_sum,
         # we update the value of n with the value of the sum digits
         if n == 0:
@@ -32,5 +31,3 @@ def magic_number(n):
 
     # Return true if sum becomes 1
     return total_sum == 1
-
-
diff --git a/algorithms/maths/modular_inverse.py b/algorithms/maths/modular_inverse.py
index f53d0f6..c6f849d 100644
--- a/algorithms/maths/modular_inverse.py
+++ b/algorithms/maths/modular_inverse.py
@@ -1,5 +1,5 @@
-# extended_gcd(a, b) modified from 
-# https://github.com/keon/algorithms/blob/master/algorithms/maths/extended_gcd.py 
+# extended_gcd(a, b) modified from
+# https://github.com/keon/algorithms/blob/master/algorithms/maths/extended_gcd.py
 
 def extended_gcd(a: int, b: int) -> [int, int, int]:
     """Extended GCD algorithm.
@@ -11,24 +11,24 @@ def extended_gcd(a: int, b: int) -> [int, int, int]:
     old_s, s = 1, 0
     old_t, t = 0, 1
     old_r, r = a, b
-    
+
     while r != 0:
         quotient = old_r // r
-        
+
         old_r, r = r, old_r - quotient * r
         old_s, s = s, old_s - quotient * s
         old_t, t = t, old_t - quotient * t
-    
+
     return old_s, old_t, old_r
 
 
 def modular_inverse(a: int, m: int) -> int:
     """
     Returns x such that a * x = 1 (mod m)
-    a and m must be coprime 
+    a and m must be coprime
     """
 
-    s, t, g = extended_gcd(a, m)
+    s, _, g = extended_gcd(a, m)
     if g != 1:
         raise ValueError("a and m must be coprime")
     return s % m
diff --git a/algorithms/maths/next_bigger.py b/algorithms/maths/next_bigger.py
index e14e22c..a159da1 100644
--- a/algorithms/maths/next_bigger.py
+++ b/algorithms/maths/next_bigger.py
@@ -1,9 +1,9 @@
 """
-I just bombed an interview and made pretty much zero 
-progress on my interview question. 
+I just bombed an interview and made pretty much zero
+progress on my interview question.
 
-Given a number, find the next higher number which has the 
-exact same set of digits as the original number. 
+Given a number, find the next higher number which has the
+exact same set of digits as the original number.
 For example: given 38276 return 38627.
              given 99999 return -1. (no such number exists)
 
diff --git a/algorithms/maths/next_perfect_square.py b/algorithms/maths/next_perfect_square.py
index 7e6e6b9..be2d24a 100644
--- a/algorithms/maths/next_perfect_square.py
+++ b/algorithms/maths/next_perfect_square.py
@@ -1,6 +1,7 @@
 """
 This program will look for the next perfect square.
-Check the argument to see if it is a perfect square itself, if it is not then return -1 otherwise look for the next perfect square
+Check the argument to see if it is a perfect square itself, if it is not then return -1 otherwise
+look for the next perfect square.
 for instance if you pass 121 then the script should return the next perfect square which is 144.
 """
 
@@ -9,11 +10,8 @@ def find_next_square(sq):
     if root.is_integer():
         return (root + 1)**2
     return -1
-    
-    
-# Another way:
 
 def find_next_square2(sq):
-    x = sq**0.5    
-    return -1 if x % 1 else (x+1)**2
-
+    """ Alternative method, works by evaluating anything non-zero as True (0.000001 --> True) """
+    root = sq**0.5
+    return -1 if root % 1 else (root+1)**2
diff --git a/algorithms/maths/nth_digit.py b/algorithms/maths/nth_digit.py
index 381926f..f6454e9 100644
--- a/algorithms/maths/nth_digit.py
+++ b/algorithms/maths/nth_digit.py
@@ -14,4 +14,4 @@ def find_nth_digit(n):
         start *= 10
     start += (n-1) / length
     s = str(start)
-    return int(s[(n-1) % length])
\ No newline at end of file
+    return int(s[(n-1) % length])
diff --git a/algorithms/maths/num_digits.py b/algorithms/maths/num_digits.py
index 93f0e20..4ecd5c7 100644
--- a/algorithms/maths/num_digits.py
+++ b/algorithms/maths/num_digits.py
@@ -1,11 +1,12 @@
 """
-   num_digits() method will return the number of digits of a number in O(1) time using math.log10() method.
+num_digits() method will return the number of digits of a number in O(1) time using
+math.log10() method.
 """
 
 import math
 
 def num_digits(n):
-  n=abs(n)
-  if(n==0):
-      return 1;
-  return int(math.log10(n))+1
+    n=abs(n)
+    if n==0:
+        return 1
+    return int(math.log10(n))+1
diff --git a/algorithms/maths/polynomial.py b/algorithms/maths/polynomial.py
index 55b59dd..07a0c3b 100644
--- a/algorithms/maths/polynomial.py
+++ b/algorithms/maths/polynomial.py
@@ -12,7 +12,7 @@ class Monomial:
     record the details of all variables
     that a typical monomial is composed of.
     """
-    def __init__(self, variables: Dict[int, int], coeff: Union[int, float, Fraction, None]=None) -> None:
+    def __init__(self, variables: Dict[int, int], coeff: Union[int, float, Fraction, None]= None) -> None:
         '''
         Create a monomial in the given variables:
         Examples:
@@ -63,7 +63,6 @@ class Monomial:
         else:
             return num
 
-
     # def equal_upto_scalar(self, other: Monomial) -> bool:
     def equal_upto_scalar(self, other) -> bool:
         """
@@ -353,7 +352,7 @@ class Polynomial:
             return Polynomial([z for z in monos])
         elif isinstance(other, Polynomial):
             temp = list(z for z in {m.clone() for m in self.all_monomials()})
-        
+
             p = Polynomial(temp)
             for o in other.all_monomials():
                 p = p.__add__(o.clone())
@@ -391,7 +390,7 @@ class Polynomial:
             for o in other.all_monomials():
                 p = p.__sub__(o.clone())
             return p
-        
+
         else:
             raise ValueError('Can only subtract int, float, Fraction, Monomials, or Polynomials from Polynomials.')
             return
@@ -531,4 +530,3 @@ class Polynomial:
         the polynomial.
         """
         return ' + '.join(str(m) for m in self.all_monomials() if m.coeff != Fraction(0, 1))
-
diff --git a/algorithms/maths/power.py b/algorithms/maths/power.py
index 99e694f..70d8587 100644
--- a/algorithms/maths/power.py
+++ b/algorithms/maths/power.py
@@ -1,10 +1,14 @@
-def power(a: int, n: int, r: int = None):
+"""
+Performs exponentiation, similarly to the built-in pow() or ** functions.
+Allows also for calculating the exponentiation modulo.
+"""
+def power(a: int, n: int, mod: int = None):
     """
     Iterative version of binary exponentiation
-    
+
     Calculate a ^ n
-    if r is specified, return the result modulo r
-    
+    if mod is specified, return the result modulo mod
+
     Time Complexity :  O(log(n))
     Space Complexity : O(1)
     """
@@ -13,20 +17,20 @@ def power(a: int, n: int, r: int = None):
         if n & 1:
             ans = ans * a
         a = a * a
-        if r:
-            ans %= r
-            a %= r
+        if mod:
+            ans %= mod
+            a %= mod
         n >>= 1
     return ans
 
 
-def power_recur(a: int, n: int, r: int = None):
+def power_recur(a: int, n: int, mod: int = None):
     """
     Recursive version of binary exponentiation
-    
+
     Calculate a ^ n
-    if r is specified, return the result modulo r
-    
+    if mod is specified, return the result modulo mod
+
     Time Complexity :  O(log(n))
     Space Complexity : O(log(n))
     """
@@ -35,11 +39,10 @@ def power_recur(a: int, n: int, r: int = None):
     elif n == 1:
         ans = a
     else:
-        ans = power_recur(a, n // 2, r)
+        ans = power_recur(a, n // 2, mod)
         ans = ans * ans
         if n % 2:
             ans = ans * a
-    if r:
-        ans %= r
+    if mod:
+        ans %= mod
     return ans
-
diff --git a/algorithms/maths/primes_sieve_of_eratosthenes.py b/algorithms/maths/primes_sieve_of_eratosthenes.py
index 7c21c6d..b0d1d96 100644
--- a/algorithms/maths/primes_sieve_of_eratosthenes.py
+++ b/algorithms/maths/primes_sieve_of_eratosthenes.py
@@ -24,7 +24,6 @@ With this, we have reduced the array size to a half,
 and complexity it's also a half now.
 """
 
-
 def get_primes(n):
     """Return list of all primes less than n,
     Using sieve of Eratosthenes.
diff --git a/algorithms/maths/pythagoras.py b/algorithms/maths/pythagoras.py
index d896260..b24b682 100644
--- a/algorithms/maths/pythagoras.py
+++ b/algorithms/maths/pythagoras.py
@@ -1,16 +1,20 @@
 """
-input two of the three side in right angled triangle and return the third. use "?" to indicate the unknown side. 
+Given the lengths of two of the three sides of a right angled triangle, this function returns the
+length of the third side.
 """
 
-def pythagoras(opposite,adjacent,hypotenuse):
+def pythagoras(opposite, adjacent, hypotenuse):
+    """
+    Returns length of a third side of a right angled triangle.
+    Passing "?" will indicate the unknown side.
+    """
     try:
         if opposite == str("?"):
             return ("Opposite = " + str(((hypotenuse**2) - (adjacent**2))**0.5))
-        elif adjacent == str("?"):
+        if adjacent == str("?"):
             return ("Adjacent = " + str(((hypotenuse**2) - (opposite**2))**0.5))
-        elif hypotenuse == str("?"):
+        if hypotenuse == str("?"):
             return ("Hypotenuse = " + str(((opposite**2) + (adjacent**2))**0.5))
-        else:
-            return "You already know the answer!"
+        return "You already know the answer!"
     except:
-        raise ValueError("invalid argument were given.")
+        raise ValueError("invalid argument(s) were given.")
diff --git a/algorithms/maths/rabin_miller.py b/algorithms/maths/rabin_miller.py
index a3aad8e..08b12c1 100644
--- a/algorithms/maths/rabin_miller.py
+++ b/algorithms/maths/rabin_miller.py
@@ -47,5 +47,5 @@ def is_prime(n, k):
     for _ in range(k):
         if valid_witness(random.randrange(2, n - 2)):
             return False
-    
+
     return True
diff --git a/algorithms/maths/recursive_binomial_coefficient.py b/algorithms/maths/recursive_binomial_coefficient.py
index ae57bd6..a924200 100644
--- a/algorithms/maths/recursive_binomial_coefficient.py
+++ b/algorithms/maths/recursive_binomial_coefficient.py
@@ -22,7 +22,5 @@ def recursive_binomial_coefficient(n,k):
     if k > n/2:
         #C(n,k) = C(n,n-k), so if n/2 is sufficiently small, we can reduce the problem size.
         return recursive_binomial_coefficient(n,n-k)
-    else:
-        #else, we know C(n,k) = (n/k)C(n-1,k-1), so we can use this to reduce our problem size.
-        return int((n/k)*recursive_binomial_coefficient(n-1,k-1))
-
+    #else, we know C(n,k) = (n/k)C(n-1,k-1), so we can use this to reduce our problem size.
+    return int((n/k)*recursive_binomial_coefficient(n-1,k-1))
diff --git a/algorithms/maths/rsa.py b/algorithms/maths/rsa.py
index 70b7bc5..bbf193c 100644
--- a/algorithms/maths/rsa.py
+++ b/algorithms/maths/rsa.py
@@ -21,6 +21,13 @@ a number very quickly:
 (a ** b) % c == pow(a,b,c)
 """
 
+# sample usage:
+# n,e,d = generate_key(16)
+# data = 20
+# encrypted = pow(data,e,n)
+# decrypted = pow(encrypted,d,n)
+# assert decrypted == data
+
 import random
 
 
@@ -58,23 +65,23 @@ def generate_key(k, seed=None):
     # size in bits of p and q need to add up to the size of n
     p_size = k / 2
     q_size = k - p_size
-    
+
     e = gen_prime(k, seed)  # in many cases, e is also chosen to be a small constant
-    
+
     while True:
         p = gen_prime(p_size, seed)
         if p % e != 1:
             break
-    
+
     while True:
         q = gen_prime(q_size, seed)
         if q % e != 1:
             break
-    
+
     n = p * q
     l = (p - 1) * (q - 1)  # calculate totient function
     d = modinv(e, l)
-    
+
     return int(n), int(e), int(d)
 
 
@@ -84,13 +91,3 @@ def encrypt(data, e, n):
 
 def decrypt(data, d, n):
     return pow(int(data), int(d), int(n))
-
-
-
-# sample usage:
-# n,e,d = generate_key(16)
-# data = 20
-# encrypted = pow(data,e,n)
-# decrypted = pow(encrypted,d,n)
-# assert decrypted == data
-
diff --git a/algorithms/maths/summing_digits.py b/algorithms/maths/summing_digits.py
index f181a92..ec30ffd 100644
--- a/algorithms/maths/summing_digits.py
+++ b/algorithms/maths/summing_digits.py
@@ -1,18 +1,19 @@
 """
 Recently, I encountered an interview question whose description was as below:
 
-The number 89 is the first integer with more than one digit whose digits when raised up to consecutive powers give the same 
-number. For example, 89 = 8**1 + 9**2 gives the number 89. 
+The number 89 is the first integer with more than one digit whose digits when raised up to
+consecutive powers give the same number. For example, 89 = 8**1 + 9**2 gives the number 89.
 
 The next number after 89 with this property is 135 = 1**1 + 3**2 + 5**3 = 135.
 
-Write a function that returns a list of numbers with the above property. The function will receive range as parameter.
+Write a function that returns a list of numbers with the above property. The function will
+receive range as parameter.
 """
 
-def sum_dig_pow(a, b):  
+def sum_dig_pow(low, high):
     result = []
-    
-    for number in range(a, b + 1):
+
+    for number in range(low, high + 1):
         exponent = 1  # set to 1
         summation = 0    # set to 1
         number_as_string = str(number)
diff --git a/algorithms/maths/symmetry_group_cycle_index.py b/algorithms/maths/symmetry_group_cycle_index.py
index 5f3872a..01b3e05 100644
--- a/algorithms/maths/symmetry_group_cycle_index.py
+++ b/algorithms/maths/symmetry_group_cycle_index.py
@@ -1,72 +1,69 @@
-from polynomial import ( Monomial, Polynomial )
-from gcd import lcm
-from fractions import Fraction
-from typing import Dict, Union
-
-
 """
-	The significance of the cycle index (polynomial) of symmetry group
-	is deeply rooted in counting the number of configurations
-	of an object excluding those that are symmetric (in terms of permutations).
-
-	For example, the following problem can be solved as a direct
-	application of the cycle index polynomial of the symmetry
-	group.
+The significance of the cycle index (polynomial) of symmetry group
+is deeply rooted in counting the number of configurations
+of an object excluding those that are symmetric (in terms of permutations).
 
-	Note: I came across this problem as a Google's foo.bar challenge at Level 5
-	and solved it using a purely Group Theoretic approach. :)
+For example, the following problem can be solved as a direct
+application of the cycle index polynomial of the symmetry
+group.
 
-	-----
+Note: I came across this problem as a Google's foo.bar challenge at Level 5
+and solved it using a purely Group Theoretic approach. :)
+-----
 
-	Problem:
+Problem:
 
-	Given positive integers
-	w, h, and s,
-	compute the number of distinct 2D
-	grids of dimensions w x h that contain
-	entries from {0, 1, ..., s-1}.
-	Note that two grids are defined
-	to be equivalent if one can be
-	obtained from the other by
-	switching rows and columns
-	some number of times.
+Given positive integers
+w, h, and s,
+compute the number of distinct 2D
+grids of dimensions w x h that contain
+entries from {0, 1, ..., s-1}.
+Note that two grids are defined
+to be equivalent if one can be
+obtained from the other by
+switching rows and columns
+some number of times.
 
-	-----
+-----
 
-	Approach:
+Approach:
 
-	Compute the cycle index (polynomials)
-	of S_w, and S_h, i.e. the Symmetry
-	group on w and h symbols respectively.
+Compute the cycle index (polynomials)
+of S_w, and S_h, i.e. the Symmetry
+group on w and h symbols respectively.
 
-	Compute the product of the two
-	cycle indices while combining two
-	monomials in such a way that
-	for any pair of cycles c1, and c2
-	in the elements of S_w X S_h,
-	the resultant monomial contains
-	terms of the form:
-	$$ x_{lcm(|c1|, |c2|)}^{gcd(|c1|, |c2|)} $$
+Compute the product of the two
+cycle indices while combining two
+monomials in such a way that
+for any pair of cycles c1, and c2
+in the elements of S_w X S_h,
+the resultant monomial contains
+terms of the form:
+$$ x_{lcm(|c1|, |c2|)}^{gcd(|c1|, |c2|)} $$
 
-	Return the specialization of
-	the product of cycle indices
-	at x_i = s (for all the valid i).
+Return the specialization of
+the product of cycle indices
+at x_i = s (for all the valid i).
 
-	-----
+-----
 
-	Code:
+Code:
 
-	def solve(w, h, s):
+def solve(w, h, s):
+    s1 = get_cycle_index_sym(w)
+    s2 = get_cycle_index_sym(h)
 
-		s1 = get_cycle_index_sym(w)
-	    s2 = get_cycle_index_sym(h)
-	    
-	    result = cycle_product_for_two_polynomials(s1, s2, s)
-	    
-	    return str(result)
+    result = cycle_product_for_two_polynomials(s1, s2, s)
 
+    return str(result)
 """
 
+from fractions import Fraction
+from typing import Dict, Union
+from polynomial import ( Monomial, Polynomial )
+from gcd import lcm
+
+
 def cycle_product(m1: Monomial, m2: Monomial) -> Monomial:
     """
     Given two monomials (from the
@@ -132,14 +129,14 @@ def get_cycle_index_sym(n: int) -> Polynomial:
 
     """
     if n < 0:
-    	raise ValueError('n should be a non-negative integer.')
+        raise ValueError('n should be a non-negative integer.')
 
     memo = {
         0: Polynomial([
             Monomial({}, Fraction(1, 1))
         ]),
         1: Polynomial([
-            Monomial({1:1}, Fraction(1, 1))
+            Monomial({1: 1}, Fraction(1, 1))
         ]),
         2: Polynomial([
             Monomial({1: 2}, Fraction(1, 2)),
@@ -148,14 +145,14 @@ def get_cycle_index_sym(n: int) -> Polynomial:
         3: Polynomial([
             Monomial({1: 3}, Fraction(1, 6)),
             Monomial({1: 1, 2: 1}, Fraction(1, 2)),
-            Monomial({3:1}, Fraction(1, 3))
+            Monomial({3: 1}, Fraction(1, 3))
         ]),
         4: Polynomial([
-            Monomial({1:4}, Fraction(1, 24)),
-            Monomial({2:1, 1:2},Fraction(1, 4)),
-            Monomial({3:1, 1:1}, Fraction(1, 3)),
-            Monomial({2:2}, Fraction(1, 8)),
-            Monomial({4:1}, Fraction(1, 4)),
+            Monomial({1: 4}, Fraction(1, 24)),
+            Monomial({2: 1, 1: 2}, Fraction(1, 4)),
+            Monomial({3: 1, 1: 1}, Fraction(1, 3)),
+            Monomial({2: 2}, Fraction(1, 8)),
+            Monomial({4: 1}, Fraction(1, 4)),
         ])
     }
     result = cycle_index_sym_helper(n, memo)
diff --git a/algorithms/matrix/bomb_enemy.py b/algorithms/matrix/bomb_enemy.py
index debcf5d..c841263 100644
--- a/algorithms/matrix/bomb_enemy.py
+++ b/algorithms/matrix/bomb_enemy.py
@@ -17,8 +17,10 @@ E 0 W E
 return 3. (Placing a bomb at (1,1) kills 3 enemies)
 """
 
+
 def max_killed_enemies(grid):
-    if not grid: return 0
+    if not grid:
+        return 0
     m, n = len(grid), len(grid[0])
     max_killed = 0
     row_e, col_e = 0, [0] * n
@@ -38,6 +40,7 @@ def max_killed_enemies(grid):
 
     return max_killed
 
+
 # calculate killed enemies for row i from column j
 def row_kills(grid, i, j):
     num = 0
@@ -48,6 +51,7 @@ def row_kills(grid, i, j):
         j += 1
     return num
 
+
 # calculate killed enemies for  column j from row i
 def col_kills(grid, i, j):
     num = 0
@@ -57,7 +61,6 @@ def col_kills(grid, i, j):
             num += 1
         i += 1
     return num
-                
 
 
 # ----------------- TESTS -------------------------
@@ -66,14 +69,16 @@ def col_kills(grid, i, j):
     Testsuite for the project
 """
 
-import unittest 
+import unittest
+
 
 class TestBombEnemy(unittest.TestCase):
     def test_3x4(self):
-        grid1 = [["0","E","0","0"],
-                ["E","0","W","E"],
-                ["0","E","0","0"]]
-        self.assertEqual(3,max_killed_enemies(grid1))
+        grid1 = [["0", "E", "0", "0"],
+                 ["E", "0", "W", "E"],
+                 ["0", "E", "0", "0"]]
+        self.assertEqual(3, max_killed_enemies(grid1))
+
     def test_4x4(self):
         grid1 = [
                 ["0", "E", "0", "E"],
@@ -85,9 +90,9 @@ class TestBombEnemy(unittest.TestCase):
                 ["E", "0", "0", "0"],
                 ["E", "0", "W", "E"],
                 ["0", "E", "0", "0"]]
-        self.assertEqual(5,max_killed_enemies(grid1))
-        self.assertEqual(3,max_killed_enemies(grid2))
+        self.assertEqual(5, max_killed_enemies(grid1))
+        self.assertEqual(3, max_killed_enemies(grid2))
+
 
 if __name__ == "__main__":
     unittest.main()
-
diff --git a/algorithms/matrix/cholesky_matrix_decomposition.py b/algorithms/matrix/cholesky_matrix_decomposition.py
index 4b5e24e..28ef5ea 100644
--- a/algorithms/matrix/cholesky_matrix_decomposition.py
+++ b/algorithms/matrix/cholesky_matrix_decomposition.py
@@ -1,6 +1,8 @@
 """
-Cholesky matrix decomposition is used to find the decomposition of a Hermitian positive-definite matrix A
-into matrix V, so that V * V* = A, where V* denotes the conjugate transpose of L.
+Cholesky matrix decomposition is used to find the decomposition of a
+Hermitian positive-definite matrix A
+into matrix V, so that V * V* = A, where V* denotes the conjugate
+transpose of L.
 The dimensions of the matrix A must match.
 
 This method is mainly used for numeric solution of linear equations Ax = b.
@@ -25,7 +27,8 @@ import math
 def cholesky_decomposition(A):
     """
     :param A: Hermitian positive-definite matrix of type List[List[float]]
-    :return: matrix of type List[List[float]] if A can be decomposed, otherwise None
+    :return: matrix of type List[List[float]] if A can be decomposed,
+    otherwise None
     """
     n = len(A)
     for ai in A:
diff --git a/algorithms/matrix/copy_transform.py b/algorithms/matrix/copy_transform.py
index 772a81c..99bfa46 100644
--- a/algorithms/matrix/copy_transform.py
+++ b/algorithms/matrix/copy_transform.py
@@ -9,6 +9,7 @@ def rotate_clockwise(matrix):
                 new[i].append(elem)
     return new
 
+
 def rotate_counterclockwise(matrix):
     new = []
     for row in matrix:
@@ -20,6 +21,7 @@ def rotate_counterclockwise(matrix):
                 new[i].append(elem)
     return new
 
+
 def top_left_invert(matrix):
     new = []
     for row in matrix:
@@ -31,6 +33,7 @@ def top_left_invert(matrix):
                 new[i].append(elem)
     return new
 
+
 def bottom_left_invert(matrix):
     new = []
     for row in reversed(matrix):
@@ -42,6 +45,7 @@ def bottom_left_invert(matrix):
                 new[i].append(elem)
     return new
 
+
 if __name__ == '__main__':
     def print_matrix(matrix, name):
         print('{}:\n['.format(name))
diff --git a/algorithms/matrix/crout_matrix_decomposition.py b/algorithms/matrix/crout_matrix_decomposition.py
index 46929b5..bfb859b 100644
--- a/algorithms/matrix/crout_matrix_decomposition.py
+++ b/algorithms/matrix/crout_matrix_decomposition.py
@@ -26,6 +26,7 @@ We can check that L * U = A.
 I think the complexity should be O(n^3).
 """
 
+
 def crout_matrix_decomposition(A):
     n = len(A)
     L = [[0.0] * n for i in range(n)]
@@ -44,4 +45,4 @@ def crout_matrix_decomposition(A):
             if int(L[j][j]) == 0:
                 L[j][j] = float(0.1**40)
             U[j][i] = float(tempU/L[j][j])
-    return (L,U)
+    return (L, U)
diff --git a/algorithms/matrix/matrix_exponentiation.py b/algorithms/matrix/matrix_exponentiation.py
index f9673ce..2c836fe 100644
--- a/algorithms/matrix/matrix_exponentiation.py
+++ b/algorithms/matrix/matrix_exponentiation.py
@@ -13,18 +13,20 @@ def multiply(matA: list, matB: list) -> list:
 
     return matC
 
+
 def identity(n: int) -> list:
     """
     Returns the Identity matrix of size n x n
     Time Complexity: O(n^2)
     """
     I = [[0 for i in range(n)] for j in range(n)]
-    
+
     for i in range(n):
         I[i][i] = 1
-    
+
     return I
 
+
 def matrix_exponentiation(mat: list, n: int) -> list:
     """
     Calculates mat^n by repeated squaring
diff --git a/algorithms/matrix/rotate_image.py b/algorithms/matrix/rotate_image.py
index f237fbf..a8b5e4e 100644
--- a/algorithms/matrix/rotate_image.py
+++ b/algorithms/matrix/rotate_image.py
@@ -25,9 +25,9 @@ def rotate(mat):
 
 
 if __name__ == "__main__":
-    mat = [[1,2,3],
-           [4,5,6],
-           [7,8,9]]
+    mat = [[1, 2, 3],
+           [4, 5, 6],
+           [7, 8, 9]]
     print(mat)
     rotate(mat)
     print(mat)
diff --git a/algorithms/matrix/search_in_sorted_matrix.py b/algorithms/matrix/search_in_sorted_matrix.py
index ce37112..54502c3 100644
--- a/algorithms/matrix/search_in_sorted_matrix.py
+++ b/algorithms/matrix/search_in_sorted_matrix.py
@@ -10,13 +10,13 @@ def search_in_a_sorted_matrix(mat, m, n, key):
     i, j = m-1, 0
     while i >= 0 and j < n:
         if key == mat[i][j]:
-            print ('Key %s found at row- %s column- %s' % (key, i+1, j+1))
+            print('Key %s found at row- %s column- %s' % (key, i+1, j+1))
             return
         if key < mat[i][j]:
             i -= 1
         else:
             j += 1
-    print ('Key %s not found' % (key))
+    print('Key %s not found' % (key))
 
 
 def main():
@@ -27,7 +27,7 @@ def main():
            [12, 17, 20]
           ]
     key = 13
-    print (mat)
+    print(mat)
     search_in_a_sorted_matrix(mat, len(mat), len(mat[0]), key)
 
 
diff --git a/algorithms/matrix/sort_matrix_diagonally.py b/algorithms/matrix/sort_matrix_diagonally.py
index 4e9e085..b32c710 100644
--- a/algorithms/matrix/sort_matrix_diagonally.py
+++ b/algorithms/matrix/sort_matrix_diagonally.py
@@ -32,7 +32,7 @@ def sort_diagonally(mat: List[List[int]]) -> List[List[int]]:
     for i in range(len(mat)+len(mat[0])-1):
         # Process the rows
         if i+1 < len(mat):
-            # Initialize heap, set row and column
+            # Initialize heap, set row and column
             h = []
             row = len(mat)-(i+1)
             col = 0
diff --git a/algorithms/matrix/sparse_dot_vector.py b/algorithms/matrix/sparse_dot_vector.py
index 19053ec..0cba0a5 100644
--- a/algorithms/matrix/sparse_dot_vector.py
+++ b/algorithms/matrix/sparse_dot_vector.py
@@ -1,7 +1,8 @@
 #! /usr/bin/env python3
 
 """
-Suppose we have very large sparse vectors, which contains a lot of zeros and double .
+Suppose we have very large sparse vectors, which contains a lot of
+zeros and double .
 
 find a data structure to store them
 get the dot product of them
diff --git a/algorithms/matrix/sparse_mul.py b/algorithms/matrix/sparse_mul.py
index c3b7b61..eeaae0e 100644
--- a/algorithms/matrix/sparse_mul.py
+++ b/algorithms/matrix/sparse_mul.py
@@ -30,7 +30,8 @@ def multiply(self, a, b):
     :type B: List[List[int]]
     :rtype: List[List[int]]
     """
-    if a is None or b is None: return None
+    if a is None or b is None:
+        return None
     m, n, l = len(a), len(b[0]), len(b[0])
     if len(b) != n:
         raise Exception("A's column number must be equal to B's row number.")
@@ -39,7 +40,8 @@ def multiply(self, a, b):
         for k, eleA in enumerate(row):
             if eleA:
                 for j, eleB in enumerate(b[k]):
-                    if eleB: c[i][j] += eleA * eleB
+                    if eleB:
+                        c[i][j] += eleA * eleB
     return c
 
 
@@ -50,7 +52,8 @@ def multiply(self, a, b):
     :type B: List[List[int]]
     :rtype: List[List[int]]
     """
-    if a is None or b is None: return None
+    if a is None or b is None:
+        return None
     m, n, l = len(a), len(a[0]), len(b[0])
     if len(b) != n:
         raise Exception("A's column number must be equal to B's row number.")
@@ -59,7 +62,8 @@ def multiply(self, a, b):
     for k, row in enumerate(b):
         table_b[k] = {}
         for j, eleB in enumerate(row):
-            if eleB: table_b[k][j] = eleB
+            if eleB:
+                table_b[k][j] = eleB
     for i, row in enumerate(a):
         for k, eleA in enumerate(row):
             if eleA:
@@ -67,6 +71,7 @@ def multiply(self, a, b):
                     c[i][j] += eleA * eleB
     return c
 
+
 # Python solution with two tables (~196ms):
 def multiply(self, a, b):
     """
@@ -74,7 +79,8 @@ def multiply(self, a, b):
     :type B: List[List[int]]
     :rtype: List[List[int]]
     """
-    if a is None or b is None: return None
+    if a is None or b is None:
+        return None
     m, n = len(a), len(b[0])
     if len(b) != n:
         raise Exception("A's column number must be equal to B's row number.")
@@ -83,17 +89,20 @@ def multiply(self, a, b):
     for i, row in enumerate(a):
         for j, ele in enumerate(row):
             if ele:
-                if i not in table_a: table_a[i] = {}
+                if i not in table_a:
+                    table_a[i] = {}
                 table_a[i][j] = ele
     for i, row in enumerate(b):
         for j, ele in enumerate(row):
             if ele:
-                if i not in table_b: table_b[i] = {}
+                if i not in table_b:
+                    table_b[i] = {}
                 table_b[i][j] = ele
     c = [[0 for j in range(l)] for i in range(m)]
     for i in table_a:
         for k in table_a[i]:
-            if k not in table_b: continue
+            if k not in table_b:
+                continue
             for j in table_b[k]:
                 c[i][j] += table_a[i][k] * table_b[k][j]
     return c
diff --git a/algorithms/matrix/sudoku_validator.py b/algorithms/matrix/sudoku_validator.py
index 7bda6e4..257fcce 100644
--- a/algorithms/matrix/sudoku_validator.py
+++ b/algorithms/matrix/sudoku_validator.py
@@ -1,12 +1,19 @@
 """
-Write a function validSolution/ValidateSolution/valid_solution() that accepts a 2D array representing a Sudoku board, and returns true if it is a valid solution, or false otherwise. The cells of the sudoku board may also contain 0's, which will represent empty cells. Boards containing one or more zeroes are considered to be invalid solutions.
-The board is always 9 cells by 9 cells, and every cell only contains integers from 0 to 9.
+Write a function validSolution/ValidateSolution/valid_solution()
+that accepts a 2D array representing a Sudoku board, and returns true
+if it is a valid solution, or false otherwise. The cells of the sudoku
+board may also contain 0's, which will represent empty cells.
+Boards containing one or more zeroes are considered to be invalid solutions.
+The board is always 9 cells by 9 cells, and every cell only contains integers
+from 0 to 9.
 
 (More info at: http://en.wikipedia.org/wiki/Sudoku)
 """
 
 # Using dict/hash-table
 from collections import defaultdict
+
+
 def valid_solution_hashtable(board):
     for i in range(len(board)):
         dict_row = defaultdict(int)
@@ -31,7 +38,7 @@ def valid_solution_hashtable(board):
             grid_add = 0
             for k in range(3):
                 for l in range(3):
-                    grid_add += board[i*3+k][j*3+l]
+                    grid_add += board[i * 3 + k][j * 3 + l]
             if grid_add != 45:
                 return False
     return True
@@ -65,7 +72,7 @@ def valid_solution(board):
 
 
 # Using set
-def valid_solution_set (board):
+def valid_solution_set(board):
     valid = set(range(1, 10))
 
     for row in board:
diff --git a/algorithms/matrix/sum_sub_squares.py b/algorithms/matrix/sum_sub_squares.py
index 45de7f1..1231547 100644
--- a/algorithms/matrix/sum_sub_squares.py
+++ b/algorithms/matrix/sum_sub_squares.py
@@ -1,6 +1,6 @@
-# Function to find sum of all  
-# sub-squares of size k x k in a given 
-# square matrix of size n x n 
+# Function to find sum of all
+# sub-squares of size k x k in a given
+# square matrix of size n x n
 def sum_sub_squares(matrix, k):
     n = len(matrix)
     result = [[0 for i in range(k)] for j in range(k)]
@@ -8,17 +8,16 @@ def sum_sub_squares(matrix, k):
     if k > n:
         return
     for i in range(n - k + 1):
-        l = 0 
+        l = 0
         for j in range(n - k + 1):
             sum = 0
-            
-            # Calculate and print sum of current sub-square 
+
+            # Calculate and print sum of current sub-square
             for p in range(i, k + i):
                 for q in range(j, k + j):
                     sum += matrix[p][q]
-            
+
             result[i][l] = sum
-            l += 1 
-         
-    return result
+            l += 1
 
+    return result
diff --git a/algorithms/queues/max_sliding_window.py b/algorithms/queues/max_sliding_window.py
index 7d1a45f..74db65e 100644
--- a/algorithms/queues/max_sliding_window.py
+++ b/algorithms/queues/max_sliding_window.py
@@ -18,6 +18,8 @@ For each index i:
 """
 
 import collections
+
+
 def max_sliding_window(arr, k):
     qi = collections.deque()  # queue storing indexes of elements
     result = []
diff --git a/algorithms/queues/priority_queue.py b/algorithms/queues/priority_queue.py
index 76b0815..c573ac3 100644
--- a/algorithms/queues/priority_queue.py
+++ b/algorithms/queues/priority_queue.py
@@ -53,4 +53,3 @@ class PriorityQueue:
         """
         # remove and return the first node from the queue
         return self.priority_queue_list.pop().data
-
diff --git a/algorithms/queues/queue.py b/algorithms/queues/queue.py
index feab56b..b3ccb4e 100644
--- a/algorithms/queues/queue.py
+++ b/algorithms/queues/queue.py
@@ -13,6 +13,8 @@ Queue Abstract Data Type (ADT)
 * peek() returns the front element of the queue.
 """
 from abc import ABCMeta, abstractmethod
+
+
 class AbstractQueue(metaclass=ABCMeta):
 
     def __init__(self):
@@ -96,6 +98,7 @@ class QueueNode:
         self.value = value
         self.next = None
 
+
 class LinkedListQueue(AbstractQueue):
 
     def __init__(self):
diff --git a/algorithms/queues/zigzagiterator.py b/algorithms/queues/zigzagiterator.py
index a8b571f..5b1e503 100644
--- a/algorithms/queues/zigzagiterator.py
+++ b/algorithms/queues/zigzagiterator.py
@@ -5,25 +5,28 @@ class ZigZagIterator:
         :type v1: List[int]
         :type v2: List[int]
         """
-        self.queue=[_ for _ in (v1,v2) if _]
+        self.queue = [_ for _ in (v1, v2) if _]
         print(self.queue)
 
     def next(self):
         """
         :rtype: int
         """
-        v=self.queue.pop(0)
-        ret=v.pop(0)
-        if v: self.queue.append(v)
+        v = self.queue.pop(0)
+        ret = v.pop(0)
+        if v:
+            self.queue.append(v)
         return ret
 
     def has_next(self):
         """
         :rtype: bool
         """
-        if self.queue: return True
+        if self.queue:
+            return True
         return False
 
+
 l1 = [1, 2]
 l2 = [3, 4, 5, 6]
 it = ZigZagIterator(l1, l2)
diff --git a/algorithms/search/__init__.py b/algorithms/search/__init__.py
index 2226e4b..3f39479 100644
--- a/algorithms/search/__init__.py
+++ b/algorithms/search/__init__.py
@@ -1,3 +1,7 @@
+"""
+Collection of search algorithms: finding the needle in a haystack.
+"""
+
 from .binary_search import *
 from .ternary_search import *
 from .first_occurrence import *
diff --git a/algorithms/search/binary_search.py b/algorithms/search/binary_search.py
index d8bccf0..6b39876 100644
--- a/algorithms/search/binary_search.py
+++ b/algorithms/search/binary_search.py
@@ -1,33 +1,51 @@
-#
-# Binary search works for a sorted array.
-# Note: The code logic is written for an array sorted in
-#  increasing order.
-#For Binary Search, T(N) = T(N/2) + O(1) // the recurrence relation
-#Apply Masters Theorem for computing Run time complexity of recurrence relations : T(N) = aT(N/b) + f(N)
-#Here, a = 1, b = 2 => log (a base b) = 1 
-# also, here f(N) = n^c log^k(n) //k = 0 & c = log (a base b) So, T(N) = O(N^c log^(k+1)N) = O(log(N))
+"""
+Binary Search
 
+Find an element in a sorted array (in ascending order).
+"""
+
+# For Binary Search, T(N) = T(N/2) + O(1) // the recurrence relation
+# Apply Masters Theorem for computing Run time complexity of recurrence relations:
+#       T(N) = aT(N/b) + f(N)
+# Here,
+#       a = 1, b = 2 => log (a base b) = 1
+# also, here
+#       f(N) = n^c log^k(n)  // k = 0 & c = log (a base b)
+# So,
+#       T(N) = O(N^c log^(k+1)N) = O(log(N))
 
 def binary_search(array, query):
-    lo, hi = 0, len(array) - 1
-    while lo <= hi:
-        mid = (hi + lo) // 2
+    """
+    Worst-case Complexity: O(log(n))
+
+    reference: https://en.wikipedia.org/wiki/Binary_search_algorithm
+    """
+
+    low, high = 0, len(array) - 1
+    while low <= high:
+        mid = (high + low) // 2
         val = array[mid]
         if val == query:
             return mid
-        elif val < query:
-            lo = mid + 1
+
+        if val < query:
+            low = mid + 1
         else:
-            hi = mid - 1
+            high = mid - 1
     return None
 
 def binary_search_recur(array, low, high, val):
+    """
+    Worst-case Complexity: O(log(n))
+
+    reference: https://en.wikipedia.org/wiki/Binary_search_algorithm
+    """
+
     if low > high:       # error case
         return -1
     mid = (low + high) // 2
     if val < array[mid]:
         return binary_search_recur(array, low, mid - 1, val)
-    elif val > array[mid]:
+    if val > array[mid]:
         return binary_search_recur(array, mid + 1, high, val)
-    else:
-        return mid
+    return mid
diff --git a/algorithms/search/find_min_rotate.py b/algorithms/search/find_min_rotate.py
index 1afc4ee..b47fd4e 100644
--- a/algorithms/search/find_min_rotate.py
+++ b/algorithms/search/find_min_rotate.py
@@ -7,6 +7,9 @@ Find the minimum element. The complexity must be O(logN)
 You may assume no duplicate exists in the array.
 """
 def find_min_rotate(array):
+    """
+    Finds the minimum element in a sorted array that has been rotated.
+    """
     low = 0
     high = len(array) - 1
     while low < high:
@@ -19,10 +22,12 @@ def find_min_rotate(array):
     return array[low]
 
 def find_min_rotate_recur(array, low, high):
+    """
+    Finds the minimum element in a sorted array that has been rotated.
+    """
     mid = (low + high) // 2
     if mid == low:
         return array[low]
-    elif array[mid] > array[high]:
+    if array[mid] > array[high]:
         return find_min_rotate_recur(array, mid + 1, high)
-    else:
-        return find_min_rotate_recur(array, low, mid)
+    return find_min_rotate_recur(array, low, mid)
diff --git a/algorithms/search/first_occurrence.py b/algorithms/search/first_occurrence.py
index 86dc89c..119ba4d 100644
--- a/algorithms/search/first_occurrence.py
+++ b/algorithms/search/first_occurrence.py
@@ -1,18 +1,23 @@
-#
-# Find first occurance of a number in a sorted array (increasing order)
-# Approach- Binary Search
-# T(n)- O(log n)
-#
+"""
+Find first occurance of a number in a sorted array (increasing order)
+Approach- Binary Search
+T(n)- O(log n)
+"""
 def first_occurrence(array, query):
-    lo, hi = 0, len(array) - 1
-    while lo <= hi:
-        mid = (lo + hi) // 2
+    """
+    Returns the index of the first occurance of the given element in an array.
+    The array has to be sorted in increasing order.
+    """
+
+    low, high = 0, len(array) - 1
+    while low <= high:
+        mid = (low + high) // 2
         #print("lo: ", lo, " hi: ", hi, " mid: ", mid)
-        if lo == hi:
+        if low == high:
             break
         if array[mid] < query:
-            lo = mid + 1
+            low = mid + 1
         else:
-            hi = mid
-    if array[lo] == query:
-      return lo
+            high = mid
+    if array[low] == query:
+        return low
diff --git a/algorithms/search/interpolation_search.py b/algorithms/search/interpolation_search.py
index 9227e1f..5b1d00a 100644
--- a/algorithms/search/interpolation_search.py
+++ b/algorithms/search/interpolation_search.py
@@ -1,4 +1,4 @@
-""" 
+"""
 Python implementation of the Interpolation Search algorithm.
 Given a sorted array in increasing order, interpolation search calculates
 the starting point of its search according to the search key.
@@ -41,14 +41,14 @@ def interpolation_search(array: List[int], search_key: int) -> int:
         pos = low + int(((search_key - array[low]) *
                          (high - low) / (array[high] - array[low])))
 
-        # search_key is found 
+        # search_key is found
         if array[pos] == search_key:
             return pos
 
         # if search_key is larger, search_key is in upper part
         if array[pos] < search_key:
             low = pos + 1
-            
+
         # if search_key is smaller, search_key is in lower part
         else:
             high = pos - 1
diff --git a/algorithms/search/jump_search.py b/algorithms/search/jump_search.py
index da8d8c3..2ec0749 100644
--- a/algorithms/search/jump_search.py
+++ b/algorithms/search/jump_search.py
@@ -1,40 +1,45 @@
+"""
+Jump Search
+
+Find an element in a sorted array.
+"""
+
 import math
 
 def jump_search(arr,target):
-    """Jump Search
-        Worst-case Complexity: O(√n) (root(n))
-        All items in list must be sorted like binary search
-
-        Find block that contains target value and search it linearly in that block
-        It returns a first target value in array
+    """
+    Worst-case Complexity: O(√n) (root(n))
+    All items in list must be sorted like binary search
 
-        reference: https://en.wikipedia.org/wiki/Jump_search
+    Find block that contains target value and search it linearly in that block
+    It returns a first target value in array
 
+    reference: https://en.wikipedia.org/wiki/Jump_search
     """
-    n = len(arr)
-    block_size = int(math.sqrt(n))
+
+    length = len(arr)
+    block_size = int(math.sqrt(length))
     block_prev = 0
     block= block_size
 
     # return -1 means that array doesn't contain target value
     # find block that contains target value
-    
-    if arr[n - 1] < target:
-        return -1  
-    while block <= n and arr[block - 1] < target:
+
+    if arr[length - 1] < target:
+        return -1
+    while block <= length and arr[block - 1] < target:
         block_prev = block
         block += block_size
 
     # find target value in block
-    
+
     while arr[block_prev] < target :
         block_prev += 1
-        if block_prev == min(block, n) :
+        if block_prev == min(block, length) :
             return -1
 
     # if there is target value in array, return it
-    
+
     if arr[block_prev] == target :
         return block_prev
-    else :
-        return -1
+    return -1
diff --git a/algorithms/search/last_occurrence.py b/algorithms/search/last_occurrence.py
index 345b423..6374625 100644
--- a/algorithms/search/last_occurrence.py
+++ b/algorithms/search/last_occurrence.py
@@ -1,16 +1,20 @@
-#
-# Find last occurance of a number in a sorted array (increasing order)
-# Approach- Binary Search
-# T(n)- O(log n)
-#
+"""
+Find last occurance of a number in a sorted array (increasing order)
+Approach- Binary Search
+T(n)- O(log n)
+"""
 def last_occurrence(array, query):
-    lo, hi = 0, len(array) - 1
-    while lo <= hi:
-        mid = (hi + lo) // 2
+    """
+    Returns the index of the last occurance of the given element in an array.
+    The array has to be sorted in increasing order.
+    """
+    low, high = 0, len(array) - 1
+    while low <= high:
+        mid = (high + low) // 2
         if (array[mid] == query and mid == len(array)-1) or \
            (array[mid] == query and array[mid+1] > query):
             return mid
-        elif (array[mid] <= query):
-            lo = mid + 1
+        if array[mid] <= query:
+            low = mid + 1
         else:
-            hi = mid - 1
+            high = mid - 1
diff --git a/algorithms/search/linear_search.py b/algorithms/search/linear_search.py
index cf57fcf..d375d77 100644
--- a/algorithms/search/linear_search.py
+++ b/algorithms/search/linear_search.py
@@ -1,12 +1,15 @@
-#
-# Linear search works in any array.
-#
-# T(n): O(n)
-#
+"""
+Linear search works in any array.
+T(n): O(n)
+"""
 
 def linear_search(array, query):
-    for i in range(len(array)):
-        if array[i] == query:
+    """
+    Find the index of the given element in the array.
+    There are no restrictions on the order of the elements in the array.
+    If the element couldn't be found, returns -1.
+    """
+    for i, value in enumerate(array):
+        if value == query:
             return i
-
     return -1
diff --git a/algorithms/search/search_insert.py b/algorithms/search/search_insert.py
index b10eb7d..279e64e 100644
--- a/algorithms/search/search_insert.py
+++ b/algorithms/search/search_insert.py
@@ -1,14 +1,18 @@
 """
-Given a sorted array and a target value, return the index if the target is
-found. If not, return the index where it would be if it were inserted in order.
-
-For example:
-[1,3,5,6], 5 -> 2
-[1,3,5,6], 2 -> 1
-[1,3,5,6], 7 -> 4
-[1,3,5,6], 0 -> 0
+Helper methods for implementing insertion sort.
 """
+
 def search_insert(array, val):
+    """
+    Given a sorted array and a target value, return the index if the target is
+    found. If not, return the index where it would be if it were inserted in order.
+
+    For example:
+    [1,3,5,6], 5 -> 2
+    [1,3,5,6], 2 -> 1
+    [1,3,5,6], 7 -> 4
+    [1,3,5,6], 0 -> 0
+    """
     low = 0
     high = len(array) - 1
     while low <=  high:
diff --git a/algorithms/search/search_rotate.py b/algorithms/search/search_rotate.py
index a92a15e..fe54745 100644
--- a/algorithms/search/search_rotate.py
+++ b/algorithms/search/search_rotate.py
@@ -37,6 +37,10 @@ There are 2 possible solution: iterative and recursion.
 Recursion helps you understand better the above algorithm explanation
 """
 def search_rotate(array, val):
+    """
+    Finds the index of the given value in an array that has been sorted in
+    ascending order and then rotated at some unknown pivot.
+    """
     low, high = 0, len(array) - 1
     while low <= high:
         mid = (low + high) // 2
@@ -58,6 +62,10 @@ def search_rotate(array, val):
 
 # Recursion technique
 def search_rotate_recur(array, low, high, val):
+    """
+    Finds the index of the given value in an array that has been sorted in
+    ascending order and then rotated at some unknown pivot.
+    """
     if low >= high:
         return -1
     mid = (low + high) // 2
@@ -66,10 +74,7 @@ def search_rotate_recur(array, low, high, val):
     if array[low] <= array[mid]:
         if array[low] <= val <= array[mid]:
             return search_rotate_recur(array, low, mid - 1, val)    # Search left
-        else:
-            return search_rotate_recur(array, mid + 1, high, val)   # Search right
-    else:
-        if array[mid] <= val <= array[high]:
-            return search_rotate_recur(array, mid + 1, high, val)   # Search right
-        else:
-            return search_rotate_recur(array, low, mid - 1, val)    # Search left
+        return search_rotate_recur(array, mid + 1, high, val)   # Search right
+    if array[mid] <= val <= array[high]:
+        return search_rotate_recur(array, mid + 1, high, val)   # Search right
+    return search_rotate_recur(array, low, mid - 1, val)    # Search left
diff --git a/algorithms/search/ternary_search.py b/algorithms/search/ternary_search.py
index b7d36fb..0d0ee1b 100644
--- a/algorithms/search/ternary_search.py
+++ b/algorithms/search/ternary_search.py
@@ -1,37 +1,42 @@
 """
-Ternary search is a divide and conquer algorithm that can be used to find an element in an array. 
-It is similar to binary search where we divide the array into two parts but in this algorithm, 
-we divide the given array into three parts and determine which has the key (searched element). 
+Ternary search is a divide and conquer algorithm that can be used to find an element in an array.
+It is similar to binary search where we divide the array into two parts but in this algorithm,
+we divide the given array into three parts and determine which has the key (searched element).
 We can divide the array into three parts by taking mid1 and mid2.
 Initially, l and r will be equal to 0 and n-1 respectively, where n is the length of the array.
-mid1 = l + (r-l)/3 
-mid2 = r – (r-l)/3 
+mid1 = l + (r-l)/3
+mid2 = r – (r-l)/3
 
 Note: Array needs to be sorted to perform ternary search on it.
 T(N) = O(log3(N))
 log3 = log base 3
 """
-def ternary_search(l, r, key, arr):
-	while r >= l:
-		
-		mid1 = l + (r-l) // 3
-		mid2 = r - (r-l) // 3
+def ternary_search(left, right, key, arr):
+    """
+    Find the given value (key) in an array sorted in ascending order.
+    Returns the index of the value if found, and -1 otherwise.
+    If the index is not in the range left..right (ie. left <= index < right) returns -1.
+    """
 
-		if key == arr[mid1]:
-			return mid1
-		if key == mid2:
-			return mid2
+    while right >= left:
+        mid1 = left + (right-left) // 3
+        mid2 = right - (right-left) // 3
 
-		if key < arr[mid1]:
+        if key == arr[mid1]:
+            return mid1
+        if key == mid2:
+            return mid2
+
+        if key < arr[mid1]:
             # key lies between l and mid1
-			r = mid1 - 1
-		elif key > arr[mid2]:
+            right = mid1 - 1
+        elif key > arr[mid2]:
             # key lies between mid2 and r
-			l = mid2 + 1
-		else:
+            left = mid2 + 1
+        else:
             # key lies between mid1 and mid2
-			l = mid1 + 1
-			r = mid2 - 1
+            left = mid1 + 1
+            right = mid2 - 1
 
-    # key not found 
-	return -1
+    # key not found
+    return -1
diff --git a/algorithms/search/two_sum.py b/algorithms/search/two_sum.py
index 4251e53..e8400fd 100644
--- a/algorithms/search/two_sum.py
+++ b/algorithms/search/two_sum.py
@@ -15,37 +15,57 @@ two_sum: using binary search
 two_sum1: using dictionary as a hash table
 two_sum2: using two pointers
 """
-# Using binary search technique
+
 def two_sum(numbers, target):
-    for i in range(len(numbers)):
-        second_val = target - numbers[i]
+    """
+    Given a list of numbers sorted in ascending order, find the indices of two
+    numbers such that their sum is the given target.
+
+    Using binary search.
+    """
+    for i, number in enumerate(numbers):
+        second_val = target - number
         low, high = i+1, len(numbers)-1
         while low <= high:
             mid = low + (high - low) // 2
             if second_val == numbers[mid]:
                 return [i + 1, mid + 1]
-            elif second_val > numbers[mid]:
+
+            if second_val > numbers[mid]:
                 low = mid + 1
             else:
                 high = mid - 1
+    return None
 
-# Using dictionary as a hash table
 def two_sum1(numbers, target):
+    """
+    Given a list of numbers, find the indices of two numbers such that their
+    sum is the given target.
+
+    Using a hash table.
+    """
     dic = {}
     for i, num in enumerate(numbers):
         if target - num in dic:
             return [dic[target - num] + 1, i + 1]
         dic[num] = i
+    return None
 
-# Using two pointers
 def two_sum2(numbers, target):
-    p1 = 0                      # pointer 1 holds from left of array numbers
-    p2 = len(numbers) - 1       # pointer 2 holds from right of array numbers
-    while p1 < p2:
-        s = numbers[p1] + numbers[p2]
-        if s == target:
-            return [p1 + 1, p2 + 1]
-        elif s > target:
-            p2 = p2 - 1
+    """
+    Given a list of numbers sorted in ascending order, find the indices of two
+    numbers such that their sum is the given target.
+
+    Using a bidirectional linear search.
+    """
+    left = 0                      # pointer 1 holds from left of array numbers
+    right = len(numbers) - 1       # pointer 2 holds from right of array numbers
+    while left < right:
+        current_sum = numbers[left] + numbers[right]
+        if current_sum == target:
+            return [left + 1, right + 1]
+
+        if current_sum > target:
+            right = right - 1
         else:
-            p1 = p1 + 1
+            left = left + 1
diff --git a/algorithms/set/find_keyboard_row.py b/algorithms/set/find_keyboard_row.py
index e00e368..c15dcda 100644
--- a/algorithms/set/find_keyboard_row.py
+++ b/algorithms/set/find_keyboard_row.py
@@ -8,6 +8,7 @@ Output: ["Alaska", "Dad"]
 
 Reference: https://leetcode.com/problems/keyboard-row/description/
 """
+
 def find_keyboard_row(words):
     """
     :type words: List[str]
diff --git a/algorithms/stack/is_consecutive.py b/algorithms/stack/is_consecutive.py
index f73ddff..44e3f90 100644
--- a/algorithms/stack/is_consecutive.py
+++ b/algorithms/stack/is_consecutive.py
@@ -18,14 +18,15 @@ second_is_consecutive: it uses a single queue as auxiliary storage
 """
 import collections
 
+
 def first_is_consecutive(stack):
     storage_stack = []
     for i in range(len(stack)):
         first_value = stack.pop()
-        if len(stack) == 0:                # Case odd number of values in stack
+        if len(stack) == 0:  # Case odd number of values in stack
             return True
         second_value = stack.pop()
-        if first_value - second_value != 1: # Not consecutive
+        if first_value - second_value != 1:  # Not consecutive
             return False
         stack.append(second_value)          # Backup second value
         storage_stack.append(first_value)
@@ -35,14 +36,15 @@ def first_is_consecutive(stack):
         stack.append(storage_stack.pop())
     return True
 
+
 def second_is_consecutive(stack):
     q = collections.deque()
     for i in range(len(stack)):
         first_value = stack.pop()
-        if len(stack) == 0:                # Case odd number of values in stack
+        if len(stack) == 0:  # Case odd number of values in stack
             return True
         second_value = stack.pop()
-        if first_value - second_value != 1: # Not consecutive
+        if first_value - second_value != 1:  # Not consecutive
             return False
         stack.append(second_value)          # Backup second value
         q.append(first_value)
diff --git a/algorithms/stack/is_sorted.py b/algorithms/stack/is_sorted.py
index 0a69d83..b3c3337 100644
--- a/algorithms/stack/is_sorted.py
+++ b/algorithms/stack/is_sorted.py
@@ -9,6 +9,8 @@ The function should return false
 bottom [1, 2, 3, 4, 5, 6] top
 The function should return true
 """
+
+
 def is_sorted(stack):
     storage_stack = []
     for i in range(len(stack)):
diff --git a/algorithms/stack/longest_abs_path.py b/algorithms/stack/longest_abs_path.py
index 67aad5a..edc4ee8 100644
--- a/algorithms/stack/longest_abs_path.py
+++ b/algorithms/stack/longest_abs_path.py
@@ -1,37 +1,37 @@
 # def lengthLongestPath(input):
-    # maxlen = 0
-    # pathlen = {0: 0}
-    # for line in input.splitlines():
-        # print("---------------")
-        # print("line:", line)
-        # name = line.strip('\t')
-        # print("name:", name)
-        # depth = len(line) - len(name)
-        # print("depth:", depth)
-        # if '.' in name:
-            # maxlen = max(maxlen, pathlen[depth] + len(name))
-        # else:
-            # pathlen[depth + 1] = pathlen[depth] + len(name) + 1
-        # print("maxlen:", maxlen)
-    # return maxlen
+#     maxlen = 0
+#     pathlen = {0: 0}
+#     for line in input.splitlines():
+#         print("---------------")
+#         print("line:", line)
+#         name = line.strip('\t')
+#         print("name:", name)
+#         depth = len(line) - len(name)
+#         print("depth:", depth)
+#         if '.' in name:
+#             maxlen = max(maxlen, pathlen[depth] + len(name))
+#         else:
+#             pathlen[depth + 1] = pathlen[depth] + len(name) + 1
+#         print("maxlen:", maxlen)
+#     return maxlen
 
 # def lengthLongestPath(input):
-    # paths = input.split("\n")
-    # level = [0] * 10
-    # maxLength = 0
-    # for path in paths:
-        # print("-------------")
-        # levelIdx = path.rfind("\t")
-        # print("Path: ", path)
-        # print("path.rfind(\\t)", path.rfind("\t"))
-        # print("levelIdx: ", levelIdx)
-        # print("level: ", level)
-        # level[levelIdx + 1] = level[levelIdx] + len(path) - levelIdx + 1
-        # print("level: ", level)
-        # if "." in path:
-            # maxLength = max(maxLength, level[levelIdx+1] - 1)
-            # print("maxlen: ", maxLength)
-    # return maxLength
+#     paths = input.split("\n")
+#     level = [0] * 10
+#     maxLength = 0
+#     for path in paths:
+#         print("-------------")
+#         levelIdx = path.rfind("\t")
+#         print("Path: ", path)
+#         print("path.rfind(\\t)", path.rfind("\t"))
+#         print("levelIdx: ", levelIdx)
+#         print("level: ", level)
+#         level[levelIdx + 1] = level[levelIdx] + len(path) - levelIdx + 1
+#         print("level: ", level)
+#         if "." in path:
+#             maxLength = max(maxLength, level[levelIdx+1] - 1)
+#             print("maxlen: ", maxLength)
+#     return maxLength
 
 def length_longest_path(input):
     """
@@ -57,9 +57,9 @@ def length_longest_path(input):
             max_len = max(max_len, curr_len-1)    # -1 is to minus one '/'
     return max_len
 
-st= "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdirectory1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"
+
+st = "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdirectory1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext"
 st2 = "a\n\tb1\n\t\tf1.txt\n\taaaaa\n\t\tf2.txt"
 print("path:", st2)
 
 print("answer:", length_longest_path(st2))
-
diff --git a/algorithms/stack/ordered_stack.py b/algorithms/stack/ordered_stack.py
index 7a30d14..94191d6 100644
--- a/algorithms/stack/ordered_stack.py
+++ b/algorithms/stack/ordered_stack.py
@@ -1,33 +1,36 @@
-#The stack remains always ordered such that the highest value is at the top and the lowest at the bottom
+# The stack remains always ordered such that the highest value
+# is at the top and the lowest at the bottom
+
 
 class OrderedStack:
-     def __init__(self):
-         self.items = []
-
-     def is_empty(self):
-         return self.items == []
-
-     def push_t(self, item):
-         self.items.append(item)
-
-     def push(self, item): #push method to maintain order when pushing new elements
-         temp_stack = OrderedStack()
-         if self.is_empty() or item > self.peek():
-             self.push_t(item)
-         else:
-             while item < self.peek() and not self.is_empty():
-                 temp_stack.push_t(self.pop())
-             self.push_t(item)
-             while not temp_stack.is_empty():
-                 self.push_t(temp_stack.pop())
-
-     def pop(self):
-         if self.is_empty():
-             raise IndexError("Stack is empty")
-         return self.items.pop()
-
-     def peek(self):
-         return self.items[len(self.items) - 1]
-
-     def size(self):
-         return len(self.items)
+    def __init__(self):
+        self.items = []
+
+    def is_empty(self):
+        return self.items == []
+
+    def push_t(self, item):
+        self.items.append(item)
+
+    # push method to maintain order when pushing new elements
+    def push(self, item):
+        temp_stack = OrderedStack()
+        if self.is_empty() or item > self.peek():
+            self.push_t(item)
+        else:
+            while item < self.peek() and not self.is_empty():
+                temp_stack.push_t(self.pop())
+            self.push_t(item)
+            while not temp_stack.is_empty():
+                self.push_t(temp_stack.pop())
+
+    def pop(self):
+        if self.is_empty():
+            raise IndexError("Stack is empty")
+        return self.items.pop()
+
+    def peek(self):
+        return self.items[len(self.items) - 1]
+
+    def size(self):
+        return len(self.items)
diff --git a/algorithms/stack/remove_min.py b/algorithms/stack/remove_min.py
index 1cd8fc6..ce635a4 100644
--- a/algorithms/stack/remove_min.py
+++ b/algorithms/stack/remove_min.py
@@ -8,6 +8,8 @@ After remove_min(stack):
 bottom [2, 8, 3, 7, 3] top
 
 """
+
+
 def remove_min(stack):
     storage_stack = []
     if len(stack) == 0:  # Stack is empty
diff --git a/algorithms/stack/simplify_path.py b/algorithms/stack/simplify_path.py
index fed4385..09f9de8 100644
--- a/algorithms/stack/simplify_path.py
+++ b/algorithms/stack/simplify_path.py
@@ -7,8 +7,9 @@ path = "/a/./b/../../c/", => "/c"
 
 * Did you consider the case where path = "/../"?
     In this case, you should return "/".
-* Another corner case is the path might contain multiple slashes '/' together, such as "/home//foo/".
-    In this case, you should ignore redundant slashes and return "/home/foo".
+* Another corner case is the path might contain multiple slashes '/' together,
+    such as "/home//foo/". In this case, you should ignore redundant
+    slashes and return "/home/foo".
 """
 def simplify_path(path):
     """
diff --git a/algorithms/stack/stack.py b/algorithms/stack/stack.py
index 216c264..a79aec4 100644
--- a/algorithms/stack/stack.py
+++ b/algorithms/stack/stack.py
@@ -8,12 +8,12 @@ pop() removes the top item from the stack.
    It needs no parameters and returns the item. The stack is modified.
 peek() returns the top item from the stack but does not remove it.
    It needs no parameters. The stack is not modified.
-isEmpty() tests to see whether the stack is empty.
+is_empty() tests to see whether the stack is empty.
    It needs no parameters and returns a boolean value.
-size() returns the number of items on the stack.
-   It needs no parameters and returns an integer.
 """
 from abc import ABCMeta, abstractmethod
+
+
 class AbstractStack(metaclass=ABCMeta):
     """Abstract Class for Stacks."""
     def __init__(self):
@@ -72,7 +72,7 @@ class ArrayStack(AbstractStack):
 
     def pop(self):
         if self.is_empty():
-            raise IndexError("stack is empty")
+            raise IndexError("Stack is empty")
         value = self._array[self._top]
         self._top -= 1
         return value
@@ -80,7 +80,7 @@ class ArrayStack(AbstractStack):
     def peek(self):
         """returns the current top element of the stack."""
         if self.is_empty():
-            raise IndexError("stack is empty")
+            raise IndexError("Stack is empty")
         return self._array[self._top]
 
     def _expand(self):
diff --git a/algorithms/stack/stutter.py b/algorithms/stack/stutter.py
index 3031499..ceb6451 100644
--- a/algorithms/stack/stutter.py
+++ b/algorithms/stack/stutter.py
@@ -13,6 +13,7 @@ second_stutter: it uses a single queue as auxiliary storage
 """
 import collections
 
+
 def first_stutter(stack):
     storage_stack = []
     for i in range(len(stack)):
@@ -24,6 +25,7 @@ def first_stutter(stack):
 
     return stack
 
+
 def second_stutter(stack):
     q = collections.deque()
     # Put all values into queue from stack
diff --git a/algorithms/stack/switch_pairs.py b/algorithms/stack/switch_pairs.py
index f5db228..d8b22dc 100644
--- a/algorithms/stack/switch_pairs.py
+++ b/algorithms/stack/switch_pairs.py
@@ -4,13 +4,15 @@ switches successive pairs of numbers starting at the bottom of the stack.
 
 For example, if the stack initially stores these values:
 bottom [3, 8, 17, 9, 1, 10] top
-Your function should switch the first pair (3, 8), the second pair (17, 9), ...:
+Your function should switch the first pair (3, 8),
+the second pair (17, 9), ...:
 bottom [8, 3, 9, 17, 10, 1] top
 
 if there are an odd number of values in the stack, the value at the top of the
 stack is not moved: For example:
 bottom [3, 8, 17, 9, 1] top
-It would again switch pairs of values, but the value at the top of the stack (1)
+It would again switch pairs of values, but the value at the
+top of the stack (1)
 would not be moved
 bottom [8, 3, 9, 17, 1] top
 
@@ -20,6 +22,7 @@ second_switch_pairs: it uses a single queue as auxiliary storage
 """
 import collections
 
+
 def first_switch_pairs(stack):
     storage_stack = []
     for i in range(len(stack)):
@@ -36,6 +39,7 @@ def first_switch_pairs(stack):
         stack.append(first)
     return stack
 
+
 def second_switch_pairs(stack):
     q = collections.deque()
     # Put all values into queue from stack
diff --git a/algorithms/stack/valid_parenthesis.py b/algorithms/stack/valid_parenthesis.py
index b62ac02..8fdb861 100644
--- a/algorithms/stack/valid_parenthesis.py
+++ b/algorithms/stack/valid_parenthesis.py
@@ -6,6 +6,8 @@ determine if the input string is valid.
 The brackets must close in the correct order,
 "()" and "()[]{}" are all valid but "(]" and "([)]" are not.
 """
+
+
 def is_valid(s: str) -> bool:
     stack = []
     dic = {")": "(",
diff --git a/algorithms/streaming/misra_gries.py b/algorithms/streaming/misra_gries.py
index 3133909..58fd84b 100644
--- a/algorithms/streaming/misra_gries.py
+++ b/algorithms/streaming/misra_gries.py
@@ -1,11 +1,17 @@
 
 """
 Implementation of the Misra-Gries algorithm.
-Given a list of items and a value k, it returns the every item in the list that appears at least n/k times, where n is the length of the array
-By default, k is set to 2, solving the majority problem. 
-For the majority problem, this algorithm only guarantees that if there is an element that appears more than n/2 times, it will be outputed. If there
-is no such element, any arbitrary element is returned by the algorithm. Therefore, we need to iterate through again at the end. But since we have filtred
-out the suspects, the memory complexity is significantly lower than it would be to create counter for every element in the list.
+Given a list of items and a value k, it returns the every item in the list
+that appears at least n/k times, where n is the length of the array
+
+By default, k is set to 2, solving the majority problem.
+
+For the majority problem, this algorithm only guarantees that if there is
+an element that appears more than n/2 times, it will be outputed. If there
+is no such element, any arbitrary element is returned by the algorithm.
+Therefore, we need to iterate through again at the end. But since we have filtred
+out the suspects, the memory complexity is significantly lower than
+it would be to create counter for every element in the list.
 
 For example:
 Input misras_gries([1,4,4,4,5,4,4])
@@ -17,33 +23,38 @@ Output {'0':4,'1':3}
 Input misras_gries([0,0,0,1,1,1]
 Output None
 """
+
 def misras_gries(array,k=2):
-  keys = {}
-  for i in range(len(array)):
-    val = str(array[i])
-    if val in keys:
-      keys[val] = keys[val] + 1
-
-    elif len(keys) < k - 1:
-      keys[val] = 1
-
-    else:
-      for key in list(keys):
-        keys[key] = keys[key] - 1
-        if keys[key] == 0:
-          del keys[key]
-
-  suspects =  keys.keys()
-  frequencies = {}
-  for suspect in suspects:
-    freq = _count_frequency(array,int(suspect))
-    if freq >= len(array) / k:
-      frequencies[suspect] = freq
-
-  return frequencies if len(frequencies) > 0 else None
-  
+    """Misra-Gries algorithm
 
-def _count_frequency(array,element):
-  return array.count(element)
+    Keyword arguments:
+    array -- list of integers
+    k -- value of k (default 2)
+    """
+    keys = {}
+    for i in array:
+        val = str(i)
+        if val in keys:
+            keys[val] = keys[val] + 1
+
+        elif len(keys) < k - 1:
+            keys[val] = 1
 
-      
+        else:
+            for key in list(keys):
+                keys[key] = keys[key] - 1
+                if keys[key] == 0:
+                    del keys[key]
+
+    suspects =  keys.keys()
+    frequencies = {}
+    for suspect in suspects:
+        freq = _count_frequency(array,int(suspect))
+        if freq >= len(array) / k:
+            frequencies[suspect] = freq
+
+    return frequencies if len(frequencies) > 0 else None
+
+
+def _count_frequency(array,element):
+    return array.count(element)
diff --git a/algorithms/streaming/one_sparse_recovery.py b/algorithms/streaming/one_sparse_recovery.py
index 084a9f7..18a2641 100644
--- a/algorithms/streaming/one_sparse_recovery.py
+++ b/algorithms/streaming/one_sparse_recovery.py
@@ -1,61 +1,68 @@
-""" Non-negative 1-sparse recovery problem. This algorithm assumes we have a non negative dynamic stream.
-Given a stream of tuples, where each tuple contains a number and a sign (+/-), it check if the stream is 1-sparse, meaning if the elements 
-in the stream cancel eacheother out in such a way that ther is only a unique number at the end. 
+"""
+Non-negative 1-sparse recovery problem.
+This algorithm assumes we have a non negative dynamic stream.
+
+Given a stream of tuples, where each tuple contains a number and a sign (+/-), it check if the
+stream is 1-sparse, meaning if the elements in the stream cancel eacheother out in such
+a way that ther is only a unique number at the end.
 
 Examples:
-#1 
+#1
 Input:  [(4,'+'), (2,'+'),(2,'-'),(4,'+'),(3,'+'),(3,'-')],
-Output: 4 
+Output: 4
 Comment: Since 2 and 3 gets removed.
-#2 
+#2
 Input:  [(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'+')]
-Output: 2 
+Output: 2
 Comment: No other numbers present
 #3
 Input:  [(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'+'),(1,'+')]
-Output: None 
+Output: None
 Comment: Not 1-sparse
 """
 
 def one_sparse(array):
-  sum_signs = 0 
-  bitsum = [0]*32 
-  sum_values = 0 
-  for val,sign in array: 
-    if sign == "+": 
-      sum_signs += 1
-      sum_values += val
+    """1-sparse algorithm
+
+    Keyword arguments:
+    array -- stream of tuples
+    """
+    sum_signs = 0
+    bitsum = [0]*32
+    sum_values = 0
+    for val,sign in array:
+        if sign == "+":
+            sum_signs += 1
+            sum_values += val
+        else:
+            sum_signs -= 1
+            sum_values -= val
+
+        _get_bit_sum(bitsum,val,sign)
+
+    if sum_signs > 0 and _check_every_number_in_bitsum(bitsum,sum_signs):
+        return int(sum_values/sum_signs)
     else:
-      sum_signs -= 1 
-      sum_values -= val
-    
-    _get_bit_sum(bitsum,val,sign)
-  
-  if sum_signs > 0 and _check_every_number_in_bitsum(bitsum,sum_signs):
-    return int(sum_values/sum_signs)
-  else:
-    return None
-   
+        return None
+
 #Helper function to check that every entry in the list is either 0 or  the same as the
 #sum of signs
 def _check_every_number_in_bitsum(bitsum,sum_signs):
-  for val in bitsum: 
-    if val != 0 and val != sum_signs : 
-      return False
-  return True
+    for val in bitsum:
+        if val != 0 and val != sum_signs :
+            return False
+    return True
 
 # Adds bit representation value to bitsum array
 def _get_bit_sum(bitsum,val,sign):
-  i = 0 
-  if sign == "+":
-    while(val):
-      bitsum[i] += val & 1
-      i +=1
-      val >>=1
-  else :
-    while(val):
-      bitsum[i] -= val & 1
-      i +=1
-      val >>=1
-
-
+    i = 0
+    if sign == "+":
+        while val:
+            bitsum[i] += val & 1
+            i +=1
+            val >>=1
+    else :
+        while val:
+            bitsum[i] -= val & 1
+            i +=1
+            val >>=1
diff --git a/algorithms/strings/knuth_morris_pratt.py b/algorithms/strings/knuth_morris_pratt.py
index 0bdf4d5..e1953a2 100644
--- a/algorithms/strings/knuth_morris_pratt.py
+++ b/algorithms/strings/knuth_morris_pratt.py
@@ -1,13 +1,23 @@
-"""
-Given two strings text and pattern,
-return the list of  start indexes in text that matches with the pattern
-using knuth_morris_pratt algorithm.
-If idx is in the list, text[idx : idx + M] matches with pattern.
-Time complexity : O(N+M)
-N and M is the length of text and pattern, respectively.
-"""
+from typing import Sequence, List
 
-def knuth_morris_pratt(text, pattern):
+def knuth_morris_pratt(text : Sequence, pattern : Sequence) -> List[int]:
+    """
+    Given two strings text and pattern, return the list of start indexes in text that matches with the pattern
+    using knuth_morris_pratt algorithm.
+
+    Args:
+        text: Text to search
+        pattern: Pattern to search in the text
+    Returns:
+        List of indices of patterns found
+
+    Example:
+        >>> knuth_morris_pratt('hello there hero!', 'he')
+        [0, 7, 12]
+
+    If idx is in the list, text[idx : idx + M] matches with pattern.
+    Time complexity of the algorithm is O(N+M), with N and M the length of text and pattern, respectively.
+    """
     n = len(text)
     m = len(pattern)
     pi = [0 for i in range(m)]
diff --git a/algorithms/tree/avl/avl.py b/algorithms/tree/avl/avl.py
index 102fec8..e3cbecb 100644
--- a/algorithms/tree/avl/avl.py
+++ b/algorithms/tree/avl/avl.py
@@ -1,3 +1,4 @@
+""" Imports TreeNodes"""
 from tree.tree import TreeNode
 
 
@@ -17,9 +18,9 @@ class AvlTree(object):
         Insert new key into node
         """
         # Create new node
-        n = TreeNode(key)
+        node = TreeNode(key)
         if not self.node:
-            self.node = n
+            self.node = node
             self.node.left = AvlTree()
             self.node.right = AvlTree()
         elif key < self.node.val:
@@ -65,7 +66,8 @@ class AvlTree(object):
                 if self.node.right:
                     self.node.right.update_heights()
 
-            self.height = 1 + max(self.node.left.height, self.node.right.height)
+            self.height = 1 + max(self.node.left.height,
+                                  self.node.right.height)
         else:
             self.height = -1
 
diff --git a/algorithms/tree/b_tree.py b/algorithms/tree/b_tree.py
index bedf31b..1e68b43 100644
--- a/algorithms/tree/b_tree.py
+++ b/algorithms/tree/b_tree.py
@@ -3,7 +3,8 @@ B-tree is used to disk operations. Each node (except root) contains
 at least t-1 keys (t children) and at most 2*t - 1 keys (2*t children)
 where t is the degree of b-tree. It is not a kind of typical bst tree, because
 this tree grows up.
-B-tree is balanced which means that the difference between height of left subtree and right subtree is at most 1.
+B-tree is balanced which means that the difference between height of left
+subtree and right subtree is at most 1.
 
 Complexity
     n - number of elements
@@ -18,6 +19,8 @@ Complexity
 
 
 class Node:
+    """ Class of Node"""
+
     def __init__(self):
         # self.is_leaf = is_leaf
         self.keys = []
@@ -28,13 +31,16 @@ class Node:
 
     @property
     def is_leaf(self):
+        """ Return if it is a leaf"""
         return len(self.children) == 0
 
 
 class BTree:
-    def __init__(self, t=2):
-        self.min_numbers_of_keys = t - 1
-        self.max_number_of_keys = 2 * t - 1
+    """ Class of BTree """
+
+    def __init__(self, t_val=2):
+        self.min_numbers_of_keys = t_val - 1
+        self.max_number_of_keys = 2 * t_val - 1
 
         self.root = Node()
 
@@ -55,7 +61,8 @@ class BTree:
         parent.children.insert(child_index + 1, new_right_child)
 
     def insert_key(self, key):
-        if len(self.root.keys) >= self.max_number_of_keys:  # overflow, tree increases in height
+        """ overflow, tree increases in height """
+        if len(self.root.keys) >= self.max_number_of_keys:
             new_root = Node()
             new_root.children.append(self.root)
             self.root = new_root
@@ -72,26 +79,27 @@ class BTree:
         if node.is_leaf:
             node.keys.insert(i + 1, key)
         else:
-            if len(node.children[i + 1].keys) >= self.max_number_of_keys:  # overflow
+            # overflow
+            if len(node.children[i + 1].keys) >= self.max_number_of_keys:
                 self._split_child(node, i + 1)
-                if node.keys[i + 1] < key:  # decide which child is going to have a new key
+                # decide which child is going to have a new key
+                if node.keys[i + 1] < key:
                     i += 1
 
             self._insert_to_nonfull_node(node.children[i + 1], key)
 
     def find(self, key) -> bool:
+        """ Finds key """
         current_node = self.root
         while True:
             i = len(current_node.keys) - 1
             while i >= 0 and current_node.keys[i] > key:
                 i -= 1
-
             if i >= 0 and current_node.keys[i] == key:
                 return True
-            elif current_node.is_leaf:
+            if current_node.is_leaf:
                 return False
-            else:
-                current_node = current_node.children[i + 1]
+            current_node = current_node.children[i + 1]
 
     def remove_key(self, key):
         self._remove_key(self.root, key)
@@ -101,10 +109,8 @@ class BTree:
             key_index = node.keys.index(key)
             if node.is_leaf:
                 node.keys.remove(key)
-                return True
             else:
                 self._remove_from_nonleaf_node(node, key_index)
-
             return True
 
         except ValueError:  # key not found in node
@@ -114,7 +120,8 @@ class BTree:
             else:
                 i = 0
                 number_of_keys = len(node.keys)
-                while i < number_of_keys and key > node.keys[i]:  # decide in which subtree may be key
+                # decide in which subtree may be key
+                while i < number_of_keys and key > node.keys[i]:
                     i += 1
 
                 action_performed = self._repair_tree(node, i)
@@ -125,15 +132,16 @@ class BTree:
 
     def _repair_tree(self, node: Node, child_index: int) -> bool:
         child = node.children[child_index]
-        if self.min_numbers_of_keys < len(child.keys) <= self.max_number_of_keys:  # The leaf/node is correct
+        # The leaf/node is correct
+        if self.min_numbers_of_keys < len(child.keys) <= self.max_number_of_keys:
             return False
 
         if child_index > 0 and len(node.children[child_index - 1].keys) > self.min_numbers_of_keys:
             self._rotate_right(node, child_index)
             return True
 
-        if (child_index < len(node.children) - 1 and
-                len(node.children[child_index + 1].keys) > self.min_numbers_of_keys):  # 0 <-- 1
+        if (child_index < len(node.children) - 1
+                and len(node.children[child_index + 1].keys) > self.min_numbers_of_keys):  # 0 <-- 1
             self._rotate_left(node, child_index)
             return True
 
@@ -156,8 +164,10 @@ class BTree:
         parent_node.keys[child_index] = new_parent_key
 
         if not parent_node.children[child_index + 1].is_leaf:
-            ownerless_child = parent_node.children[child_index + 1].children.pop(0)
-            # make ownerless_child as a new biggest child (with highest key) -> transfer from right subtree to left subtree
+            ownerless_child = parent_node.children[child_index
+                                                   + 1].children.pop(0)
+            # make ownerless_child as a new biggest child (with highest key)
+            # -> transfer from right subtree to left subtree
             parent_node.children[child_index].children.append(ownerless_child)
 
     def _rotate_right(self, parent_node: Node, child_index: int):
@@ -170,9 +180,12 @@ class BTree:
         parent_node.keys[child_index - 1] = new_parent_key
 
         if not parent_node.children[child_index - 1].is_leaf:
-            ownerless_child = parent_node.children[child_index - 1].children.pop()
-            # make ownerless_child as a new lowest child (with lowest key) -> transfer from left subtree to right subtree
-            parent_node.children[child_index].children.insert(0, ownerless_child)
+            ownerless_child = parent_node.children[child_index
+                                                   - 1].children.pop()
+            # make ownerless_child as a new lowest child (with lowest key)
+            # -> transfer from left subtree to right subtree
+            parent_node.children[child_index].children.insert(
+                0, ownerless_child)
 
     def _merge(self, parent_node: Node, to_merge_index: int, transfered_child_index: int):
         from_merge_node = parent_node.children.pop(transfered_child_index)
@@ -191,9 +204,11 @@ class BTree:
         key = node.keys[key_index]
         left_subtree = node.children[key_index]
         if len(left_subtree.keys) > self.min_numbers_of_keys:
-            largest_key = self._find_largest_and_delete_in_left_subtree(left_subtree)
+            largest_key = self._find_largest_and_delete_in_left_subtree(
+                left_subtree)
         elif len(node.children[key_index + 1].keys) > self.min_numbers_of_keys:
-            largest_key = self._find_largest_and_delete_in_right_subtree(node.children[key_index + 1])
+            largest_key = self._find_largest_and_delete_in_right_subtree(
+                node.children[key_index + 1])
         else:
             self._merge(node, key_index, key_index + 1)
             return self._remove_key(node, key)
@@ -217,7 +232,8 @@ class BTree:
         else:
             ch_index = 0
             self._repair_tree(node, ch_index)
-            largest_key_in_subtree = self._find_largest_and_delete_in_right_subtree(node.children[0])
+            largest_key_in_subtree = self._find_largest_and_delete_in_right_subtree(
+                node.children[0])
             # self._repair_tree(node, ch_index)
             return largest_key_in_subtree
 
diff --git a/algorithms/tree/is_balanced.py b/algorithms/tree/is_balanced.py
index 004daaa..3910e1b 100644
--- a/algorithms/tree/is_balanced.py
+++ b/algorithms/tree/is_balanced.py
@@ -15,7 +15,7 @@ def __get_depth(root):
     """
     if root is None:
         return 0
-    left  = __get_depth(root.left)
+    left = __get_depth(root.left)
     right = __get_depth(root.right)
     if abs(left-right) > 1 or -1 in [left, right]:
         return -1
@@ -28,7 +28,8 @@ def __get_depth(root):
 #     """
 #     left = max_height(root.left)
 #     right = max_height(root.right)
-#     return abs(left-right) <= 1 and is_balanced(root.left) and is_balanced(root.right)
+#     return abs(left-right) <= 1 and is_balanced(root.left) and
+#     is_balanced(root.right)
 
 # def max_height(root):
 #     if root is None:
diff --git a/algorithms/tree/same_tree.py b/algorithms/tree/same_tree.py
index 7e87e7e..c2805a8 100644
--- a/algorithms/tree/same_tree.py
+++ b/algorithms/tree/same_tree.py
@@ -7,11 +7,11 @@ structurally identical and the nodes have the same value.
 """
 
 
-def is_same_tree(p, q):
-    if p is None and q is None:
+def is_same_tree(tree_p, tree_q):
+    if tree_p is None and tree_q is None:
         return True
-    if p is not None and q is not None and p.val == q.val:
-        return is_same_tree(p.left, q.left) and is_same_tree(p.right, q.right)
+    if tree_p is not None and tree_q is not None and tree_p.val == tree_q.val:
+        return is_same_tree(tree_p.left, tree_q.left) and is_same_tree(tree_p.right, tree_q.right)
     return False
 
 # Time Complexity O(min(N,M))
diff --git a/algorithms/tree/traversal/inorder.py b/algorithms/tree/traversal/inorder.py
index 17cadaf..ff1798e 100644
--- a/algorithms/tree/traversal/inorder.py
+++ b/algorithms/tree/traversal/inorder.py
@@ -2,6 +2,7 @@
 Time complexity : O(n)
 '''
 
+
 class Node:
 
     def __init__(self, val, left=None, right=None):
@@ -11,6 +12,7 @@ class Node:
 
 
 def inorder(root):
+    """ In order function """
     res = []
     if not root:
         return res
@@ -24,17 +26,18 @@ def inorder(root):
         root = root.right
     return res
 
-# Recursive Implementation
 def inorder_rec(root, res=None):
+    """ Recursive Implementation """
     if root is None:
         return []
-    if res is None: 
+    if res is None:
         res = []
     inorder_rec(root.left, res)
     res.append(root.val)
     inorder_rec(root.right, res)
     return res
 
+
 if __name__ == '__main__':
     n1 = Node(100)
     n2 = Node(50)
@@ -46,6 +49,6 @@ if __name__ == '__main__':
     n1.left, n1.right = n2, n3
     n2.left, n2.right = n4, n5
     n3.left, n3.right = n6, n7
-    
-    assert inorder(n1)     == [25, 50, 75, 100, 125, 150, 175]
+
+    assert inorder(n1) == [25, 50, 75, 100, 125, 150, 175]
     assert inorder_rec(n1) == [25, 50, 75, 100, 125, 150, 175]
diff --git a/algorithms/tree/traversal/preorder.py b/algorithms/tree/traversal/preorder.py
index 45346ba..c290371 100644
--- a/algorithms/tree/traversal/preorder.py
+++ b/algorithms/tree/traversal/preorder.py
@@ -2,7 +2,9 @@
 Time complexity : O(n)
 '''
 
+
 class Node:
+    """ This is a class of Node """
 
     def __init__(self, val, left=None, right=None):
         self.val = val
@@ -11,6 +13,7 @@ class Node:
 
 
 def preorder(root):
+    """ Function to Preorder """
     res = []
     if not root:
         return res
@@ -25,8 +28,8 @@ def preorder(root):
             stack.append(root.left)
     return res
 
-# Recursive Implementation
 def preorder_rec(root, res=None):
+    """ Recursive Implementation """
     if root is None:
         return []
     if res is None:
@@ -35,4 +38,3 @@ def preorder_rec(root, res=None):
     preorder_rec(root.left, res)
     preorder_rec(root.right, res)
     return res
-
diff --git a/algorithms/unionfind/count_islands.py b/algorithms/unionfind/count_islands.py
index 56bed5b..ca94aa0 100644
--- a/algorithms/unionfind/count_islands.py
+++ b/algorithms/unionfind/count_islands.py
@@ -1,78 +1,126 @@
 """
-A 2d grid map of m rows and n columns is initially filled with water.
-We may perform an addLand operation which turns the water at position
-(row, col) into a land. Given a list of positions to operate,
-count the number of islands after each addLand operation.
-An island is surrounded by water and is formed by connecting adjacent
-lands horizontally or vertically.
-You may assume all four edges of the grid are all surrounded by water.
-
-Given m = 3, n = 3, positions = [[0,0], [0,1], [1,2], [2,1]].
-Initially, the 2d grid grid is filled with water.
-(Assume 0 represents water and 1 represents land).
-
-0 0 0
-0 0 0
-0 0 0
-Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land.
-
-1 0 0
-0 0 0   Number of islands = 1
-0 0 0
-Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land.
-
-1 1 0
-0 0 0   Number of islands = 1
-0 0 0
-Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land.
-
-1 1 0
-0 0 1   Number of islands = 2
-0 0 0
-Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land.
-
-1 1 0
-0 0 1   Number of islands = 3
-0 1 0
+Defines the Union-Find (or Disjoint Set) data structure.
+
+A disjoint set is made up of a number of elements contained within another
+number of sets. Initially, elements are put in their own set, but sets may be
+merged using the `unite` operation. We can check if two elements are in the
+same seet by comparing their `root`s. If they are identical, the two elements
+are in the same set. All operations can be completed in O(a(n)) where `n` is
+the number of elements, and `a` the inverse ackermann function. a(n) grows so
+slowly that it might as well be constant for any conceivable `n`.
 """
 
+class Union:
+    """
+    A Union-Find data structure.
+
+    Consider the following sequence of events:
+    Starting with the elements 1, 2, 3, and 4:
+
+        {1} {2} {3} {4}
+
+    Initally they all live in their own sets, which means that `root(1) !=
+    root(3)`, however, if we call `unite(1, 3)` we would then have the following:
+
+        {1,3} {2} {4}
+
+    Now we have `root(1) == root(3)`, but it is still the case that `root(1) != root(2)`.
+
+    We may call `unite(2, 4)` and end up with:
+
+        {1,3} {2,4}
+
+    Again we have `root(1) != root(2)`. But after `unite(3, 4)` we end up with:
+
+        {1,2,3,4}
+
+    which results in `root(1) == root(2)`.
+    """
 
-class Solution(object):
-    def num_islands2(self, m, n, positions):
-        ans = []
-        islands = Union()
-        for p in map(tuple, positions):
-            islands.add(p)
-            for dp in (0, 1), (0, -1), (1, 0), (-1, 0):
-                q = (p[0] + dp[0], p[1] + dp[1])
-                if q in islands.id:
-                    islands.unite(p, q)
-            ans += [islands.count]
-        return ans
-
-class Union(object):
     def __init__(self):
-        self.id = {}
-        self.sz = {}
+        self.parents = {}
+        self.size = {}
         self.count = 0
 
-    def add(self, p):
-        self.id[p] = p
-        self.sz[p] = 1
+    def add(self, element):
+        """
+        Add a new set containing the single element
+        """
+
+        self.parents[element] = element
+        self.size[element] = 1
         self.count += 1
 
-    def root(self, i):
-        while i != self.id[i]:
-            self.id[i] = self.id[self.id[i]]
-            i = self.id[i]
-        return i
+    def root(self, element):
+        """
+        Find the root element which represents the set of a given element.
+        That is, all elements that are in the same set will return the same
+        root element.
+        """
+
+        while element != self.parents[element]:
+            self.parents[element] = self.parents[self.parents[element]]
+            element = self.parents[element]
+        return element
+
+    def unite(self, element1, element2):
+        """
+        Finds the sets which contains the two elements and merges them into a
+        single set.
+        """
 
-    def unite(self, p, q):
-        i, j = self.root(p), self.root(q)
-        if i == j:
+        root1, root2 = self.root(element1), self.root(element2)
+        if root1 == root2:
             return
-        if self.sz[i] > self.sz[j]:
-            i, j = j, i
-        self.id[i] = j
-        self.sz[j] += self.sz[i]
+        if self.size[root1] > self.size[root2]:
+            root1, root2 = root2, root1
+        self.parents[root1] = root2
+        self.size[root2] += self.size[root1]
         self.count -= 1
+
+def num_islands(positions):
+    """
+    Given a list of positions to operate, count the number of islands
+    after each addLand operation. An island is surrounded by water and is
+    formed by connecting adjacent lands horizontally or vertically. You may
+    assume all four edges of the grid are all surrounded by water.
+
+    Given a 3x3 grid, positions = [[0,0], [0,1], [1,2], [2,1]].
+    Initially, the 2d grid grid is filled with water.
+    (Assume 0 represents water and 1 represents land).
+
+    0 0 0
+    0 0 0
+    0 0 0
+    Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land.
+
+    1 0 0
+    0 0 0   Number of islands = 1
+    0 0 0
+    Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land.
+
+    1 1 0
+    0 0 0   Number of islands = 1
+    0 0 0
+    Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land.
+
+    1 1 0
+    0 0 1   Number of islands = 2
+    0 0 0
+    Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land.
+
+    1 1 0
+    0 0 1   Number of islands = 3
+    0 1 0
+    """
+
+    ans = []
+    islands = Union()
+    for position in map(tuple, positions):
+        islands.add(position)
+        for delta in (0, 1), (0, -1), (1, 0), (-1, 0):
+            adjacent = (position[0] + delta[0], position[1] + delta[1])
+            if adjacent in islands.parents:
+                islands.unite(position, adjacent)
+        ans += [islands.count]
+    return ans
diff --git a/docs/source/conf.py b/docs/source/conf.py
index b6c0c83..768277d 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -32,13 +32,13 @@ from recommonmark.parser import CommonMarkParser
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 extensions = ['sphinx.ext.autodoc',
-    'sphinx.ext.doctest',
-    'sphinx.ext.todo',
-    'sphinx.ext.coverage',
-    'sphinx.ext.mathjax',
-    'sphinx.ext.ifconfig',
-    'sphinx.ext.viewcode',
-    'sphinx.ext.githubpages']
+              'sphinx.ext.doctest',
+              'sphinx.ext.todo',
+              'sphinx.ext.coverage',
+              'sphinx.ext.mathjax',
+              'sphinx.ext.ifconfig',
+              'sphinx.ext.viewcode',
+              'sphinx.ext.githubpages']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
diff --git a/setup.py b/setup.py
index 56099a5..c5bb201 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,4 @@
-import os
 import io
-import re
 from setuptools import find_packages, setup
 
 


Test patch:
diff --git a/algorithms/graph/all_pairs_shortest_path.py b/algorithms/graph/all_pairs_shortest_path.py
index 46f3b7c..d8e6fec 100644
--- a/algorithms/graph/all_pairs_shortest_path.py
+++ b/algorithms/graph/all_pairs_shortest_path.py
@@ -7,22 +7,36 @@ Time complexity : O(E^3)
 
 example
 
-a = [[0, 0.1, 0.101, 0.142, 0.277], [0.465, 0, 0.191, 0.192, 0.587], [0.245, 0.554, 0, 0.333, 0.931], [1.032, 0.668, 0.656, 0, 0.151], [0.867, 0.119, 0.352, 0.398, 0]]
+a = [[0    , 0.1  , 0.101, 0.142, 0.277],
+     [0.465, 0    , 0.191, 0.192, 0.587],
+     [0.245, 0.554, 0    , 0.333, 0.931],
+     [1.032, 0.668, 0.656, 0    , 0.151],
+     [0.867, 0.119, 0.352, 0.398, 0]]
 
-result 
+result
 
-[[0, 0.1, 0.101, 0.142, 0.277], [0.436, 0, 0.191, 0.192, 0.34299999999999997], [0.245, 0.345, 0, 0.333, 0.484], [0.706, 0.27, 0.46099999999999997, 0, 0.151], [0.5549999999999999, 0.119, 0.31, 0.311, 0]]
+[[0    , 0.1  , 0.101, 0.142, 0.277],
+ [0.436, 0    , 0.191, 0.192, 0.343],
+ [0.245, 0.345, 0    , 0.333, 0.484],
+ [0.706, 0.27 , 0.461, 0    , 0.151],
+ [0.555, 0.119, 0.31 , 0.311, 0]]
 
 """
 import copy
 
 def all_pairs_shortest_path(adjacency_matrix):
+    """
+    Given a matrix of the edge weights between respective nodes, returns a
+    matrix containing the shortest distance distance between the two nodes.
+    """
+
     new_array = copy.deepcopy(adjacency_matrix)
 
-    for k in range(len(new_array)):
-        for i in range(len(new_array)):
-            for j in range(len(new_array)):
+    size = len(new_array)
+    for k in range(size):
+        for i in range(size):
+            for j in range(size):
                 if new_array[i][j] > new_array[i][k] + new_array[k][j]:
-                    new_array[i][j] = new_array[i][k] + new_array[k][j]           
-    
-    return new_array
\ No newline at end of file
+                    new_array[i][j] = new_array[i][k] + new_array[k][j]
+
+    return new_array
diff --git a/algorithms/search/next_greatest_letter.py b/algorithms/search/next_greatest_letter.py
index 5abe001..26ec853 100644
--- a/algorithms/search/next_greatest_letter.py
+++ b/algorithms/search/next_greatest_letter.py
@@ -26,17 +26,17 @@ Reference: https://leetcode.com/problems/find-smallest-letter-greater-than-targe
 
 import bisect
 
-"""
-Using bisect libarary
-"""
 def next_greatest_letter(letters, target):
+    """
+    Using bisect libarary
+    """
     index = bisect.bisect(letters, target)
     return letters[index % len(letters)]
 
-"""
-Using binary search: complexity O(logN)
-"""
 def next_greatest_letter_v1(letters, target):
+    """
+    Using binary search: complexity O(logN)
+    """
     if letters[0] > target:
         return letters[0]
     if letters[len(letters) - 1] <= target:
@@ -48,12 +48,12 @@ def next_greatest_letter_v1(letters, target):
             right = mid - 1
         else:
             left = mid + 1
-    return letters[left]    
+    return letters[left]
 
-"""
-Brute force: complexity O(N)
-"""
 def next_greatest_letter_v2(letters, target):
+    """
+    Brute force: complexity O(N)
+    """
     for index in letters:
         if index > target:
             return index
diff --git a/tests/test_array.py b/tests/test_array.py
index c02b275..eaabfc7 100644
--- a/tests/test_array.py
+++ b/tests/test_array.py
@@ -3,7 +3,8 @@ from algorithms.arrays import (
     flatten_iter, flatten,
     garage,
     josephus,
-    longest_non_repeat_v1, longest_non_repeat_v2, get_longest_non_repeat_v1, get_longest_non_repeat_v2,
+    longest_non_repeat_v1, longest_non_repeat_v2,
+    get_longest_non_repeat_v1, get_longest_non_repeat_v2,
     Interval, merge_intervals,
     missing_ranges,
     move_zeros,
@@ -51,12 +52,14 @@ class TestDeleteNth(unittest.TestCase):
                              [1, 1, 3, 3, 7, 2, 2, 2, 2], n=3),
                              [1, 1, 3, 3, 7, 2, 2, 2])
         self.assertListEqual(delete_nth_naive(
-                             [1, 2, 3, 1, 1, 2, 1, 2, 3, 3, 2, 4, 5, 3, 1], n=3),
+                             [1, 2, 3, 1, 1, 2, 1, 2, 3, 3, 2, 4, 5, 3, 1],
+                             n=3),
                              [1, 2, 3, 1, 1, 2, 2, 3, 3, 4, 5])
         self.assertListEqual(delete_nth_naive([], n=5),
                              [])
         self.assertListEqual(delete_nth_naive(
-                             [1, 2, 3, 1, 1, 2, 1, 2, 3, 3, 2, 4, 5, 3, 1], n=0),
+                             [1, 2, 3, 1, 1, 2, 1, 2, 3, 3, 2, 4, 5, 3, 1],
+                             n=0),
                              [])
 
     def test_delete_nth(self):
@@ -65,11 +68,13 @@ class TestDeleteNth(unittest.TestCase):
                              [20, 37, 21])
         self.assertListEqual(delete_nth([1, 1, 3, 3, 7, 2, 2, 2, 2], n=3),
                              [1, 1, 3, 3, 7, 2, 2, 2])
-        self.assertListEqual(delete_nth([1, 2, 3, 1, 1, 2, 1, 2, 3, 3, 2, 4, 5, 3, 1], n=3),
+        self.assertListEqual(delete_nth([1, 2, 3, 1, 1, 2, 1, 2, 3, 3, 2, 4,
+                                        5, 3, 1], n=3),
                              [1, 2, 3, 1, 1, 2, 2, 3, 3, 4, 5])
         self.assertListEqual(delete_nth([], n=5),
                              [])
-        self.assertListEqual(delete_nth([1, 2, 3, 1, 1, 2, 1, 2, 3, 3, 2, 4, 5, 3, 1], n=0),
+        self.assertListEqual(delete_nth([1, 2, 3, 1, 1, 2, 1, 2, 3, 3, 2, 4,
+                                        5, 3, 1], n=0),
                              [])
 
 
@@ -169,9 +174,8 @@ class TestLongestNonRepeat(unittest.TestCase):
 
         string = "asjrgapa"
         self.assertEqual(longest_non_repeat_v2(string), 6)
-    
+
     def test_get_longest_non_repeat_v1(self):
-        
         string = "abcabcbb"
         self.assertEqual(get_longest_non_repeat_v1(string), (3, 'abc'))
 
@@ -188,7 +192,6 @@ class TestLongestNonRepeat(unittest.TestCase):
         self.assertEqual(get_longest_non_repeat_v1(string), (6, 'sjrgap'))
 
     def test_get_longest_non_repeat_v2(self):
-        
         string = "abcabcbb"
         self.assertEqual(get_longest_non_repeat_v2(string), (3, 'abc'))
 
@@ -209,9 +212,12 @@ class TestMaxOnesIndex(unittest.TestCase):
 
     def test_max_ones_index(self):
 
-        self.assertEqual(9, max_ones_index([1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1]))
-        self.assertEqual(3, max_ones_index([1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1]))
-        self.assertEqual(-1, max_ones_index([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))
+        self.assertEqual(9, max_ones_index([1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1,
+                                           1, 1]))
+        self.assertEqual(3, max_ones_index([1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1,
+                                           1, 1]))
+        self.assertEqual(-1, max_ones_index([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                            1, 1]))
 
 
 class TestMergeInterval(unittest.TestCase):
@@ -255,7 +261,8 @@ class TestMoveZeros(unittest.TestCase):
         self.assertListEqual(move_zeros([False, 1, 0, 1, 2, 0, 1, 3, "a"]),
                              [False, 1, 1, 2, 1, 3, "a", 0, 0])
 
-        self.assertListEqual(move_zeros([0, 34, 'rahul', [], None, 0, True, 0]),
+        self.assertListEqual(move_zeros([0, 34, 'rahul', [], None, 0,
+                                        True, 0]),
                              [34, 'rahul', [], None, True, 0, 0, 0])
 
 
@@ -297,31 +304,31 @@ class TestRotateArray(unittest.TestCase):
     def test_rotate_v1(self):
 
         self.assertListEqual(rotate_v1([1, 2, 3, 4, 5, 6, 7], k=3),
-                                       [5, 6, 7, 1, 2, 3, 4])
+                             [5, 6, 7, 1, 2, 3, 4])
         self.assertListEqual(rotate_v1([1, 2, 3, 4, 5, 6, 7], k=1),
-                                       [7, 1, 2, 3, 4, 5, 6])
+                             [7, 1, 2, 3, 4, 5, 6])
         self.assertListEqual(rotate_v1([1, 2, 3, 4, 5, 6, 7], k=7),
-                                       [1, 2, 3, 4, 5, 6, 7])
+                             [1, 2, 3, 4, 5, 6, 7])
         self.assertListEqual(rotate_v1([1, 2], k=111), [2, 1])
 
     def test_rotate_v2(self):
 
         self.assertListEqual(rotate_v2([1, 2, 3, 4, 5, 6, 7], k=3),
-                                       [5, 6, 7, 1, 2, 3, 4])
+                             [5, 6, 7, 1, 2, 3, 4])
         self.assertListEqual(rotate_v2([1, 2, 3, 4, 5, 6, 7], k=1),
-                                       [7, 1, 2, 3, 4, 5, 6])
+                             [7, 1, 2, 3, 4, 5, 6])
         self.assertListEqual(rotate_v2([1, 2, 3, 4, 5, 6, 7], k=7),
-                                       [1, 2, 3, 4, 5, 6, 7])
+                             [1, 2, 3, 4, 5, 6, 7])
         self.assertListEqual(rotate_v2([1, 2], k=111), [2, 1])
 
     def test_rotate_v3(self):
 
         self.assertListEqual(rotate_v3([1, 2, 3, 4, 5, 6, 7], k=3),
-                                       [5, 6, 7, 1, 2, 3, 4])
+                             [5, 6, 7, 1, 2, 3, 4])
         self.assertListEqual(rotate_v3([1, 2, 3, 4, 5, 6, 7], k=1),
-                                       [7, 1, 2, 3, 4, 5, 6])
+                             [7, 1, 2, 3, 4, 5, 6])
         self.assertListEqual(rotate_v3([1, 2, 3, 4, 5, 6, 7], k=7),
-                                       [1, 2, 3, 4, 5, 6, 7])
+                             [1, 2, 3, 4, 5, 6, 7])
         self.assertListEqual(rotate_v3([1, 2], k=111), [2, 1])
 
 
@@ -363,19 +370,22 @@ class TestTrimmean(unittest.TestCase):
     def test_trimmean(self):
 
         self.assertEqual(trimmean([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 20), 5.5)
-        self.assertEqual(trimmean([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 20), 6.0)
+        self.assertEqual(trimmean([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 20),
+                         6.0)
 
 
 class TestTop1(unittest.TestCase):
 
     def test_top_1(self):
-        self.assertListEqual(top_1([1 , 1, 2, 2, 3]), [1, 2])
-        self.assertListEqual(top_1([1, 2, 3, 324, 234, 23, 23, 1, 23, 23]), [23])
+        self.assertListEqual(top_1([1, 1, 2, 2, 3]), [1, 2])
+        self.assertListEqual(top_1([1, 2, 3, 324, 234, 23, 23, 1, 23, 23]),
+                             [23])
 
 
 class TestLimit(unittest.TestCase):
 
     def test_limit(self):
+        self.assertListEqual(limit([1, 2, 3, 4, 5]), [1, 2, 3, 4, 5])
         self.assertListEqual(limit([1, 2, 3, 4, 5], 2, 4), [2, 3, 4])
         self.assertListEqual(limit([1, 2, 3, 4, 5], 2), [2, 3, 4, 5])
         self.assertListEqual(limit([1, 2, 3, 4, 5], None, 4), [1, 2, 3, 4])
@@ -385,21 +395,34 @@ class TestNSum(unittest.TestCase):
 
     def test_n_sum(self):
         self.assertEqual(n_sum(2, [-3, 5, 2, 3, 8, -9], 6), [])  # noqa: E501
-        self.assertEqual(n_sum(3, [-5, -4, -3, -2, -1, 0, 1, 2, 3], 0), sorted([[-5,2,3],[-2,0,2],[-4,1,3],[-3,1,2],[-1,0,1],[-2,-1,3],[-3,0,3]]))  # noqa: E501
-        self.assertEqual(n_sum(3, [-1,0,1,2,-1,-4], 0), sorted([[-1,-1,2],[-1,0,1]]))  # noqa: E501
-        self.assertEqual(n_sum(4, [1, 0, -1, 0, -2, 2], 0), sorted([[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]]))  # noqa: E501
+        self.assertEqual(n_sum(3, [-5, -4, -3, -2, -1, 0, 1, 2, 3], 0),
+                         sorted([[-5, 2, 3], [-2, 0, 2], [-4, 1, 3],
+                                [-3, 1, 2], [-1, 0, 1], [-2, -1, 3],
+                                [-3, 0, 3]]))  # noqa: E501
+        self.assertEqual(n_sum(3, [-1, 0, 1, 2, -1, -4], 0),
+                         sorted([[-1, -1, 2], [-1, 0, 1]]))  # noqa: E501
+        self.assertEqual(n_sum(4, [1, 0, -1, 0, -2, 2], 0),
+                         sorted([[-2, -1, 1, 2], [-2, 0, 0, 2],
+                                 [-1, 0, 0, 1]]))  # noqa: E501
         self.assertEqual(n_sum(4, [7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 6, 4, -3, -2], 10), sorted([[-6, 2, 7, 7], [-6, 3, 6, 7], [-6, 4, 5, 7], [-6, 4, 6, 6], [-5, 1, 7, 7], [-5, 2, 6, 7], [-5, 3, 5, 7], [-5, 3, 6, 6], [-5, 4, 4, 7], [-5, 4, 5, 6], [-4, 0, 7, 7], [-4, 1, 6, 7], [-4, 2, 5, 7], [-4, 2, 6, 6], [-4, 3, 4, 7], [-4, 3, 5, 6], [-4, 4, 4, 6], [-3, -1, 7, 7], [-3, 0, 6, 7], [-3, 1, 5, 7], [-3, 1, 6, 6], [-3, 2, 4, 7], [-3, 2, 5, 6], [-3, 3, 4, 6], [-3, 4, 4, 5], [-2, -2, 7, 7], [-2, -1, 6, 7], [-2, 0, 5, 7], [-2, 0, 6, 6], [-2, 1, 4, 7], [-2, 1, 5, 6], [-2, 2, 3, 7], [-2, 2, 4, 6], [-2, 3, 4, 5], [-1, 0, 4, 7], [-1, 0, 5, 6], [-1, 1, 3, 7], [-1, 1, 4, 6], [-1, 2, 3, 6], [-1, 2, 4, 5], [-1, 3, 4, 4], [0, 1, 2, 7], [0, 1, 3, 6], [0, 1, 4, 5], [0, 2, 3, 5], [0, 2, 4, 4], [1, 2, 3, 4]]))  # noqa: E501
 
-        self.assertEqual(n_sum(2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4], [-9, 5]], 0,  # noqa: E501
+        self.assertEqual(n_sum(2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4],
+                                   [-9, 5]], 0,  # noqa: E501
                                sum_closure=lambda a, b: a[0] + b[0]),  # noqa: E501
                          [[[-3, 0], [3, 3]], [[-2, 1], [2, 2]]])  # noqa: E501
-        self.assertEqual(n_sum(2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4], [-9, 5]], [0, 3],  # noqa: E501
-                               sum_closure=lambda a, b: [a[0] + b[0], a[1] + b[1]],  # noqa: E501
-                               same_closure=lambda a, b: a[0] == b[0] and a[1] == b[1]),  # noqa: E501
+        self.assertEqual(n_sum(2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4],
+                                   [-9, 5]], [0, 3],  # noqa: E501
+                               sum_closure=lambda a, b: [a[0] + b[0],
+                               a[1] + b[1]],  # noqa: E501
+                               same_closure=lambda a, b: a[0] == b[0]
+                               and a[1] == b[1]),  # noqa: E501
                          [[[-3, 0], [3, 3]], [[-2, 1], [2, 2]]])  # noqa: E501
-        self.assertEqual(n_sum(2, [[-3, 0], [-2, 1], [2, 2], [3, 3], [8, 4], [-9, 5]], -5,  # noqa: E501
-                               sum_closure=lambda a, b: [a[0] + b[1], a[1] + b[0]],  # noqa: E501
-                               compare_closure=lambda a, b: -1 if a[0] < b else 1 if a[0] > b else 0),  # noqa: E501
+        self.assertEqual(n_sum(2, [[-3, 0], [-2, 1], [2, 2], [3, 3],
+                                   [8, 4], [-9, 5]], -5,  # noqa: E501
+                               sum_closure=lambda a, b: [a[0] + b[1],
+                               a[1] + b[0]],  # noqa: E501
+                               compare_closure=lambda a, b: -1 if a[0] < b
+                               else 1 if a[0] > b else 0),  # noqa: E501
                          [[[-9, 5], [8, 4]]])  # noqa: E501
 
 
diff --git a/tests/test_automata.py b/tests/test_automata.py
index 201c3d4..dbd766a 100644
--- a/tests/test_automata.py
+++ b/tests/test_automata.py
@@ -6,43 +6,43 @@ import unittest
 
 class TestDFA(unittest.TestCase):
     def test_DFA(self):
-    
         transitions = {
             'a': {'1': 'a', '0': 'b'},
             'b': {'1': 'b', '0': 'a'}
         }
 
-        final=['a']
+        final = ['a']
         start = 'a'
-    
+
         self.assertEqual(False, DFA(transitions, start, final, "000111100"))
         self.assertEqual(True, DFA(transitions, start, final, "111000011"))
-        
+
         transitions1 = {
             '0': {'0': '1', '1': '0'},
             '1': {'0': '2', '1': '0'},
             '2': {'0': '2', '1': '3'},
             '3': {'0': '3', '1': '3'}
-        }    
-        
+        }
+
         final1 = ['0', '1', '2']
         start1 = '0'
-        
+
         self.assertEqual(False, DFA(transitions1, start1, final1, "0001111"))
         self.assertEqual(True, DFA(transitions1, start1, final1, "01010101"))
-        
+
         transitions2 = {
             '0': {'a': '0', 'b': '1'},
             '1': {'a': '0', 'b': '2'},
             '2': {'a': '3', 'b': '2'},
             '3': {'a': '3', 'b': '3'}
         }
-        
-        final2=['3']
+
+        final2 = ['3']
         start2 = '0'
 
         self.assertEqual(False, DFA(transitions2, start2, final2, "aaabbb"))
         self.assertEqual(True, DFA(transitions2, start2, final2, "baabba"))
-        
+
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/test_backtrack.py b/tests/test_backtrack.py
index 682a89b..4e9b9f6 100644
--- a/tests/test_backtrack.py
+++ b/tests/test_backtrack.py
@@ -1,6 +1,5 @@
 from algorithms.backtrack import (
     add_operators,
-    permute,
     permute_iter,
     anagram,
     array_sum_combinations,
@@ -82,7 +81,8 @@ class TestArrayCombinationSum(unittest.TestCase):
                   [1, 3, 3], [1, 4, 2], [2, 2, 3], [2, 2, 3],
                   [2, 3, 2], [2, 3, 2], [3, 2, 2], [3, 2, 2]]
         answer.sort()
-        self.assertListEqual(sorted(array_sum_combinations(A, B, C, target)), answer)
+        self.assertListEqual(sorted(array_sum_combinations(A, B, C, target)),
+                             answer)
 
     def test_unique_array_sum_combinations(self):
         A = [1, 2, 3, 3]
@@ -92,7 +92,9 @@ class TestArrayCombinationSum(unittest.TestCase):
         answer = [(2, 3, 2), (3, 2, 2), (1, 2, 4),
                   (1, 4, 2), (2, 2, 3), (1, 3, 3)]
         answer.sort()
-        self.assertListEqual(sorted(unique_array_sum_combinations(A, B, C, target)), answer)
+        self.assertListEqual(sorted(unique_array_sum_combinations(A, B, C,
+                                                                  target)),
+                             answer)
 
 
 class TestCombinationSum(unittest.TestCase):
@@ -135,7 +137,7 @@ class TestFactorCombinations(unittest.TestCase):
             [4, 8]
         ]
         self.assertEqual(sorted(get_factors(target1)), sorted(answer1))
-        
+
         target2 = 12
         answer2 = [
             [2, 6],
@@ -145,7 +147,7 @@ class TestFactorCombinations(unittest.TestCase):
         self.assertEqual(sorted(get_factors(target2)), sorted(answer2))
         self.assertEqual(sorted(get_factors(1)), [])
         self.assertEqual(sorted(get_factors(37)), [])
-    
+
     def test_recursive_get_factors(self):
         target1 = 32
         answer1 = [
@@ -156,15 +158,17 @@ class TestFactorCombinations(unittest.TestCase):
             [2, 4, 4],
             [4, 8]
         ]
-        self.assertEqual(sorted(recursive_get_factors(target1)), sorted(answer1))
-        
+        self.assertEqual(sorted(recursive_get_factors(target1)),
+                         sorted(answer1))
+
         target2 = 12
         answer2 = [
             [2, 6],
             [2, 2, 3],
             [3, 4]
         ]
-        self.assertEqual(sorted(recursive_get_factors(target2)), sorted(answer2))
+        self.assertEqual(sorted(recursive_get_factors(target2)),
+                         sorted(answer2))
         self.assertEqual(sorted(recursive_get_factors(1)), [])
         self.assertEqual(sorted(recursive_get_factors(37)), [])
 
@@ -221,15 +225,18 @@ class TestGenerateAbbreviations(unittest.TestCase):
     def test_generate_abbreviations(self):
         word1 = "word"
         answer1 = ['word', 'wor1', 'wo1d', 'wo2', 'w1rd', 'w1r1', 'w2d', 'w3',
-            '1ord', '1or1', '1o1d', '1o2', '2rd', '2r1', '3d', '4']
-        self.assertEqual(sorted(generate_abbreviations(word1)), sorted(answer1))
+                   '1ord', '1or1', '1o1d', '1o2', '2rd', '2r1', '3d', '4']
+        self.assertEqual(sorted(generate_abbreviations(word1)),
+                         sorted(answer1))
 
         word2 = "hello"
         answer2 = ['hello', 'hell1', 'hel1o', 'hel2', 'he1lo', 'he1l1', 'he2o',
-            'he3', 'h1llo', 'h1ll1', 'h1l1o', 'h1l2', 'h2lo', 'h2l1', 'h3o', 'h4',
-            '1ello', '1ell1', '1el1o', '1el2', '1e1lo', '1e1l1', '1e2o', '1e3',
-            '2llo', '2ll1', '2l1o', '2l2', '3lo', '3l1', '4o', '5']
-        self.assertEqual(sorted(generate_abbreviations(word2)), sorted(answer2))
+                   'he3', 'h1llo', 'h1ll1', 'h1l1o', 'h1l2', 'h2lo', 'h2l1',
+                   'h3o', 'h4', '1ello', '1ell1', '1el1o', '1el2', '1e1lo',
+                   '1e1l1', '1e2o', '1e3', '2llo', '2ll1', '2l1o', '2l2',
+                   '3lo', '3l1', '4o', '5']
+        self.assertEqual(sorted(generate_abbreviations(word2)),
+                         sorted(answer2))
 
 
 class TestPatternMatch(unittest.TestCase):
@@ -251,9 +258,11 @@ class TestGenerateParenthesis(unittest.TestCase):
 
     def test_generate_parenthesis(self):
         self.assertEqual(generate_parenthesis_v1(2), ['()()', '(())'])
-        self.assertEqual(generate_parenthesis_v1(3), ['()()()', '()(())', '(())()', '(()())', '((()))'])
+        self.assertEqual(generate_parenthesis_v1(3), ['()()()', '()(())',
+                         '(())()', '(()())', '((()))'])
         self.assertEqual(generate_parenthesis_v2(2), ['(())', '()()'])
-        self.assertEqual(generate_parenthesis_v2(3), ['((()))', '(()())', '(())()', '()(())', '()()()'])
+        self.assertEqual(generate_parenthesis_v2(3), ['((()))', '(()())',
+                         '(())()', '()(())', '()()()'])
 
 
 class TestLetterCombinations(unittest.TestCase):
@@ -277,13 +286,17 @@ class TestPalindromicSubstrings(unittest.TestCase):
 
         string2 = "abcba"
         answer2 = [['abcba'], ['a', 'bcb', 'a'], ['a', 'b', 'c', 'b', 'a']]
-        self.assertEqual(sorted(palindromic_substrings(string2)), sorted(answer2))
+        self.assertEqual(sorted(palindromic_substrings(string2)),
+                         sorted(answer2))
 
         string3 = "abcccba"
-        answer3 = [['abcccba'], ['a', 'bcccb', 'a'], ['a', 'b', 'ccc', 'b', 'a'],
-            ['a', 'b', 'cc', 'c', 'b', 'a'], ['a', 'b', 'c', 'cc', 'b', 'a'], 
-            ['a', 'b', 'c', 'c', 'c', 'b', 'a']]
-        self.assertEqual(sorted(palindromic_substrings(string3)), sorted(answer3))
+        answer3 = [['abcccba'], ['a', 'bcccb', 'a'],
+                   ['a', 'b', 'ccc', 'b', 'a'],
+                   ['a', 'b', 'cc', 'c', 'b', 'a'],
+                   ['a', 'b', 'c', 'cc', 'b', 'a'],
+                   ['a', 'b', 'c', 'c', 'c', 'b', 'a']]
+        self.assertEqual(sorted(palindromic_substrings(string3)),
+                         sorted(answer3))
 
 
 class TestPermuteUnique(unittest.TestCase):
@@ -294,12 +307,14 @@ class TestPermuteUnique(unittest.TestCase):
         self.assertEqual(sorted(permute_unique(nums1)), sorted(answer1))
 
         nums2 = [1, 2, 1, 3]
-        answer2 = [[3, 1, 2, 1], [1, 3, 2, 1], [1, 2, 3, 1], [1, 2, 1, 3], [3, 2, 1, 1], 
-            [2, 3, 1, 1], [2, 1, 3, 1], [2, 1, 1, 3], [3, 1, 1, 2], [1, 3, 1, 2], [1, 1, 3, 2], [1, 1, 2, 3]]
+        answer2 = [[3, 1, 2, 1], [1, 3, 2, 1], [1, 2, 3, 1], [1, 2, 1, 3],
+                   [3, 2, 1, 1], [2, 3, 1, 1], [2, 1, 3, 1], [2, 1, 1, 3],
+                   [3, 1, 1, 2], [1, 3, 1, 2], [1, 1, 3, 2], [1, 1, 2, 3]]
         self.assertEqual(sorted(permute_unique(nums2)), sorted(answer2))
 
         nums3 = [1, 2, 3]
-        answer3 = [[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2], [1, 3, 2], [1, 2, 3]]
+        answer3 = [[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2],
+                   [1, 3, 2], [1, 2, 3]]
         self.assertEqual(sorted(permute_unique(nums3)), sorted(answer3))
 
 
@@ -307,28 +322,32 @@ class TestPermute(unittest.TestCase):
 
     def test_permute(self):
         nums1 = [1, 2, 3, 4]
-        answer1 = [[1, 2, 3, 4], [2, 1, 3, 4], [2, 3, 1, 4], [2, 3, 4, 1], [1, 3, 2, 4], 
-            [3, 1, 2, 4], [3, 2, 1, 4], [3, 2, 4, 1], [1, 3, 4, 2], [3, 1, 4, 2], 
-            [3, 4, 1, 2], [3, 4, 2, 1], [1, 2, 4, 3], [2, 1, 4, 3], [2, 4, 1, 3], 
-            [2, 4, 3, 1], [1, 4, 2, 3], [4, 1, 2, 3], [4, 2, 1, 3], [4, 2, 3, 1], 
-            [1, 4, 3, 2], [4, 1, 3, 2], [4, 3, 1, 2], [4, 3, 2, 1]]
+        answer1 = [[1, 2, 3, 4], [2, 1, 3, 4], [2, 3, 1, 4], [2, 3, 4, 1],
+                   [1, 3, 2, 4], [3, 1, 2, 4], [3, 2, 1, 4], [3, 2, 4, 1],
+                   [1, 3, 4, 2], [3, 1, 4, 2], [3, 4, 1, 2], [3, 4, 2, 1],
+                   [1, 2, 4, 3], [2, 1, 4, 3], [2, 4, 1, 3], [2, 4, 3, 1],
+                   [1, 4, 2, 3], [4, 1, 2, 3], [4, 2, 1, 3], [4, 2, 3, 1],
+                   [1, 4, 3, 2], [4, 1, 3, 2], [4, 3, 1, 2], [4, 3, 2, 1]]
         self.assertEqual(sorted(permute(nums1)), sorted(answer1))
 
         nums2 = [1, 2, 3]
-        answer2 = [[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2], [1, 3, 2], [1, 2, 3]]
+        answer2 = [[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2],
+                   [1, 3, 2], [1, 2, 3]]
         self.assertEqual(sorted(permute(nums2)), sorted(answer2))
 
     def test_permute_recursive(self):
         nums1 = [1, 2, 3, 4]
-        answer1 = [[1, 2, 3, 4], [2, 1, 3, 4], [2, 3, 1, 4], [2, 3, 4, 1], [1, 3, 2, 4], 
-            [3, 1, 2, 4], [3, 2, 1, 4], [3, 2, 4, 1], [1, 3, 4, 2], [3, 1, 4, 2], 
-            [3, 4, 1, 2], [3, 4, 2, 1], [1, 2, 4, 3], [2, 1, 4, 3], [2, 4, 1, 3], 
-            [2, 4, 3, 1], [1, 4, 2, 3], [4, 1, 2, 3], [4, 2, 1, 3], [4, 2, 3, 1], 
-            [1, 4, 3, 2], [4, 1, 3, 2], [4, 3, 1, 2], [4, 3, 2, 1]]
+        answer1 = [[1, 2, 3, 4], [2, 1, 3, 4], [2, 3, 1, 4], [2, 3, 4, 1],
+                   [1, 3, 2, 4], [3, 1, 2, 4], [3, 2, 1, 4], [3, 2, 4, 1],
+                   [1, 3, 4, 2], [3, 1, 4, 2], [3, 4, 1, 2], [3, 4, 2, 1],
+                   [1, 2, 4, 3], [2, 1, 4, 3], [2, 4, 1, 3], [2, 4, 3, 1],
+                   [1, 4, 2, 3], [4, 1, 2, 3], [4, 2, 1, 3], [4, 2, 3, 1],
+                   [1, 4, 3, 2], [4, 1, 3, 2], [4, 3, 1, 2], [4, 3, 2, 1]]
         self.assertEqual(sorted(permute_recursive(nums1)), sorted(answer1))
 
         nums2 = [1, 2, 3]
-        answer2 = [[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2], [1, 3, 2], [1, 2, 3]]
+        answer2 = [[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2],
+                   [1, 3, 2], [1, 2, 3]]
         self.assertEqual(sorted(permute_recursive(nums2)), sorted(answer2))
 
 
@@ -340,8 +359,9 @@ class TestSubsetsUnique(unittest.TestCase):
         self.assertEqual(sorted(subsets_unique(nums1)), sorted(answer1))
 
         nums2 = [1, 2, 3, 4]
-        answer2 = [(1, 2), (1, 3), (1, 2, 3, 4), (1,), (2,), (3,), (1, 4), (1, 2, 3), 
-            (4,), (), (2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4), (3, 4), (2, 4)]
+        answer2 = [(1, 2), (1, 3), (1, 2, 3, 4), (1,), (2,), (3,),
+                   (1, 4), (1, 2, 3), (4,), (), (2, 3), (1, 2, 4),
+                   (1, 3, 4), (2, 3, 4), (3, 4), (2, 4)]
         self.assertEqual(sorted(subsets_unique(nums2)), sorted(answer2))
 
 
@@ -353,8 +373,9 @@ class TestSubsets(unittest.TestCase):
         self.assertEqual(sorted(subsets(nums1)), sorted(answer1))
 
         nums2 = [1, 2, 3, 4]
-        answer2 = [[1, 2, 3, 4], [1, 2, 3], [1, 2, 4], [1, 2], [1, 3, 4], 
-            [1, 3], [1, 4], [1], [2, 3, 4], [2, 3], [2, 4], [2], [3, 4], [3], [4], []]
+        answer2 = [[1, 2, 3, 4], [1, 2, 3], [1, 2, 4], [1, 2], [1, 3, 4],
+                   [1, 3], [1, 4], [1], [2, 3, 4], [2, 3], [2, 4], [2],
+                   [3, 4], [3], [4], []]
         self.assertEqual(sorted(subsets(nums2)), sorted(answer2))
 
     def test_subsets_v2(self):
@@ -363,8 +384,9 @@ class TestSubsets(unittest.TestCase):
         self.assertEqual(sorted(subsets_v2(nums1)), sorted(answer1))
 
         nums2 = [1, 2, 3, 4]
-        answer2 = [[1, 2, 3, 4], [1, 2, 3], [1, 2, 4], [1, 2], [1, 3, 4], 
-            [1, 3], [1, 4], [1], [2, 3, 4], [2, 3], [2, 4], [2], [3, 4], [3], [4], []]
+        answer2 = [[1, 2, 3, 4], [1, 2, 3], [1, 2, 4], [1, 2], [1, 3, 4],
+                   [1, 3], [1, 4], [1], [2, 3, 4], [2, 3], [2, 4], [2],
+                   [3, 4], [3], [4], []]
         self.assertEqual(sorted(subsets_v2(nums2)), sorted(answer2))
 
 
diff --git a/tests/test_bfs.py b/tests/test_bfs.py
index 98bcb7e..f9b22f1 100644
--- a/tests/test_bfs.py
+++ b/tests/test_bfs.py
@@ -1,7 +1,6 @@
 from algorithms.bfs import (
     count_islands,
     maze_search,
-    shortest_distance_from_all_buildings,
     ladder_length
 )
 
@@ -11,22 +10,27 @@ import unittest
 class TestCountIslands(unittest.TestCase):
 
     def test_count_islands(self):
-        grid_1 = [[1,1,1,1,0], [1,1,0,1,0], [1,1,0,0,0], [0,0,0,0,0]]
+        grid_1 = [[1, 1, 1, 1, 0], [1, 1, 0, 1, 0], [1, 1, 0, 0, 0],
+                  [0, 0, 0, 0, 0]]
         self.assertEqual(1, count_islands(grid_1))
-        grid_2 = [[1,1,0,0,0], [1,1,0,0,0], [0,0,1,0,0], [0,0,0,1,1]]
+        grid_2 = [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [0, 0, 1, 0, 0],
+                  [0, 0, 0, 1, 1]]
         self.assertEqual(3, count_islands(grid_2))
-        grid_3 = [[1,1,1,0,0,0], [1,1,0,0,0,0], [1,0,0,0,0,1], [0,0,1,1,0,1], [0,0,1,1,0,0]]
+        grid_3 = [[1, 1, 1, 0, 0, 0], [1, 1, 0, 0, 0, 0], [1, 0, 0, 0, 0, 1],
+                  [0, 0, 1, 1, 0, 1], [0, 0, 1, 1, 0, 0]]
         self.assertEqual(3, count_islands(grid_3))
-        grid_4 = [[1,1,0,0,1,1], [0,0,1,1,0,0], [0,0,0,0,0,1], [1,1,1,1,0,0]]
+        grid_4 = [[1, 1, 0, 0, 1, 1], [0, 0, 1, 1, 0, 0], [0, 0, 0, 0, 0, 1],
+                  [1, 1, 1, 1, 0, 0]]
         self.assertEqual(5, count_islands(grid_4))
 
 
 class TestMazeSearch(unittest.TestCase):
 
     def test_maze_search(self):
-        grid_1 = [[1,0,1,1,1,1],[1,0,1,0,1,0],[1,0,1,0,1,1],[1,1,1,0,1,1]]
+        grid_1 = [[1, 0, 1, 1, 1, 1], [1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1],
+                  [1, 1, 1, 0, 1, 1]]
         self.assertEqual(14, maze_search(grid_1))
-        grid_2 = [[1,0,0],[0,1,1],[0,1,1]]
+        grid_2 = [[1, 0, 0], [0, 1, 1], [0, 1, 1]]
         self.assertEqual(-1, maze_search(grid_2))
 
 
@@ -35,11 +39,13 @@ class TestWordLadder(unittest.TestCase):
     def test_ladder_length(self):
 
         # hit -> hot -> dot -> dog -> cog
-        self.assertEqual(5, ladder_length('hit', 'cog', ["hot", "dot", "dog", "lot", "log"]))
+        self.assertEqual(5, ladder_length('hit', 'cog', ["hot", "dot", "dog",
+                                          "lot", "log"]))
 
         # pick -> sick -> sink -> sank -> tank == 5
         self.assertEqual(5, ladder_length('pick', 'tank',
-                                          ['tock', 'tick', 'sank', 'sink', 'sick']))
+                                          ['tock', 'tick', 'sank', 'sink',
+                                           'sick']))
 
         # live -> life == 1, no matter what is the word_list.
         self.assertEqual(1, ladder_length('live', 'life', ['hoho', 'luck']))
@@ -48,7 +54,8 @@ class TestWordLadder(unittest.TestCase):
         self.assertEqual(0, ladder_length('ate', 'ate', []))
 
         # not possible to reach !
-        self.assertEqual(-1, ladder_length('rahul', 'coder', ['blahh', 'blhah']))
+        self.assertEqual(-1, ladder_length('rahul', 'coder', ['blahh',
+                                           'blhah']))
 
 
 if __name__ == "__main__":
diff --git a/tests/test_bit.py b/tests/test_bit.py
index 23e9d94..c494a97 100644
--- a/tests/test_bit.py
+++ b/tests/test_bit.py
@@ -11,7 +11,7 @@ from algorithms.bit import (
     single_number3,
     subsets,
     get_bit, set_bit, clear_bit, update_bit,
-    int_to_bytes_big_endian, int_to_bytes_little_endian, 
+    int_to_bytes_big_endian, int_to_bytes_little_endian,
     bytes_big_endian_to_int, bytes_little_endian_to_int,
     swap_pair,
     find_difference,
@@ -151,20 +151,24 @@ class TestSuite(unittest.TestCase):
         self.assertEqual(single, single_number2(nums))
 
     def test_single_number3(self):
-        self.assertEqual(sorted([2,5]),
+        self.assertEqual(sorted([2, 5]),
                          sorted(single_number3([2, 1, 5, 6, 6, 1])))
-        self.assertEqual(sorted([4,3]),
+        self.assertEqual(sorted([4, 3]),
                          sorted(single_number3([9, 9, 4, 3])))
 
     def test_subsets(self):
 
         self.assertSetEqual(subsets([1, 2, 3]),
-                            {(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)})
+                            {(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3),
+                            (1, 2, 3)})
 
         self.assertSetEqual(subsets([10, 20, 30, 40]),
-                            {(10, 40), (10, 20, 40), (10, 30), (10, 20, 30, 40), (40,),
-                             (10, 30, 40), (30,), (20, 30), (30, 40), (10,), (),
-                             (10, 20), (20, 40), (20, 30, 40), (10, 20, 30), (20,)})
+                            {(10, 40), (10, 20, 40), (10, 30),
+                            (10, 20, 30, 40), (40,),
+                             (10, 30, 40), (30,), (20, 30), (30, 40), (10,),
+                             (),
+                             (10, 20), (20, 40), (20, 30, 40), (10, 20, 30),
+                             (20,)})
 
     def test_get_bit(self):
         # 22 = 10110
@@ -180,20 +184,22 @@ class TestSuite(unittest.TestCase):
         self.assertEqual(18, clear_bit(22, 2))
 
     def test_update_bit(self):
-        # 22 = 10110 --> after update bit at 3th position with value 1: 30 = 11110
+        # 22 = 10110 --> after update bit at 3th position with
+        # value 1: 30 = 11110
         self.assertEqual(30, update_bit(22, 3, 1))
-        # 22 = 10110 --> after update bit at 2nd position with value 0: 20 = 10010
+        # 22 = 10110 --> after update bit at 2nd position with
+        # value 0: 20 = 10010
         self.assertEqual(18, update_bit(22, 2, 0))
 
     def test_int_to_bytes_big_endian(self):
         self.assertEqual(b'\x11', int_to_bytes_big_endian(17))
-    
+
     def test_int_to_bytes_little_endian(self):
         self.assertEqual(b'\x11', int_to_bytes_little_endian(17))
 
     def test_bytes_big_endian_to_int(self):
         self.assertEqual(17, bytes_big_endian_to_int(b'\x11'))
-    
+
     def test_bytes_little_endian_to_int(self):
         self.assertEqual(17, bytes_little_endian_to_int(b'\x11'))
 
diff --git a/tests/test_compression.py b/tests/test_compression.py
index cd41283..503369c 100644
--- a/tests/test_compression.py
+++ b/tests/test_compression.py
@@ -35,35 +35,40 @@ class TestHuffmanCoding(unittest.TestCase):
         os.remove(self.file_out_bin_name)
         os.remove(self.file_out_name)
 
+
 class TestRLECompression(unittest.TestCase):
-    
+
     def test_encode_rle(self):
         self.assertEqual('12W1B12W3B24W1B14W',
-            encode_rle('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'))
+                         encode_rle('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW'))
 
     def test_decode_rle(self):
-        self.assertEqual('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW', 
-            decode_rle('12W1B12W3B24W1B14W'))
+        self.assertEqual('WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW',
+                         decode_rle('12W1B12W3B24W1B14W'))
+
 
 class TestEliasCoding(unittest.TestCase):
 
     def test_elias_gamma(self):
-        correct_result = ['0', '00', '100', '101', '11000', '11001', '11010', '11011', '1110000', '1110001', '1110010']
-        
+        correct_result = ['0', '00', '100', '101', '11000', '11001', '11010',
+                          '11011', '1110000', '1110001', '1110010']
+
         result = []
-        for i in range(11):	
+        for i in range(11):
             result.append(elias_gamma(i))
 
         self.assertEqual(correct_result, result)
 
     def test_elias_delta(self):
-        correct_result = ['0', '000', '1000', '1001', '10100', '10101', '10110', '10111', '11000000', '11000001', '11000010']
+        correct_result = ['0', '000', '1000', '1001', '10100', '10101',
+                          '10110', '10111', '11000000', '11000001', '11000010']
 
         result = []
-        for i in range(11):	
+        for i in range(11):
             result.append(elias_delta(i))
 
-        self.assertEqual(correct_result, result)        
+        self.assertEqual(correct_result, result)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests/test_dfs.py b/tests/test_dfs.py
index 0f198e4..3164ab8 100644
--- a/tests/test_dfs.py
+++ b/tests/test_dfs.py
@@ -12,53 +12,69 @@ import unittest
 
 class TestAllFactors(unittest.TestCase):
     def test_get_factors(self):
-        self.assertEqual([[2, 16], [2, 2, 8], [2, 2, 2, 4], [2, 2, 2, 2, 2], [2, 4, 4], [4, 8]],
-        get_factors(32))
+        self.assertEqual([[2, 16], [2, 2, 8], [2, 2, 2, 4], [2, 2, 2, 2, 2],
+                         [2, 4, 4], [4, 8]], get_factors(32))
+
     def test_get_factors_iterative1(self):
-        self.assertEqual([[2, 16], [4, 8], [2, 2, 8], [2, 4, 4], [2, 2, 2, 4], [2, 2, 2, 2, 2]],
-        get_factors_iterative1(32))
+        self.assertEqual([[2, 16], [4, 8], [2, 2, 8], [2, 4, 4], [2, 2, 2, 4],
+                          [2, 2, 2, 2, 2]], get_factors_iterative1(32))
+
     def test_get_factors_iterative2(self):
-        self.assertEqual([[2, 2, 2, 2, 2], [2, 2, 2, 4], [2, 2, 8], [2, 4, 4], [2, 16], [4, 8]],
-        get_factors_iterative2(32))
+        self.assertEqual([[2, 2, 2, 2, 2], [2, 2, 2, 4], [2, 2, 8], [2, 4, 4],
+                          [2, 16], [4, 8]], get_factors_iterative2(32))
 
 
 class TestCountIslands(unittest.TestCase):
     def test_num_islands(self):
-        self.assertEqual(1, num_islands([[1, 1, 1, 1, 0], [1, 1, 0, 1, 0], [1, 1, 0, 0, 0], [0, 0, 0, 0, 0]]))
-        self.assertEqual(3, num_islands([[1, 1, 0, 0, 0], [1, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 1]]))
+        self.assertEqual(1, num_islands([[1, 1, 1, 1, 0], [1, 1, 0, 1, 0],
+                                         [1, 1, 0, 0, 0], [0, 0, 0, 0, 0]]))
+        self.assertEqual(3, num_islands([[1, 1, 0, 0, 0], [1, 1, 0, 0, 0],
+                                         [0, 0, 1, 0, 0], [0, 0, 0, 1, 1]]))
 
 
 class TestPacificAtlantic(unittest.TestCase):
     def test_pacific_atlantic(self):
-        self.assertEqual([[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]], 
-            pacific_atlantic([[1, 2, 2, 3, 5], [3, 2, 3, 4, 4], [2, 4, 5, 3, 1], [6, 7, 1, 4, 5], [5, 1, 1, 2, 4]]))
+        self.assertEqual([[0, 4], [1, 3], [1, 4], [2, 2], [3, 0],
+                          [3, 1], [4, 0]], pacific_atlantic([[1, 2, 2, 3, 5],
+                                                            [3, 2, 3, 4, 4],
+                                                            [2, 4, 5, 3, 1],
+                                                            [6, 7, 1, 4, 5],
+                                                            [5, 1, 1, 2, 4]]))
 
 
 class TestSudoku(unittest.TestCase):
     def test_sudoku_solver(self):
-        board = [["5","3","."], ["6",".", "."],[".","9","8"]]
+        board = [["5", "3", "."], ["6", ".", "."], [".", "9", "8"]]
         test_obj = Sudoku(board, 3, 3)
         test_obj.solve()
-        self.assertEqual([['5', '3', '1'], ['6', '1', '2'], ['1', '9', '8']],test_obj.board)
+        self.assertEqual([['5', '3', '1'], ['6', '1', '2'],
+                         ['1', '9', '8']], test_obj.board)
 
 
 class TestWallsAndGates(unittest.TestCase):
     def test_walls_and_gates(self):
-        rooms = [[float("inf"), -1, 0, float("inf")], 
-                [float("inf"), float("inf"), float("inf"), -1], 
-                [float("inf"), -1, float("inf"), -1], 
-                [0, -1, float("inf"), float("inf")]]
+        rooms = [[float("inf"), -1, 0, float("inf")],
+                 [float("inf"), float("inf"), float("inf"), -1],
+                 [float("inf"), -1, float("inf"), -1],
+                 [0, -1, float("inf"), float("inf")]]
         walls_and_gates(rooms)
-        self.assertEqual([[3, -1, 0, 1], [2, 2, 1, -1], [1, -1, 2, -1], [0, -1, 3, 4]], rooms)
+        self.assertEqual([[3, -1, 0, 1], [2, 2, 1, -1], [1, -1, 2, -1],
+                          [0, -1, 3, 4]], rooms)
+
 
 class TestMazeSearch(unittest.TestCase):
     def test_maze_search(self):
-        maze_1 = [[1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1], [1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1]]
+        maze_1 = [[1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1,
+                   1, 0, 1, 1, 1],
+                  [1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,
+                   0, 1, 1, 1, 0, 1]]
         self.assertEqual(37, find_path(maze_1))
-        maze_2 = [[1,0,1,1,1,1], [1,0,1,0,1,0], [1,0,1,0,1,1], [1,1,1,0,1,1]]
+        maze_2 = [[1, 0, 1, 1, 1, 1], [1, 0, 1, 0, 1, 0],
+                  [1, 0, 1, 0, 1, 1], [1, 1, 1, 0, 1, 1]]
         self.assertEqual(14, find_path(maze_2))
-        maze_3 = [[1,0,0], [0,1,1], [0,1,1]]
+        maze_3 = [[1, 0, 0], [0, 1, 1], [0, 1, 1]]
         self.assertEqual(-1, find_path(maze_3))
 
+
 if __name__ == "__main__":
-    unittest.main()
\ No newline at end of file
+    unittest.main()
diff --git a/tests/test_dp.py b/tests/test_dp.py
index 300be3d..e92800a 100644
--- a/tests/test_dp.py
+++ b/tests/test_dp.py
@@ -14,7 +14,7 @@ from algorithms.dp import (
     longest_increasing_subsequence_optimized,
     longest_increasing_subsequence_optimized2,
     int_divide,find_k_factor,
-    planting_trees
+    planting_trees, regex_matching
 )
 
 
@@ -85,7 +85,7 @@ class TestFib(unittest.TestCase):
 class TestHosoyaTriangle(unittest.TestCase):
     """[summary]
     Test for the file hosoya_triangle
-    
+
     Arguments:
         unittest {[type]} -- [description]
     """
@@ -109,7 +109,7 @@ class TestHosoyaTriangle(unittest.TestCase):
                           21, 13, 16, 15, 15, 16, 13, 21,
                           34, 21, 26, 24, 25, 24, 26, 21, 34,
                           55, 34, 42, 39, 40, 40, 39, 42, 34, 55],
-                          hosoya_testing(10))
+                         hosoya_testing(10))
 
 
 class TestHouseRobber(unittest.TestCase):
@@ -129,7 +129,8 @@ class TestKnapsack(unittest.TestCase):
         self.assertEqual(220, get_maximum_value([item1, item2, item3], 50))
 
         item1, item2, item3, item4 = Item(60, 5), Item(50, 3), Item(70, 4), Item(30, 2)
-        self.assertEqual(80, get_maximum_value([item1, item2, item3, item4], 5))
+        self.assertEqual(80, get_maximum_value([item1, item2, item3, item4],
+                                               5))
 
 
 class TestLongestIncreasingSubsequence(unittest.TestCase):
@@ -156,32 +157,34 @@ class TestIntDivide(unittest.TestCase):
         self.assertEqual(42, int_divide(10))
         self.assertEqual(204226, int_divide(50))
 
+
 class Test_dp_K_Factor(unittest.TestCase):
     def test_kfactor(self):
-        #Test 1
-        n1=4
-        k1=1
-        self.assertEqual(find_k_factor(n1,k1),1)
-
-        #Test 2
-        n2=7
-        k2=1
-        self.assertEqual(find_k_factor(n2,k2),70302)
-
-        #Test 3
-        n3=10
-        k3=2
-        self.assertEqual(find_k_factor(n3,k3),74357)
-
-        #Test 4
-        n4=8
-        k4=2
-        self.assertEqual(find_k_factor(n4,k4),53)
-
-        #Test 5
-        n5=9
-        k5=1
-        self.assertEqual(find_k_factor(n5,k5),71284044)
+        # Test 1
+        n1 = 4
+        k1 = 1
+        self.assertEqual(find_k_factor(n1, k1), 1)
+
+        # Test 2
+        n2 = 7
+        k2 = 1
+        self.assertEqual(find_k_factor(n2, k2), 70302)
+
+        # Test 3
+        n3 = 10
+        k3 = 2
+        self.assertEqual(find_k_factor(n3, k3), 74357)
+
+        # Test 4
+        n4 = 8
+        k4 = 2
+        self.assertEqual(find_k_factor(n4, k4), 53)
+
+        # Test 5
+        n5 = 9
+        k5 = 1
+        self.assertEqual(find_k_factor(n5, k5), 71284044)
+
 
 class TestPlantingTrees(unittest.TestCase):
     def test_simple(self):
@@ -207,6 +210,54 @@ class TestPlantingTrees(unittest.TestCase):
 
         # assert
         self.assertEqual(res, 9.28538328578604)
+    
+class TestRegexMatching(unittest.TestCase):
+    def test_none_0(self):
+        s = ""
+        p = ""
+        self.assertTrue(regex_matching.is_match(s, p))
+
+    def test_none_1(self):
+        s = ""
+        p = "a"
+        self.assertFalse(regex_matching.is_match(s, p))
+
+    def test_no_symbol_equal(self):
+        s = "abcd"
+        p = "abcd"
+        self.assertTrue(regex_matching.is_match(s, p))
+
+    def test_no_symbol_not_equal_0(self):
+        s = "abcd"
+        p = "efgh"
+        self.assertFalse(regex_matching.is_match(s, p))
+
+    def test_no_symbol_not_equal_1(self):
+        s = "ab"
+        p = "abb"
+        self.assertFalse(regex_matching.is_match(s, p))
+
+    def test_symbol_0(self):
+        s = ""
+        p = "a*"
+        self.assertTrue(regex_matching.is_match(s, p))
+
+    def test_symbol_1(self):
+        s = "a"
+        p = "ab*"
+        self.assertTrue(regex_matching.is_match(s, p))
+
+    def test_symbol_2(self):
+        # E.g.
+        #   s a b b
+        # p 1 0 0 0
+        # a 0 1 0 0
+        # b 0 0 1 0
+        # * 0 1 1 1
+        s = "abb"
+        p = "ab*"
+        self.assertTrue(regex_matching.is_match(s, p))
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/test_graph.py b/tests/test_graph.py
index 325b5d8..eb50dd4 100644
--- a/tests/test_graph.py
+++ b/tests/test_graph.py
@@ -8,9 +8,12 @@ from algorithms.graph import maximum_flow_bfs
 from algorithms.graph import maximum_flow_dfs
 from algorithms.graph import all_pairs_shortest_path
 from algorithms.graph import bellman_ford
-from algorithms.graph import bellman_ford
 from algorithms.graph import count_connected_number_of_component
 from algorithms.graph import prims_minimum_spanning
+from algorithms.graph import check_digraph_strongly_connected
+from algorithms.graph import cycle_detection
+from algorithms.graph import find_path
+from algorithms.graph import path_between_two_vertices_in_digraph
 
 import unittest
 
@@ -37,7 +40,8 @@ class TestTarjan(unittest.TestCase):
         }
 
         g = Tarjan(example)
-        self.assertEqual(g.sccs, [['F', 'G'], ['C', 'D', 'H'], ['A', 'B', 'E']])
+        self.assertEqual(g.sccs, [['F', 'G'], ['C', 'D', 'H'],
+                                  ['A', 'B', 'E']])
 
     def test_tarjan_example_2(self):
         # Graph from https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm#/media/File:Tarjan%27s_Algorithm_Animation.gif
@@ -53,39 +57,36 @@ class TestTarjan(unittest.TestCase):
         }
 
         g = Tarjan(example)
-        self.assertEqual(g.sccs, [['A', 'B', 'E'], ['C', 'D'], ['F', 'G'], ['H']])
+        self.assertEqual(g.sccs, [['A', 'B', 'E'], ['C', 'D'], ['F', 'G'],
+                                  ['H']])
+
 
-        
 class TestCheckBipartite(unittest.TestCase):
-    
     def test_check_bipartite(self):
-        
         adj_list_1 = [[0, 0, 1], [0, 0, 1], [1, 1, 0]]
         self.assertEqual(True, check_bipartite(adj_list_1))
-        
         adj_list_2 = [[0, 1, 0, 1], [1, 0, 1, 0], [0, 1, 0, 1], [1, 0, 1, 0]]
         self.assertEqual(True, check_bipartite(adj_list_2))
-        
         adj_list_3 = [[0, 1, 0, 0], [1, 0, 1, 1], [0, 1, 0, 1], [0, 1, 1, 0]]
         self.assertEqual(False, check_bipartite(adj_list_3))
 
+
 class TestDijkstra(unittest.TestCase):
-    
     def test_dijkstra(self):
-        g = Dijkstra(9) 
-        g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0], 
-           [4, 0, 8, 0, 0, 0, 0, 11, 0], 
-           [0, 8, 0, 7, 0, 4, 0, 0, 2], 
-           [0, 0, 7, 0, 9, 14, 0, 0, 0], 
-           [0, 0, 0, 9, 0, 10, 0, 0, 0], 
-           [0, 0, 4, 14, 10, 0, 2, 0, 0], 
-           [0, 0, 0, 0, 0, 2, 0, 1, 6], 
-           [8, 11, 0, 0, 0, 0, 1, 0, 7], 
-           [0, 0, 2, 0, 0, 0, 6, 7, 0] 
-          ]; 
+        g = Dijkstra(9)
+        g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
+                   [4, 0, 8, 0, 0, 0, 0, 11, 0],
+                   [0, 8, 0, 7, 0, 4, 0, 0, 2],
+                   [0, 0, 7, 0, 9, 14, 0, 0, 0],
+                   [0, 0, 0, 9, 0, 10, 0, 0, 0],
+                   [0, 0, 4, 14, 10, 0, 2, 0, 0],
+                   [0, 0, 0, 0, 0, 2, 0, 1, 6],
+                   [8, 11, 0, 0, 0, 0, 1, 0, 7],
+                   [0, 0, 2, 0, 0, 0, 6, 7, 0]]
 
         self.assertEqual(g.dijkstra(0), [0, 4, 12, 19, 21, 11, 9, 8, 14])
 
+
 class TestMaximumFlow(unittest.TestCase):
     """
     Test for the file maximum_flow.py
@@ -104,6 +105,7 @@ class TestMaximumFlow(unittest.TestCase):
                 [0, 0, 0, 0, 0, 0, 0]
             ]
         self.assertEqual(19, ford_fulkerson(capacity, 0, 6))
+
     def test_edmonds_karp(self):
         capacity = [
                 [0, 10, 10, 0, 0, 0, 0],
@@ -115,6 +117,7 @@ class TestMaximumFlow(unittest.TestCase):
                 [0, 0, 0, 0, 0, 0, 0]
             ]
         self.assertEqual(19, edmonds_karp(capacity, 0, 6))
+
     def dinic(self):
         capacity = [
                 [0, 10, 10, 0, 0, 0, 0],
@@ -127,6 +130,7 @@ class TestMaximumFlow(unittest.TestCase):
             ]
         self.assertEqual(19, dinic(capacity, 0, 6))
 
+
 class TestMaximum_Flow_Bfs(unittest.TestCase):
 
     """
@@ -134,13 +138,12 @@ class TestMaximum_Flow_Bfs(unittest.TestCase):
     Arguments:
         unittest {[type]} -- [description]
     """
-    
     def test_maximum_flow_bfs(self):
         graph = [
             [0, 16, 13, 0, 0, 0],
             [0, 0, 10, 12, 0, 0],
-            [0, 4, 0, 0, 14, 0], 
-            [0, 0, 9, 0, 0, 20], 
+            [0, 4, 0, 0, 14, 0],
+            [0, 0, 9, 0, 0, 20],
             [0, 0, 0, 7, 0, 4],
             [0, 0, 0, 0, 0, 0]
         ]
@@ -148,6 +151,7 @@ class TestMaximum_Flow_Bfs(unittest.TestCase):
 
         self.assertEqual(maximum_flow, 23)
 
+
 class TestMaximum_Flow_Dfs(unittest.TestCase):
 
     """
@@ -155,13 +159,12 @@ class TestMaximum_Flow_Dfs(unittest.TestCase):
     Arguments:
         unittest {[type]} -- [description]
     """
-    
     def test_maximum_flow_dfs(self):
         graph = [
             [0, 16, 13, 0, 0, 0],
             [0, 0, 10, 12, 0, 0],
-            [0, 4, 0, 0, 14, 0], 
-            [0, 0, 9, 0, 0, 20], 
+            [0, 4, 0, 0, 14, 0],
+            [0, 0, 9, 0, 0, 20],
             [0, 0, 0, 7, 0, 4],
             [0, 0, 0, 0, 0, 0]
         ]
@@ -171,24 +174,26 @@ class TestMaximum_Flow_Dfs(unittest.TestCase):
 
 
 class TestAll_Pairs_Shortest_Path(unittest.TestCase):
-    
     def test_all_pairs_shortest_path(self):
-        graph = [[0, 0.1, 0.101, 0.142, 0.277], 
-                 [0.465, 0, 0.191, 0.192, 0.587], 
-                 [0.245, 0.554, 0, 0.333, 0.931], 
-                 [1.032, 0.668, 0.656, 0, 0.151], 
+        graph = [[0, 0.1, 0.101, 0.142, 0.277],
+                 [0.465, 0, 0.191, 0.192, 0.587],
+                 [0.245, 0.554, 0, 0.333, 0.931],
+                 [1.032, 0.668, 0.656, 0, 0.151],
                  [0.867, 0.119, 0.352, 0.398, 0]]
         result = all_pairs_shortest_path(graph)
 
         self.assertEqual(result, [
-          [0, 0.1, 0.101, 0.142, 0.277],
-          [0.436, 0, 0.191, 0.192, 0.34299999999999997],
-          [0.245, 0.345, 0, 0.333, 0.484],
-          [0.706, 0.27, 0.46099999999999997, 0, 0.151],
-          [0.5549999999999999, 0.119, 0.31, 0.311, 0],
-        ])
-
-        
+                                    [0, 0.1, 0.101, 0.142, 0.277],
+                                    [0.436, 0, 0.191, 0.192,
+                                     0.34299999999999997],
+                                    [0.245, 0.345, 0, 0.333, 0.484],
+                                    [0.706, 0.27, 0.46099999999999997, 0,
+                                     0.151],
+                                    [0.5549999999999999, 0.119, 0.31, 0.311,
+                                     0],
+                                ])
+
+
 class TestBellmanFord(unittest.TestCase):
     def test_bellman_ford(self):
         graph1 = {
@@ -198,90 +203,149 @@ class TestBellmanFord(unittest.TestCase):
             'd': {'a': 2, 'c': 7},
             'e': {'b': -3}
         }
-    
         self.assertEqual(True, bellman_ford(graph1, 'a'))
-    
         graph2 = {
             'a': {'d': 3, 'e': 4},
-            'b': {'a': 7, 'e':2},
-            'c': {'a': 12, 'd':9, 'e':11},
+            'b': {'a': 7, 'e': 2},
+            'c': {'a': 12, 'd': 9, 'e': 11},
             'd': {'c': 5, 'e': 11},
             'e': {'a': 7, 'b': 5, 'd': 1}
-        } 
-    
+        }
         self.assertEqual(True, bellman_ford(graph2, 'a'))
 
-        
-class TestConnectedComponentInGraph(unittest.TestCase):    
+
+class TestConnectedComponentInGraph(unittest.TestCase):
     """
      Class for testing different cases for connected components in graph
     """
     def test_count_connected_components(self):
         """
-           Test Function that test the different cases of count connected components
-            
+           Test Function that test the different cases of count connected
+           components
             2----------0    1--------5      3
             |
             |
             4
-                
                 output = 3
         """
         expected_result = 3
-        
         # adjacency list representation of graph
         l = [[2],
-            [5],
-            [0,4],
-            [],
-            [2],
-            [1]
-        ]
+             [5],
+             [0,4],
+             [],
+             [2],
+             [1]]
 
         size = 5
-        result = count_connected_number_of_component.count_components(l,size)
-        self.assertEqual(result,expected_result)
+        result = count_connected_number_of_component.count_components(l, size)
+        self.assertEqual(result, expected_result)
 
     def test_connected_components_with_empty_graph(self):
 
         """
-            input : 
+            input :
             output : 0
         """
-        
         l = [[]]
         expected_result = 0
         size = 0
-        result = count_connected_number_of_component.count_components(l,size)
-        self.assertEqual(result,expected_result)    
+        result = count_connected_number_of_component.count_components(l, size)
+        self.assertEqual(result, expected_result)
 
     def test_connected_components_without_edges_graph(self):
         """
           input : 0          2             3          4
           output : 4
-        """   
-        l = [[0],[],[2],[3],[4]]
+        """
+        l = [[0], [], [2], [3], [4]]
         size = 4
         expected_result = 4
-        result = count_connected_number_of_component.count_components(l,size)
-        self.assertEqual(result,expected_result)
+        result = count_connected_number_of_component.count_components(l, size)
+        self.assertEqual(result, expected_result)
+
 
-        
 class PrimsMinimumSpanning(unittest.TestCase):
     def test_prim_spanning(self):
         graph1 = {
-            1 : [ [3, 2], [8, 3] ],
-            2 : [ [3, 1], [5, 4] ],
-            3 : [ [8, 1], [2, 4], [4, 5] ],
-            4 : [ [5, 2], [2, 3], [6, 5] ],
-            5 : [ [4, 3], [6, 4] ]
+            1: [[3, 2], [8, 3]],
+            2: [[3, 1], [5, 4]],
+            3: [[8, 1], [2, 4], [4, 5]],
+            4: [[5, 2], [2, 3], [6, 5]],
+            5: [[4, 3], [6, 4]]
         }
         self.assertEqual(14, prims_minimum_spanning(graph1))
-        
         graph2 = {
-            1 : [ [7, 2], [6, 4] ],
-            2 : [ [7, 1], [9, 4], [6, 3] ],
-            3 : [ [8, 4], [6, 2] ],
-            4 : [ [6, 1], [9, 2], [8, 3] ]
+            1: [[7, 2], [6, 4]],
+            2: [[7, 1], [9, 4], [6, 3]],
+            3: [[8, 4], [6, 2]],
+            4: [[6, 1], [9, 2], [8, 3]]
         }
         self.assertEqual(19, prims_minimum_spanning(graph2))
+
+class TestDigraphStronglyConnected(unittest.TestCase):
+    def test_digraph_strongly_connected(self):
+        g1 = check_digraph_strongly_connected.Graph(5)
+        g1.add_edge(0, 1)
+        g1.add_edge(1, 2)
+        g1.add_edge(2, 3)
+        g1.add_edge(3, 0)
+        g1.add_edge(2, 4)
+        g1.add_edge(4, 2)
+        self.assertTrue(g1.is_strongly_connected())
+
+        g2 = check_digraph_strongly_connected.Graph(4)
+        g2.add_edge(0, 1)
+        g2.add_edge(1, 2)
+        g2.add_edge(2, 3)
+        self.assertFalse(g2.is_strongly_connected())
+
+class TestCycleDetection(unittest.TestCase):
+    def test_cycle_detection_with_cycle(self):
+        graph = {'A': ['B', 'C'],
+                 'B': ['D'],
+                 'C': ['F'],
+                 'D': ['E', 'F'],
+                 'E': ['B'],
+                 'F': []}
+        self.assertTrue(cycle_detection.contains_cycle(graph))
+
+    def test_cycle_detection_with_no_cycle(self):
+        graph = {'A': ['B', 'C'],
+                 'B': ['D', 'E'],
+                 'C': ['F'],
+                 'D': ['E'],
+                 'E': [],
+                 'F': []}
+        self.assertFalse(cycle_detection.contains_cycle(graph))
+
+class TestFindPath(unittest.TestCase):
+    def test_find_all_paths(self):
+        graph = {'A': ['B', 'C'],
+                 'B': ['C', 'D'],
+                 'C': ['D', 'F'],
+                 'D': ['C'],
+                 'E': ['F'],
+                 'F': ['C']}
+
+        paths = find_path.find_all_path(graph, 'A', 'F')
+        print(paths)
+        self.assertEqual(sorted(paths), sorted([
+            ['A', 'C', 'F'],
+            ['A', 'B', 'C', 'F'],
+            ['A', 'B', 'D', 'C', 'F'],
+        ]))
+
+class TestPathBetweenTwoVertices(unittest.TestCase):
+    def test_node_is_reachable(self):
+        g = path_between_two_vertices_in_digraph.Graph(4)
+        g.add_edge(0, 1)
+        g.add_edge(0, 2)
+        g.add_edge(1, 2)
+        g.add_edge(2, 0)
+        g.add_edge(2, 3)
+        g.add_edge(3, 3)
+
+        self.assertTrue(g.is_reachable(1, 3))
+        self.assertFalse(g.is_reachable(3, 1))
+
diff --git a/tests/test_greedy.py b/tests/test_greedy.py
new file mode 100644
index 0000000..095f2a2
--- /dev/null
+++ b/tests/test_greedy.py
@@ -0,0 +1,21 @@
+from algorithms.greedy import (
+    max_contiguous_subsequence_sum,
+)
+
+import unittest
+
+class TestMaxContiguousSubsequenceSum(unittest.TestCase):
+    def test_max_contiguous_subsequence_sum(self):
+        arr1 = [-2, 3, 8, -1, 4]
+        arr2 = [-1, 1, 0]
+        arr3 = [-1, -3, -4]
+        arr4 = [-2, 3, 8, -12, 8, 4]
+
+        self.assertEqual(max_contiguous_subsequence_sum(arr1), 14)
+        self.assertEqual(max_contiguous_subsequence_sum(arr2), 1)
+        self.assertEqual(max_contiguous_subsequence_sum(arr3), -1)
+        self.assertEqual(max_contiguous_subsequence_sum(arr4), 12)
+
+if __name__ == '__main__':
+
+    unittest.main()
\ No newline at end of file
diff --git a/tests/test_heap.py b/tests/test_heap.py
index 6814c61..afae0d9 100644
--- a/tests/test_heap.py
+++ b/tests/test_heap.py
@@ -28,7 +28,7 @@ class TestBinaryHeap(unittest.TestCase):
         self.min_heap.insert(2)
         self.assertEqual([0, 2, 50, 4, 55, 90, 87, 7],
                          self.min_heap.heap)
-        self.assertEqual(7, self.min_heap.currentSize)
+        self.assertEqual(7, self.min_heap.current_size)
 
     def test_remove_min(self):
         ret = self.min_heap.remove_min()
@@ -38,7 +38,7 @@ class TestBinaryHeap(unittest.TestCase):
         self.assertEqual(4, ret)
         self.assertEqual([0, 7, 50, 87, 55, 90],
                          self.min_heap.heap)
-        self.assertEqual(5, self.min_heap.currentSize)
+        self.assertEqual(5, self.min_heap.current_size)
 
 
 class TestSuite(unittest.TestCase):
@@ -55,10 +55,12 @@ class TestSuite(unittest.TestCase):
         self.assertEqual([3, 3, 5, 5, 6, 7], max_sliding_window(nums, 3))
 
     def test_k_closest_points(self):
-        points = [(1, 0), (2, 3), (5, 2), (1, 1), (2, 8), (10, 2), (-1, 0), (-2, -2)]
+        points = [(1, 0), (2, 3), (5, 2), (1, 1), (2, 8), (10, 2),
+                  (-1, 0), (-2, -2)]
         self.assertEqual([(-1, 0), (1, 0)], k_closest(points, 2))
         self.assertEqual([(1, 1), (-1, 0), (1, 0)], k_closest(points, 3))
-        self.assertEqual([(-2, -2), (1, 1), (1, 0), (-1, 0)], k_closest(points, 4))
+        self.assertEqual([(-2, -2), (1, 1), (1, 0),
+                          (-1, 0)], k_closest(points, 4))
         self.assertEqual([(10, 2), (2, 8), (5, 2), (-2, -2), (2, 3),
                           (1, 0), (-1, 0), (1, 1)], k_closest(points, 8))
 
diff --git a/tests/test_iterative_segment_tree.py b/tests/test_iterative_segment_tree.py
index b9a611a..66d2222 100644
--- a/tests/test_iterative_segment_tree.py
+++ b/tests/test_iterative_segment_tree.py
@@ -21,10 +21,14 @@ class TestSegmentTree(unittest.TestCase):
         min_segment_tree = SegmentTree(arr, min)
         sum_segment_tree = SegmentTree(arr, lambda a, b: a + b)
         gcd_segment_tree = SegmentTree(arr, gcd)
-        self.assertEqual(max_segment_tree.tree, [None, 9, 8, 9, 4, 8, 9, 2, 4, 3, 6, 8, 9, 3])
-        self.assertEqual(min_segment_tree.tree, [None, 2, 3, 2, 3, 6, 3, 2, 4, 3, 6, 8, 9, 3])
-        self.assertEqual(sum_segment_tree.tree, [None, 35, 21, 14, 7, 14, 12, 2, 4, 3, 6, 8, 9, 3])
-        self.assertEqual(gcd_segment_tree.tree, [None, 1, 1, 1, 1, 2, 3, 2, 4, 3, 6, 8, 9, 3])
+        self.assertEqual(max_segment_tree.tree,
+                         [None, 9, 8, 9, 4, 8, 9, 2, 4, 3, 6, 8, 9, 3])
+        self.assertEqual(min_segment_tree.tree,
+                         [None, 2, 3, 2, 3, 6, 3, 2, 4, 3, 6, 8, 9, 3])
+        self.assertEqual(sum_segment_tree.tree,
+                         [None, 35, 21, 14, 7, 14, 12, 2, 4, 3, 6, 8, 9, 3])
+        self.assertEqual(gcd_segment_tree.tree,
+                         [None, 1, 1, 1, 1, 2, 3, 2, 4, 3, 6, 8, 9, 3])
 
     def test_max_segment_tree(self):
         arr = [-1, 1, 10, 2, 9, -3, 8, 4, 7, 5, 6, 0]
@@ -44,29 +48,33 @@ class TestSegmentTree(unittest.TestCase):
 
     def test_max_segment_tree_with_updates(self):
         arr = [-1, 1, 10, 2, 9, -3, 8, 4, 7, 5, 6, 0]
-        updates = {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10, 10: 11, 11: 12}
+        updates = {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9,
+                   9: 10, 10: 11, 11: 12}
         self.__test_all_segments_with_updates(arr, max, updates)
 
     def test_min_segment_tree_with_updates(self):
         arr = [1, 10, -2, 9, -3, 8, 4, -7, 5, 6, 11, -12]
-        updates = {0: 7, 1: 2, 2: 6, 3: -14, 4: 5, 5: 4, 6: 7, 7: -10, 8: 9, 9: 10, 10: 12, 11: 1}
+        updates = {0: 7, 1: 2, 2: 6, 3: -14, 4: 5, 5: 4, 6: 7, 7: -10, 8: 9,
+                   9: 10, 10: 12, 11: 1}
         self.__test_all_segments_with_updates(arr, min, updates)
 
     def test_sum_segment_tree_with_updates(self):
         arr = [1, 10, 2, 9, 3, 8, 4, 7, 5, 6, -11, -12]
-        updates = {0: 12, 1: 11, 2: 10, 3: 9, 4: 8, 5: 7, 6: 6, 7: 5, 8: 4, 9: 3, 10: 2, 11: 1}
+        updates = {0: 12, 1: 11, 2: 10, 3: 9, 4: 8, 5: 7, 6: 6, 7: 5, 8: 4,
+                   9: 3, 10: 2, 11: 1}
         self.__test_all_segments_with_updates(arr, lambda a, b: a + b, updates)
 
     def test_gcd_segment_tree_with_updates(self):
         arr = [1, 10, 2, 9, 3, 8, 4, 7, 5, 6, 11, 12, 14]
-        updates = {0: 4, 1: 2, 2: 3, 3: 9, 4: 21, 5: 7, 6: 4, 7: 4, 8: 2, 9: 5, 10: 17, 11: 12, 12: 3}
+        updates = {0: 4, 1: 2, 2: 3, 3: 9, 4: 21, 5: 7, 6: 4, 7: 4, 8: 2,
+                   9: 5, 10: 17, 11: 12, 12: 3}
         self.__test_all_segments_with_updates(arr, gcd, updates)
 
     def __test_all_segments(self, arr, fnc):
         """
         Test all possible segments in the tree
         :param arr: array to test
-        :param fnc: function of the segment tree
+        :param fnc: function of the segment tpree
         """
         segment_tree = SegmentTree(arr, fnc)
         self.__test_segments_helper(segment_tree, fnc, arr)
diff --git a/tests/test_map.py b/tests/test_map.py
index c816488..a62656d 100644
--- a/tests/test_map.py
+++ b/tests/test_map.py
@@ -1,6 +1,6 @@
 from algorithms.map import (
     HashTable, ResizableHashTable,
-    Node, SeparateChainingHashTable,
+    SeparateChainingHashTable,
     word_pattern,
     is_isomorphic,
     is_anagram,
@@ -9,6 +9,7 @@ from algorithms.map import (
 
 import unittest
 
+
 class TestHashTable(unittest.TestCase):
     def test_one_entry(self):
         m = HashTable(10)
@@ -45,7 +46,7 @@ class TestHashTable(unittest.TestCase):
             m.put(i, i**2)
         m.del_(1)
         self.assertEqual(None, m.get(1))
-        self.assertEqual(4,m.get(2))
+        self.assertEqual(4, m.get(2))
 
     def test_delete_key_and_reassign(self):
         m = HashTable(10)
@@ -91,9 +92,9 @@ class TestHashTable(unittest.TestCase):
     def test_fill_up_the_limit(self):
         m = HashTable(10)
         for i in range(10):
-            m.put(i,i**2)
+            m.put(i, i**2)
         for i in range(10):
-            self.assertEqual(i**2,m.get(i))
+            self.assertEqual(i**2, m.get(i))
 
 
 class TestSeparateChainingHashTable(unittest.TestCase):
@@ -165,18 +166,20 @@ class TestIsSomorphic(unittest.TestCase):
         self.assertFalse(is_isomorphic("foo", "bar"))
         self.assertTrue(is_isomorphic("paper", "title"))
 
+
 class TestLongestPalindromicSubsequence(unittest.TestCase):
     def test_longest_palindromic_subsequence_is_correct(self):
-        self.assertEqual(3,longest_palindromic_subsequence('BBABCBCAB'))
-        self.assertEqual(4,longest_palindromic_subsequence('abbaeae'))
-        self.assertEqual(7,longest_palindromic_subsequence('babbbababaa'))
-        self.assertEqual(4,longest_palindromic_subsequence('daccandeeja'))
+        self.assertEqual(3, longest_palindromic_subsequence('BBABCBCAB'))
+        self.assertEqual(4, longest_palindromic_subsequence('abbaeae'))
+        self.assertEqual(7, longest_palindromic_subsequence('babbbababaa'))
+        self.assertEqual(4, longest_palindromic_subsequence('daccandeeja'))
 
     def test_longest_palindromic_subsequence_is_incorrect(self):
-        self.assertNotEqual(4,longest_palindromic_subsequence('BBABCBCAB'))
-        self.assertNotEqual(5,longest_palindromic_subsequence('abbaeae'))
-        self.assertNotEqual(2,longest_palindromic_subsequence('babbbababaa'))
-        self.assertNotEqual(1,longest_palindromic_subsequence('daccandeeja'))
+        self.assertNotEqual(4, longest_palindromic_subsequence('BBABCBCAB'))
+        self.assertNotEqual(5, longest_palindromic_subsequence('abbaeae'))
+        self.assertNotEqual(2, longest_palindromic_subsequence('babbbababaa'))
+        self.assertNotEqual(1, longest_palindromic_subsequence('daccandeeja'))
+
 
 class TestIsAnagram(unittest.TestCase):
     def test_is_anagram(self):
@@ -184,7 +187,5 @@ class TestIsAnagram(unittest.TestCase):
         self.assertFalse(is_anagram("rat", "car"))
 
 
-
-
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests/test_maths.py b/tests/test_maths.py
index 967cf64..ec8f657 100644
--- a/tests/test_maths.py
+++ b/tests/test_maths.py
@@ -22,9 +22,7 @@ from algorithms.maths import (
     magic_number,
     find_order,
     find_primitive_root,
-    alice_private_key, alice_public_key, bob_private_key, bob_public_key, alice_shared_key, bob_shared_key, diffie_hellman_key_exchange,
     num_digits,
-    alice_private_key, alice_public_key, bob_private_key, bob_public_key, alice_shared_key, bob_shared_key,
     diffie_hellman_key_exchange, krishnamurthy_number,
     chinese_remainder_theorem,
 )
@@ -131,13 +129,15 @@ class TestGcd(unittest.TestCase):
         self.assertEqual(1, gcd(13, 17))
 
     def test_gcd_non_integer_input(self):
-        with pytest.raises(ValueError, match=r"Input arguments are not integers"):
+        with pytest.raises(ValueError,
+                           match=r"Input arguments are not integers"):
             gcd(1.0, 5)
             gcd(5, 6.7)
             gcd(33.8649, 6.12312312)
 
     def test_gcd_zero_input(self):
-        with pytest.raises(ValueError, match=r"One or more input arguments equals zero"):
+        with pytest.raises(ValueError,
+                           match=r"One or more input arguments equals zero"):
             gcd(0, 12)
             gcd(12, 0)
             gcd(0, 0)
@@ -157,7 +157,8 @@ class TestGcd(unittest.TestCase):
         self.assertEqual(1, lcm(-1, 1))
 
     def test_lcm_zero_input(self):
-        with pytest.raises(ValueError, match=r"One or more input arguments equals zero"):
+        with pytest.raises(ValueError,
+                           match=r"One or more input arguments equals zero"):
             lcm(0, 12)
             lcm(12, 0)
             lcm(0, 0)
@@ -171,7 +172,6 @@ class TestGcd(unittest.TestCase):
         self.assertEqual(1, gcd(13, 17))
 
 
-
 class TestGenerateStroboGrammatic(unittest.TestCase):
     """[summary]
     Test for the file generate_strobogrammatic.py
@@ -216,7 +216,8 @@ class TestModularInverse(unittest.TestCase):
         # checks if x * x_inv == 1 (mod m)
         self.assertEqual(1, 2 * modular_inverse.modular_inverse(2, 19) % 19)
         self.assertEqual(1, 53 * modular_inverse.modular_inverse(53, 91) % 91)
-        self.assertEqual(1, 2 * modular_inverse.modular_inverse(2, 1000000007) % 1000000007)
+        self.assertEqual(1, 2 * modular_inverse.modular_inverse(2, 1000000007)
+                         % 1000000007)
         self.assertRaises(ValueError, modular_inverse.modular_inverse, 2, 20)
 
 
@@ -295,7 +296,8 @@ class TestPythagoras(unittest.TestCase):
     """
 
     def test_pythagoras(self):
-        self.assertEqual("Hypotenuse = 3.605551275463989", pythagoras(3, 2, "?"))
+        self.assertEqual("Hypotenuse = 3.605551275463989",
+                         pythagoras(3, 2, "?"))
 
 
 class TestRabinMiller(unittest.TestCase):
@@ -417,7 +419,8 @@ class TestFindPrimitiveRoot(unittest.TestCase):
         self.assertListEqual([0], find_primitive_root(1))
         self.assertListEqual([2, 3], find_primitive_root(5))
         self.assertListEqual([], find_primitive_root(24))
-        self.assertListEqual([2, 5, 13, 15, 17, 18, 19, 20, 22, 24, 32, 35], find_primitive_root(37))
+        self.assertListEqual([2, 5, 13, 15, 17, 18, 19, 20, 22, 24, 32, 35],
+                             find_primitive_root(37))
 
 
 class TestFindOrder(unittest.TestCase):
@@ -434,6 +437,7 @@ class TestFindOrder(unittest.TestCase):
         self.assertEqual(-1, find_order(128, 256))
         self.assertEqual(352, find_order(3, 353))
 
+
 class TestKrishnamurthyNumber(unittest.TestCase):
     """[summary]
     Test for the file krishnamurthy_number.py
@@ -441,7 +445,7 @@ class TestKrishnamurthyNumber(unittest.TestCase):
     Arguments:
         unittest {[type]} -- [description]
     """
-    
+
     def test_krishnamurthy_number(self):
         self.assertFalse(krishnamurthy_number(0))
         self.assertTrue(krishnamurthy_number(2))
@@ -490,12 +494,13 @@ class TestNumberOfDigits(unittest.TestCase):
         unittest {[type]} -- [description]
     """
     def test_num_digits(self):
-        self.assertEqual(2,num_digits(12))
-        self.assertEqual(5,num_digits(99999))
-        self.assertEqual(1,num_digits(8))
-        self.assertEqual(1,num_digits(0))        
-        self.assertEqual(1,num_digits(-5))
-        self.assertEqual(3,num_digits(-254))
+        self.assertEqual(2, num_digits(12))
+        self.assertEqual(5, num_digits(99999))
+        self.assertEqual(1, num_digits(8))
+        self.assertEqual(1, num_digits(0))
+        self.assertEqual(1, num_digits(-5))
+        self.assertEqual(3, num_digits(-254))
+
 
 class TestChineseRemainderSolver(unittest.TestCase):
     def test_k_three(self):
@@ -504,7 +509,8 @@ class TestChineseRemainderSolver(unittest.TestCase):
         # solves the system of equations
         num = [3, 7, 10]
         rem = [2, 3, 3]
-        self.assertEqual(chinese_remainder_theorem.solve_chinese_remainder(num, rem), 143)
+        self.assertEqual(chinese_remainder_theorem.
+                         solve_chinese_remainder(num, rem), 143)
 
     def test_k_five(self):
         # Example which should give the answer 3383
@@ -512,7 +518,8 @@ class TestChineseRemainderSolver(unittest.TestCase):
         # solves the system of equations
         num = [3, 5, 7, 11, 26]
         rem = [2, 3, 2, 6, 3]
-        self.assertEqual(chinese_remainder_theorem.solve_chinese_remainder(num, rem), 3383)
+        self.assertEqual(chinese_remainder_theorem.
+                         solve_chinese_remainder(num, rem), 3383)
 
     def test_exception_non_coprime(self):
         # There should be an exception when all
@@ -528,5 +535,6 @@ class TestChineseRemainderSolver(unittest.TestCase):
         with self.assertRaises(Exception):
             chinese_remainder_theorem.solve_chinese_remainder(num, rem)
 
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests/test_matrix.py b/tests/test_matrix.py
index 667dc16..262fdbe 100644
--- a/tests/test_matrix.py
+++ b/tests/test_matrix.py
@@ -51,16 +51,20 @@ class TestCopyTransform(unittest.TestCase):
 
     def test_copy_transform(self):
         self.assertEqual(copy_transform.rotate_clockwise(
-            [[1, 2, 3], [4, 5, 6], [7, 8, 9]]), [[7, 4, 1], [8, 5, 2], [9, 6, 3]])
+            [[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
+            [[7, 4, 1], [8, 5, 2], [9, 6, 3]])
 
         self.assertEqual(copy_transform.rotate_counterclockwise(
-            [[1, 2, 3], [4, 5, 6], [7, 8, 9]]), [[3, 6, 9], [2, 5, 8], [1, 4, 7]])
+            [[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
+            [[3, 6, 9], [2, 5, 8], [1, 4, 7]])
 
         self.assertEqual(copy_transform.top_left_invert(
-            [[1, 2, 3], [4, 5, 6], [7, 8, 9]]), [[1, 4, 7], [2, 5, 8], [3, 6, 9]])
+            [[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
+            [[1, 4, 7], [2, 5, 8], [3, 6, 9]])
 
         self.assertEqual(copy_transform.bottom_left_invert(
-            [[1, 2, 3], [4, 5, 6], [7, 8, 9]]), [[9, 6, 3], [8, 5, 2], [7, 4, 1]])
+            [[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
+            [[9, 6, 3], [8, 5, 2], [7, 4, 1]])
 
 
 class TestCroutMatrixDecomposition(unittest.TestCase):
@@ -95,7 +99,8 @@ class TestCroutMatrixDecomposition(unittest.TestCase):
                            [0, 0, 1.0, 0.0],
                            [0, 0, 0, 1.0]]),
                          crout_matrix_decomposition.crout_matrix_decomposition(
-                             [[2, 1, 3, 1], [4, 1, 4, 1], [6, 1, 7, 1], [8, 1, 9, 1]]))
+                             [[2, 1, 3, 1], [4, 1, 4, 1], [6, 1, 7, 1],
+                              [8, 1, 9, 1]]))
 
 
 class TestCholeskyMatrixDecomposition(unittest.TestCase):
@@ -119,14 +124,16 @@ class TestCholeskyMatrixDecomposition(unittest.TestCase):
 
         self.assertEqual(None,
                          cholesky_matrix_decomposition.cholesky_decomposition(
-                             [[4, 12, -16], [12, 37, -43], [-16, -43, 98], [1, 2, 3]]))
+                             [[4, 12, -16], [12, 37, -43], [-16, -43, 98],
+                              [1, 2, 3]]))
 
         # example taken from https://ece.uwaterloo.ca/~dwharder/NumericalAnalysis/04LinearAlgebra/cholesky/
         self.assertEqual([[2.23606797749979, 0.0, 0.0, 0.0],
                           [0.5366563145999494, 2.389979079406345, 0.0, 0.0],
                           [0.13416407864998736, -0.19749126846635062,
                               2.818332343581848, 0.0],
-                          [-0.2683281572999747, 0.43682390737048743, 0.64657701271919, 3.052723872310221]],
+                          [-0.2683281572999747, 0.43682390737048743,
+                           0.64657701271919, 3.052723872310221]],
                          cholesky_matrix_decomposition.cholesky_decomposition(
                              [[5, 1.2, 0.3, -0.6], [1.2, 6, -0.4, 0.9],
                               [0.3, -0.4, 8, 1.7], [-0.6, 0.9, 1.7, 10]]))
@@ -160,11 +167,16 @@ class TestInversion(unittest.TestCase):
         self.assertEqual(matrix_inversion.invert_matrix(m5), [[-4]])
 
         m6 = [[3, 5, 1], [2, 5, 0], [1, 9, 8]]
-        self.assertEqual(matrix_inversion.invert_matrix(m6), [[Fraction(40, 53), Fraction(-31, 53), Fraction(-5, 53)],
-                                                              [Fraction(-16, 53), Fraction(
-                                                                  23, 53), Fraction(2, 53)],
-                                                              [Fraction(13, 53), Fraction(-22, 53), Fraction(5, 53)]])
-
+        self.assertEqual(matrix_inversion.invert_matrix(m6),
+                         [[Fraction(40, 53),
+                           Fraction(-31, 53),
+                           Fraction(-5, 53)],
+                          [Fraction(-16, 53),
+                           Fraction(23, 53),
+                           Fraction(2, 53)],
+                          [Fraction(13, 53),
+                           Fraction(-22, 53),
+                           Fraction(5, 53)]])
 
 
 class TestMatrixExponentiation(unittest.TestCase):
@@ -179,16 +191,16 @@ class TestMatrixExponentiation(unittest.TestCase):
         mat = [[1, 0, 2], [2, 1, 0], [0, 2, 1]]
 
         self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 0),
-            [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
+                         [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
 
         self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 1),
-            [[1, 0, 2], [2, 1, 0], [0, 2, 1]])
+                         [[1, 0, 2], [2, 1, 0], [0, 2, 1]])
 
         self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 2),
-            [[1, 4, 4], [4, 1, 4], [4, 4, 1]])
+                         [[1, 4, 4], [4, 1, 4], [4, 4, 1]])
 
         self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 5),
-            [[81, 72, 90], [90, 81, 72], [72, 90, 81]])
+                         [[81, 72, 90], [90, 81, 72], [72, 90, 81]])
 
 
 class TestMultiply(unittest.TestCase):
@@ -214,7 +226,8 @@ class TestRotateImage(unittest.TestCase):
 
     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]])
+            [[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
+            [[7, 4, 1], [8, 5, 2], [9, 6, 3]])
 
 
 class TestSparseDotVector(unittest.TestCase):
@@ -226,8 +239,12 @@ class TestSparseDotVector(unittest.TestCase):
     """
 
     def test_sparse_dot_vector(self):
-        self.assertEqual(sparse_dot_vector.dot_product(sparse_dot_vector.vector_to_index_value_list(
-            [1., 2., 3.]), sparse_dot_vector.vector_to_index_value_list([0., 2., 2.])), 10)
+        self.assertEqual(sparse_dot_vector.
+                         dot_product(sparse_dot_vector.
+                                     vector_to_index_value_list([1., 2., 3.]),
+                                     sparse_dot_vector.
+                                     vector_to_index_value_list([0., 2., 2.])),
+                         10)
 
 
 class TestSpiralTraversal(unittest.TestCase):
diff --git a/tests/test_ml.py b/tests/test_ml.py
index 61852ec..1622ae1 100644
--- a/tests/test_ml.py
+++ b/tests/test_ml.py
@@ -5,27 +5,36 @@ from algorithms.ml.nearest_neighbor import (
 
 import unittest
 
+
 class TestML(unittest.TestCase):
     def setUp(self):
         # train set for the AND-function
-        self.trainSetAND = {(0,0) : 0, (0,1) :0, (1,0) : 0, (1,1) : 1} 
+        self.trainSetAND = {(0, 0): 0, (0, 1): 0, (1, 0): 0, (1, 1): 1}
 
         # train set for light or dark colors
-        self.trainSetLight = {(11, 98, 237) : 'L', (3, 39, 96) : 'D', (242, 226, 12) : 'L', (99, 93, 4) : 'D',
-        (232, 62, 32) : 'L', (119, 28, 11) : 'D', (25, 214, 47) : 'L', (89, 136, 247) : 'L',
-        (21, 34, 63) : 'D', (237, 99, 120) : 'L', (73, 33, 39) : 'D'}
+        self.trainSetLight = {(11, 98, 237): 'L', (3, 39, 96): 'D',
+                              (242, 226, 12): 'L', (99, 93, 4): 'D',
+                              (232, 62, 32): 'L', (119, 28, 11): 'D',
+                              (25, 214, 47): 'L', (89, 136, 247): 'L',
+                              (21, 34, 63): 'D', (237, 99, 120): 'L',
+                              (73, 33, 39): 'D'}
+
     def test_nearest_neighbor(self):
         # AND-function
-        self.assertEqual(nearest_neighbor((1,1), self.trainSetAND), 1)
-        self.assertEqual(nearest_neighbor((0,1), self.trainSetAND), 0)
+        self.assertEqual(nearest_neighbor((1, 1), self.trainSetAND), 1)
+        self.assertEqual(nearest_neighbor((0, 1), self.trainSetAND), 0)
 
         # dark/light color test
-        self.assertEqual(nearest_neighbor((31, 242, 164), self.trainSetLight), 'L')
-        self.assertEqual(nearest_neighbor((13, 94, 64), self.trainSetLight), 'D')
-        self.assertEqual(nearest_neighbor((230, 52, 239), self.trainSetLight), 'L')
+        self.assertEqual(nearest_neighbor((31, 242, 164),
+                                          self.trainSetLight), 'L')
+        self.assertEqual(nearest_neighbor((13, 94, 64),
+                                          self.trainSetLight), 'D')
+        self.assertEqual(nearest_neighbor((230, 52, 239),
+                                          self.trainSetLight), 'L')
+
     def test_distance(self):
-        self.assertAlmostEqual(distance((1,2,3), (1,0,-1)), 4.47, 2)
+        self.assertAlmostEqual(distance((1, 2, 3), (1, 0, -1)), 4.47, 2)
+
 
-        
 if __name__ == "__main__":
-    unittest.main()
\ No newline at end of file
+    unittest.main()
diff --git a/tests/test_monomial.py b/tests/test_monomial.py
index 8e4667d..31e56f7 100644
--- a/tests/test_monomial.py
+++ b/tests/test_monomial.py
@@ -5,8 +5,9 @@ import math
 
 import unittest
 
+
 class TestSuite(unittest.TestCase):
-	
+
 	def setUp(self):
 		self.m1 = Monomial({})
 		self.m2 = Monomial({1: 1}, 2)
@@ -15,7 +16,7 @@ class TestSuite(unittest.TestCase):
 		self.m5 = Monomial({2: 1, 3: 0}, Fraction(2, 3))
 		self.m6 = Monomial({1: 0, 2: 0, 3: 0}, -2.27)
 		self.m7 = Monomial({1: 2, 7: 2}, -math.pi)
-		self.m8 = Monomial({150: 5, 170: 2, 10000:3}, 0)
+		self.m8 = Monomial({150: 5, 170: 2, 10000: 3}, 0)
 		self.m9 = 2
 		self.m10 = math.pi
 		self.m11 = Fraction(3, 8)
@@ -39,10 +40,11 @@ class TestSuite(unittest.TestCase):
 
 		# Zero monomial + Zero monomial = Zero monomial
 		self.assertEqual(self.m1 + self.m1, self.m1)
-		
+
 		# Coefficient float.
-		self.assertEqual(self.m7 + self.m7, Monomial({1: 2, 7: 2}, -2*math.pi))
-		
+		self.assertEqual(self.m7 + self.m7, Monomial({1: 2, 7: 2},
+		                                             -2 * math.pi))
+
 		# Coefficient 0 so should equal the zero monomial.
 		self.assertEqual(self.m8, self.m1)
 
@@ -77,13 +79,13 @@ class TestSuite(unittest.TestCase):
 
 		# Zero monomial - Zero monomial = Zero monomial
 		self.assertEqual(self.m1 - self.m1, self.m1)
-		
+
 		# Coefficient int.
 		self.assertEqual(self.m2 - self.m15, Monomial({1: 1}, -1))
-		
-		# Coefficient float.
-		self.assertEqual(self.m16 - self.m7, Monomial({1: 2, 7: 2}, 2*math.pi))
 
+		# Coefficient float.
+		self.assertEqual(self.m16 - self.m7, Monomial({1: 2, 7: 2},
+		                                              2 * math.pi))
 
 		# The constant term cannot be added to any monomial
 		# that has any variables.
@@ -103,7 +105,7 @@ class TestSuite(unittest.TestCase):
 		return
 
 	def test_monomial_multiplication(self):
-		
+
 		# Usual multiplication.
 		# The positive and negative powers of the same variable
 		# should cancel out.
@@ -116,7 +118,8 @@ class TestSuite(unittest.TestCase):
 		self.assertEqual(self.m1 * self.m2, self.m1)
 
 		# Test usual float multiplication.
-		self.assertEqual(self.m7 * self.m3, Monomial({1: 4, 2: -1, 7: 2}, -1.5*math.pi))
+		self.assertEqual(self.m7 * self.m3, Monomial({1: 4, 2: -1, 7: 2},
+		                                             -1.5*math.pi))
 
 		return
 
@@ -125,10 +128,11 @@ class TestSuite(unittest.TestCase):
 		# The Zero monomial is not invertible.
 		self.assertRaises(ValueError, lambda x: x.inverse(), self.m1)
 		self.assertRaises(ValueError, lambda x: x.inverse(), self.m8)
-		self.assertRaises(ValueError, lambda x: x.inverse(), Monomial({},self.m12))
+		self.assertRaises(ValueError, lambda x: x.inverse(),
+		                  Monomial({}, self.m12))
 
 		# Check some inverses.
-		self.assertEqual(self.m7.inverse(), Monomial({1: -2, 7: -2}, -1/math.pi))
+		self.assertEqual(self.m7.inverse(), Monomial({1: -2, 7: -2}, -1 / math.pi))
 
 		# Doesn't matter if the coefficient is Fraction or float.
 		# Both should be treated as same.
@@ -142,31 +146,41 @@ class TestSuite(unittest.TestCase):
 
 	def test_monomial_division(self):
 		# Any monomial divided by the Zero Monomial should raise a ValueError.
-		self.assertRaises(ValueError, lambda x, y: x.__truediv__(y), self.m2, self.m1)
-		self.assertRaises(ValueError, lambda x, y: x.__truediv__(y), self.m2, self.m8)
-		self.assertRaises(ValueError, lambda x, y: x.__truediv__(y), self.m2, self.m12)
+		self.assertRaises(ValueError, lambda x, y: x.__truediv__(y),
+		                  self.m2, self.m1)
+		self.assertRaises(ValueError, lambda x, y: x.__truediv__(y),
+		                  self.m2, self.m8)
+		self.assertRaises(ValueError, lambda x, y: x.__truediv__(y),
+		                  self.m2, self.m12)
 
 		# Test some usual cases.
-		self.assertEqual(self.m7 / self.m3, Monomial({2: 1, 7: 2}, -2*math.pi/3))
+		self.assertEqual(self.m7 / self.m3, Monomial({2: 1, 7: 2},
+		                                             -2 * math.pi / 3))
 		self.assertEqual(self.m14 / self.m13, Monomial({1: 1}) * Fraction(-3, 2))
 
 		return
 
 	def test_monomial_substitution(self):
 		# Test with int.
-		self.assertAlmostEqual(self.m7.substitute(2), -16*math.pi, delta=1e-9)
+		self.assertAlmostEqual(self.m7.substitute(2), -16 * math.pi, delta=1e-9)
 		# Test with float.
-		self.assertAlmostEqual(self.m7.substitute(1.5), (1.5 ** 4)* -math.pi, delta=1e-9)
+		self.assertAlmostEqual(self.m7.substitute(1.5), (1.5 ** 4) * -math.pi,
+		                       delta=1e-9)
 		# Test with Fraction.
-		self.assertAlmostEqual(self.m7.substitute(Fraction(-1, 2)), (Fraction(-1, 2) ** 4)*-math.pi, delta=1e-9)
+		self.assertAlmostEqual(self.m7.substitute(Fraction(-1, 2)),
+		                       (Fraction(-1, 2) ** 4)*-math.pi, delta=1e-9)
 		# Test with a complete substitution map.
-		self.assertAlmostEqual(self.m7.substitute({1: 3, 7: 0}), (3 ** 2) * (0 ** 2) * -math.pi, delta=1e-9)
+		self.assertAlmostEqual(self.m7.substitute({1: 3, 7: 0}),
+		                       (3 ** 2) * (0 ** 2) * -math.pi, delta=1e-9)
 		# Test with a more than complete substitution map.
-		self.assertAlmostEqual(self.m7.substitute({1: 3, 7: 0, 2: 2}), (3 ** 2) * (0 ** 2) * -math.pi, delta=1e-9)
-		
+		self.assertAlmostEqual(self.m7.substitute({1: 3, 7: 0, 2: 2}),
+		                       (3 ** 2) * (0 ** 2) * -math.pi, delta=1e-9)
+
 		# Should raise a ValueError if not enough variables are supplied!
-		self.assertRaises(ValueError, lambda x, y: x.substitute(y), self.m7, {1: 3, 2: 2})
-		self.assertRaises(ValueError, lambda x, y: x.substitute(y), self.m7, {2: 2})
+		self.assertRaises(ValueError, lambda x, y: x.substitute(y), self.m7,
+		                  {1: 3, 2: 2})
+		self.assertRaises(ValueError, lambda x, y: x.substitute(y), self.m7,
+		                  {2: 2})
 
 		# The zero monomial always gives zero upon substitution.
 		self.assertEqual(self.m8.substitute(2), 0)
@@ -193,7 +207,7 @@ class TestSuite(unittest.TestCase):
 		# and same coefficient.
 		self.assertEqual(self.m3, self.m3.clone())
 
-		# The zero monomial is identified and 
+		# The zero monomial is identified and
 		# always clones to itself.
 		self.assertEqual(self.m1, self.m8.clone())
 		self.assertEqual(self.m1, self.m1.clone())
@@ -203,4 +217,4 @@ class TestSuite(unittest.TestCase):
 
 
 if __name__ == '__main__':
-	unittest.main()
\ No newline at end of file
+	unittest.main()
diff --git a/tests/test_queues.py b/tests/test_queues.py
index b5b49ef..5a2f4c8 100644
--- a/tests/test_queues.py
+++ b/tests/test_queues.py
@@ -80,13 +80,16 @@ class TestSuite(unittest.TestCase):
         self.assertEqual(max_sliding_window(array, k=7), [6, 7])
 
         array = [8, 5, 10, 7, 9, 4, 15, 12, 90, 13]
-        self.assertEqual(max_sliding_window(array, k=4), [10, 10, 10, 15, 15, 90, 90])
+        self.assertEqual(max_sliding_window(array, k=4),
+                         [10, 10, 10, 15, 15, 90, 90])
         self.assertEqual(max_sliding_window(array, k=7), [15, 15, 90, 90])
-        self.assertEqual(max_sliding_window(array, k=2), [8, 10, 10, 9, 9, 15, 15, 90, 90])
+        self.assertEqual(max_sliding_window(array, k=2),
+                         [8, 10, 10, 9, 9, 15, 15, 90, 90])
 
     def test_reconstruct_queue(self):
         self.assertEqual([[5, 0], [7, 0], [5, 2], [6, 1], [4, 4], [7, 1]],
-                         reconstruct_queue([[7, 0], [4, 4], [7, 1], [5, 0], [6, 1], [5, 2]]))
+                         reconstruct_queue([[7, 0], [4, 4], [7, 1], [5, 0],
+                                           [6, 1], [5, 2]]))
 
 
 class TestPriorityQueue(unittest.TestCase):
diff --git a/tests/test_search.py b/tests/test_search.py
index d1ea822..8f95550 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -42,7 +42,7 @@ class TestSuite(unittest.TestCase):
         self.assertEqual(11, binary_search_recur(array, 0, 11, 6))
         self.assertEqual(-1, binary_search_recur(array, 0, 11, 7))
         self.assertEqual(-1, binary_search_recur(array, 0, 11, -1))
-    
+
     def test_ternary_search(self):
         array = [1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 6]
         self.assertEqual(10, ternary_search(0, 11, 5, array))
@@ -50,7 +50,6 @@ class TestSuite(unittest.TestCase):
         self.assertEqual(-1, ternary_search(0, 10, 5, array))
         self.assertEqual(-1, ternary_search(0, 11, 7, array))
         self.assertEqual(-1, ternary_search(0, 11, -1, array))
-        
 
     def test_last_occurrence(self):
         array = [1, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 6, 6, 6]
diff --git a/tests/test_set.py b/tests/test_set.py
index 37aea6f..e2985c9 100644
--- a/tests/test_set.py
+++ b/tests/test_set.py
@@ -4,7 +4,9 @@ from algorithms.set import (
 
 import unittest
 
+
 class TestFindKeyboardRow(unittest.TestCase):
     def test_find_keyboard_row(self):
         self.assertEqual(["Alaska", "Dad"],
-                         find_keyboard_row(["Hello", "Alaska", "Dad", "Peace"]))
+                         find_keyboard_row(["Hello", "Alaska",
+                                           "Dad", "Peace"]))
diff --git a/tests/test_sort.py b/tests/test_sort.py
index 2c23ab8..c80290f 100644
--- a/tests/test_sort.py
+++ b/tests/test_sort.py
@@ -7,7 +7,6 @@ from algorithms.sort import (
     cycle_sort,
     exchange_sort,
     max_heap_sort, min_heap_sort,
-    insertion_sort,
     merge_sort,
     pancake_sort,
     pigeonhole_sort,
@@ -42,7 +41,8 @@ class TestSuite(unittest.TestCase):
         self.assertTrue(is_sorted(bogo_sort([1, 23, 5])))
 
     def test_bitonic_sort(self):
-        self.assertTrue(is_sorted(bitonic_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+        self.assertTrue(is_sorted(bitonic_sort([1, 3, 2, 5, 65,
+                                                23, 57, 1232])))
 
     def test_bubble_sort(self):
         self.assertTrue(is_sorted(bubble_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
@@ -51,36 +51,43 @@ class TestSuite(unittest.TestCase):
         self.assertTrue(is_sorted(comb_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
 
     def test_counting_sort(self):
-        self.assertTrue(is_sorted(counting_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+        self.assertTrue(is_sorted(counting_sort([1, 3, 2, 5, 65,
+                                                 23, 57, 1232])))
 
     def test_cycle_sort(self):
         self.assertTrue(is_sorted(cycle_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
 
     def test_exchange_sort(self):
-        self.assertTrue(is_sorted(exchange_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
-    
+        self.assertTrue(is_sorted(exchange_sort([1, 3, 2, 5, 65,
+                                                 23, 57, 1232])))
+
     def test_heap_sort(self):
-        self.assertTrue(is_sorted(max_heap_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+        self.assertTrue(is_sorted(max_heap_sort([1, 3, 2, 5, 65,
+                                                 23, 57, 1232])))
 
-        self.assertTrue(is_sorted(min_heap_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+        self.assertTrue(is_sorted(min_heap_sort([1, 3, 2, 5, 65,
+                                                 23, 57, 1232])))
 
     def test_insertion_sort(self):
-        self.assertTrue(is_sorted(bitonic_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+        self.assertTrue(is_sorted(bitonic_sort([1, 3, 2, 5, 65,
+                                                23, 57, 1232])))
 
     def test_merge_sort(self):
         self.assertTrue(is_sorted(merge_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
 
     def test_pancake_sort(self):
-        self.assertTrue(is_sorted(pancake_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
-        
+        self.assertTrue(is_sorted(pancake_sort([1, 3, 2, 5, 65,
+                                                23, 57, 1232])))
+
     def test_pigeonhole_sort(self):
         self.assertTrue(is_sorted(pigeonhole_sort([1, 5, 65, 23, 57, 1232])))
-        
+
     def test_quick_sort(self):
         self.assertTrue(is_sorted(quick_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
 
     def test_selection_sort(self):
-        self.assertTrue(is_sorted(selection_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+        self.assertTrue(is_sorted(selection_sort([1, 3, 2, 5, 65,
+                                                  23, 57, 1232])))
 
     def test_bucket_sort(self):
         self.assertTrue(is_sorted(bucket_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
@@ -95,24 +102,25 @@ class TestSuite(unittest.TestCase):
         self.assertTrue(is_sorted(gnome_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
 
     def test_cocktail_shaker_sort(self):
-        self.assertTrue(is_sorted(cocktail_shaker_sort([1, 3, 2, 5, 65, 23, 57, 1232])))
+        self.assertTrue(is_sorted(cocktail_shaker_sort([1, 3, 2, 5, 65,
+                                                        23, 57, 1232])))
 
 
 class TestTopSort(unittest.TestCase):
     def setUp(self):
         self.depGraph = {
-                            "a" : [ "b" ],
-                            "b" : [ "c" ],
-                            "c" :  [ 'e'],
-                            'e' : [ 'g' ],
-                            "d" : [ ],
-                            "f" : ["e" , "d"],
-                            "g" : [ ]
+                            "a": ["b"],
+                            "b": ["c"],
+                            "c": ['e'],
+                            'e': ['g'],
+                            "d": [],
+                            "f": ["e", "d"],
+                            "g": []
                         }
 
     def test_topsort(self):
         res = top_sort_recursive(self.depGraph)
-        #print(res)
+        # print(res)
         self.assertTrue(res.index('g') < res.index('e'))
         res = top_sort(self.depGraph)
         self.assertTrue(res.index('g') < res.index('e'))
diff --git a/tests/test_stack.py b/tests/test_stack.py
index 78822bc..93b3897 100644
--- a/tests/test_stack.py
+++ b/tests/test_stack.py
@@ -11,6 +11,8 @@ from algorithms.stack import (
 )
 
 import unittest
+
+
 class TestSuite(unittest.TestCase):
     def test_is_consecutive(self):
         self.assertTrue(first_is_consecutive([3, 4, 5, 6, 7]))
@@ -133,6 +135,7 @@ class TestStack(unittest.TestCase):
 
         self.assertTrue(stack.is_empty())
 
+
 class TestOrderedStack(unittest.TestCase):
     def test_OrderedStack(self):
         stack = OrderedStack()
diff --git a/tests/test_streaming.py b/tests/test_streaming.py
index 701b5f4..2f59827 100644
--- a/tests/test_streaming.py
+++ b/tests/test_streaming.py
@@ -9,22 +9,33 @@ import unittest
 
 class TestMisraGreis(unittest.TestCase):
     def test_misra_correct(self):
-        self.assertEqual({'4':5},misras_gries([1,4,4,4,5,4,4]))
-        self.assertEqual({'1':4},misras_gries([0,0,0,1,1,1,1]))
-        self.assertEqual({'0':4,'1':3},misras_gries([0,0,0,0,1,1,1,2,2],3))
-        
+        self.assertEqual({'4': 5}, misras_gries([1, 4, 4, 4, 5, 4, 4]))
+        self.assertEqual({'1': 4}, misras_gries([0, 0, 0, 1, 1, 1, 1]))
+        self.assertEqual({'0': 4, '1': 3}, misras_gries([0, 0, 0, 0, 1, 1,
+                                                         1, 2, 2], 3))
+
     def test_misra_incorrect(self):
-        self.assertEqual(None,misras_gries([1,2,5,4,5,4,4,5,4,4,5]))
-        self.assertEqual(None,misras_gries([0,0,0,2,1,1,1]))
-        self.assertEqual(None,misras_gries([0,0,0,1,1,1]))
+        self.assertEqual(None, misras_gries([1, 2, 5, 4, 5, 4, 4, 5, 4, 4, 5]))
+        self.assertEqual(None, misras_gries([0, 0, 0, 2, 1, 1, 1]))
+        self.assertEqual(None, misras_gries([0, 0, 0, 1, 1, 1]))
+
 
 class TestOneSparse(unittest.TestCase):
     def test_one_sparse_correct(self):
-        self.assertEqual(4,one_sparse([(4,'+'), (2,'+'),(2,'-'),(4,'+'),(3,'+'),(3,'-')]))
-        self.assertEqual(2,one_sparse([(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'+')]))
-
+        self.assertEqual(4, one_sparse([(4, '+'), (2, '+'), (2, '-'),
+                                        (4, '+'), (3, '+'), (3, '-')]))
+        self.assertEqual(2, one_sparse([(2, '+'), (2, '+'), (2, '+'),
+                                        (2, '+'), (2, '+'), (2, '+'),
+                                        (2, '+')]))
 
     def test_one_sparse_incorrect(self):
-        self.assertEqual(None,one_sparse([(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'+'),(1,'+')])) #Two values remaining
-        self.assertEqual(None,one_sparse([(2,'+'),(2,'+'),(2,'+'),(2,'+'),(2,'-'),(2,'-'),(2,'-'),(2,'-')])) # No values remaining
-        self.assertEqual(None,one_sparse([(2,'+'),(2,'+'),(4,'+'),(4,'+')])) # Bitsum sum of sign is inccorect
+        self.assertEqual(None, one_sparse([(2, '+'), (2, '+'), (2, '+'),
+                                          (2, '+'), (2, '+'), (2, '+'),
+                                          (1, '+')]))  # Two values remaining
+        self.assertEqual(None, one_sparse([(2, '+'), (2, '+'),
+                                          (2, '+'), (2, '+'),
+                                          (2, '-'), (2, '-'), (2, '-'),
+                                          (2, '-')]))  # No values remaining
+        # Bitsum sum of sign is inccorect
+        self.assertEqual(None, one_sparse([(2, '+'), (2, '+'),
+                                          (4, '+'), (4, '+')]))
diff --git a/tests/test_strings.py b/tests/test_strings.py
index 907a389..57f5ff0 100644
--- a/tests/test_strings.py
+++ b/tests/test_strings.py
@@ -8,7 +8,7 @@ from algorithms.strings import (
     group_anagrams,
     int_to_roman,
     is_palindrome, is_palindrome_reverse,
-    is_palindrome_two_pointer, is_palindrome_stack, is_palindrome_deque, 
+    is_palindrome_two_pointer, is_palindrome_stack, is_palindrome_deque,
     is_rotated, is_rotated_v1,
     license_number,
     make_sentence,
@@ -20,9 +20,7 @@ from algorithms.strings import (
     reverse_vowel,
     reverse_words,
     roman_to_int,
-    strip_url_params1, strip_url_params2, strip_url_params3,
-    is_valid_coordinates_0, is_valid_coordinates_1,
-    is_valid_coordinates_regular_expression,
+    is_valid_coordinates_0,
     word_squares,
     convert_morse_word, unique_morse,
     judge_circle,
@@ -34,14 +32,16 @@ from algorithms.strings import (
     repeat_string,
     text_justification,
     min_distance,
-    longest_common_prefix_v1, longest_common_prefix_v2, longest_common_prefix_v3,
+    longest_common_prefix_v1, longest_common_prefix_v2,
+    longest_common_prefix_v3,
     rotate, rotate_alt,
     first_unique_char,
     repeat_substring,
     atbash,
     longest_palindrome,
     knuth_morris_pratt,
-    panagram
+    panagram,
+    fizzbuzz
 )
 
 import unittest
@@ -78,12 +78,17 @@ class TestBreakingBad(unittest.TestCase):
         self.assertEqual(self.result, match_symbol(self.words, self.symbols))
 
     def test_match_symbol_1(self):
-        self.assertEqual(['[Am]azon', 'Mi[cro]soft', 'Goog[le]'], match_symbol_1(self.words, self.symbols))
+        self.assertEqual(['[Am]azon', 'Mi[cro]soft', 'Goog[le]'],
+                         match_symbol_1(self.words, self.symbols))
 
     def test_bracket(self):
-        self.assertEqual(('[Am]azon', 'Mi[cro]soft', 'Goog[le]'), bracket(self.words, self.symbols))
-        self.assertEqual(('Amazon', 'Microsoft', 'Google'), bracket(self.words, ['thisshouldnotmatch']))
-        self.assertEqual(('Amazon', 'M[i]crosoft', 'Google'), bracket(self.words, ['i', 'i']))
+        self.assertEqual(('[Am]azon', 'Mi[cro]soft', 'Goog[le]'),
+                         bracket(self.words, self.symbols))
+        self.assertEqual(('Amazon', 'Microsoft', 'Google'),
+                         bracket(self.words, ['thisshouldnotmatch']))
+        self.assertEqual(('Amazon', 'M[i]crosoft', 'Google'),
+                         bracket(self.words, ['i', 'i']))
+
 
 class TestDecodeString(unittest.TestCase):
     """[summary]
@@ -119,7 +124,8 @@ class TestDomainExtractor(unittest.TestCase):
     """
 
     def test_valid(self):
-        self.assertEqual(domain_name_1("https://github.com/SaadBenn"), "github")
+        self.assertEqual(domain_name_1("https://github.com/SaadBenn"),
+                         "github")
 
     def test_invalid(self):
         self.assertEqual(domain_name_2("http://google.com"), "google")
@@ -137,7 +143,8 @@ class TestEncodeDecode(unittest.TestCase):
         self.assertEqual("4:keon2:is7:awesome", encode("keon is awesome"))
 
     def test_decode(self):
-        self.assertEqual(['keon', 'is', 'awesome'], decode("4:keon2:is7:awesome"))
+        self.assertEqual(['keon', 'is', 'awesome'],
+                         decode("4:keon2:is7:awesome"))
 
 
 class TestGroupAnagrams(unittest.TestCase):
@@ -150,7 +157,8 @@ class TestGroupAnagrams(unittest.TestCase):
 
     def test_group_anagrams(self):
         self.assertEqual([['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']], \
-                         group_anagrams(["eat", "tea", "tan", "ate", "nat", "bat"]))
+                         group_anagrams(["eat", "tea", "tan", "ate", "nat",
+                                        "bat"]))
 
 
 class TestIntToRoman(unittest.TestCase):
@@ -230,7 +238,7 @@ class TestRotated(unittest.TestCase):
         self.assertEqual("hello", rotate("hello", 5))
         self.assertEqual("elloh", rotate("hello", 6))
         self.assertEqual("llohe", rotate("hello", 7))
-        
+
     def test_rotate_alt(self):
         self.assertEqual("llohe", rotate_alt("hello", 2))
         self.assertEqual("hello", rotate_alt("hello", 5))
@@ -399,14 +407,20 @@ class TestRomanToInt(unittest.TestCase):
 #     """
 
 #     def test_strip_url_params1(self):
-#         self.assertEqual(strip_url_params1("www.saadbenn.com?a=1&b=2&a=2"), "www.saadbenn.com?a=1&b=2")
-#         self.assertEqual(strip_url_params1("www.saadbenn.com?a=1&b=2", ['b']), "www.saadbenn.com?a=1")
+#         self.assertEqual(strip_url_params1("www.saadbenn.com?a=1&b=2&a=2"),
+#                         "www.saadbenn.com?a=1&b=2")
+#         self.assertEqual(strip_url_params1("www.saadbenn.com?a=1&b=2",
+#                          ['b']), "www.saadbenn.com?a=1")
 #     def test_strip_url_params2(self):
-#         self.assertEqual(strip_url_params2("www.saadbenn.com?a=1&b=2&a=2"), "www.saadbenn.com?a=1&b=2")
-#         self.assertEqual(strip_url_params2("www.saadbenn.com?a=1&b=2", ['b']), "www.saadbenn.com?a=1")
+#         self.assertEqual(strip_url_params2("www.saadbenn.com?a=1&b=2&a=2"),
+#                         "www.saadbenn.com?a=1&b=2")
+#         self.assertEqual(strip_url_params2("www.saadbenn.com?a=1&b=2",
+#                         'b']), "www.saadbenn.com?a=1")
 #     def test_strip_url_params3(self):
-#         self.assertEqual(strip_url_params3("www.saadbenn.com?a=1&b=2&a=2"), "www.saadbenn.com?a=1&b=2")
-#         self.assertEqual(strip_url_params3("www.saadbenn.com?a=1&b=2", ['b']), "www.saadbenn.com?a=1")
+#         self.assertEqual(strip_url_params3("www.saadbenn.com?a=1&b=2&a=2"),
+#                         "www.saadbenn.com?a=1&b=2")
+#         self.assertEqual(strip_url_params3("www.saadbenn.com?a=1&b=2",
+#                         ['b']), "www.saadbenn.com?a=1")
 
 
 class TestValidateCoordinates(unittest.TestCase):
@@ -423,7 +437,9 @@ class TestValidateCoordinates(unittest.TestCase):
             self.assertTrue(is_valid_coordinates_0(coordinate))
 
     def test_invalid(self):
-        invalid_coordinates = ["23.234, - 23.4234", "99.234, 12.324", "6.325624, 43.34345.345", "0, 1,2", "23.245, 1e1"]
+        invalid_coordinates = ["23.234, - 23.4234", "99.234, 12.324",
+                               "6.325624, 43.34345.345", "0, 1,2",
+                               "23.245, 1e1"]
         for coordinate in invalid_coordinates:
             self.assertFalse(is_valid_coordinates_0(coordinate))
 
@@ -437,8 +453,10 @@ class TestWordSquares(unittest.TestCase):
     """
 
     def test_word_squares(self):
-        self.assertEqual([['wall', 'area', 'lead', 'lady'], ['ball', 'area', 'lead', 'lady']], \
-                         word_squares(["area", "lead", "wall", "lady", "ball"]))
+        self.assertEqual([['wall', 'area', 'lead', 'lady'], ['ball', 'area',
+                         'lead', 'lady']], \
+                         word_squares(["area", "lead", "wall",
+                                      "lady", "ball"]))
 
 
 class TestUniqueMorse(unittest.TestCase):
@@ -467,6 +485,7 @@ class TestCaesarCipher(unittest.TestCase):
         self.assertEqual("Lipps_Asvph!", caesar_cipher("Hello_World!", 4))
         self.assertEqual("okffng-Qwvb", caesar_cipher("middle-Outz", 2))
 
+
 class TestCheckPangram(unittest.TestCase):
     def test_check_pangram(self):
         self.assertTrue(check_pangram("The quick brown fox jumps over the lazy dog"))
@@ -498,47 +517,58 @@ class TestTextJustification(unittest.TestCase):
         self.assertEqual(["This    is    an",
                           "example  of text",
                           "justification.  "],
-
-                         text_justification(["This", "is", "an", "example", "of", "text", "justification."]
-                                            , 16)
+                         text_justification(["This", "is", "an", "example",
+                                             "of", "text",
+                                             "justification."], 16)
                          )
 
         self.assertEqual(["What   must   be",
                           "acknowledgment  ",
                           "shall be        "],
-
-                         text_justification(["What", "must", "be", "acknowledgment", "shall", "be"]
-                                            , 16)
+                         text_justification(["What", "must", "be",
+                                             "acknowledgment", "shall",
+                                             "be"], 16)
                          )
 
+
 class TestMinDistance(unittest.TestCase):
     def test_min_distance(self):
         self.assertEqual(2, min_distance("sea", "eat"))
         self.assertEqual(6, min_distance("abAlgocrithmf", "Algorithmmd"))
 
+
 class TestLongestCommonPrefix(unittest.TestCase):
     def test_longest_common_prefix(self):
         # Test first solution
-        self.assertEqual("fl", longest_common_prefix_v1(["flower","flow","flight"]))
-        self.assertEqual("", longest_common_prefix_v1(["dog","racecar","car"]))
+        self.assertEqual("fl", longest_common_prefix_v1(["flower", "flow",
+                                                        "flight"]))
+        self.assertEqual("", longest_common_prefix_v1(["dog", "racecar",
+                                                      "car"]))
         # Test second solution
-        self.assertEqual("fl", longest_common_prefix_v2(["flower","flow","flight"]))
-        self.assertEqual("", longest_common_prefix_v2(["dog","racecar","car"]))
+        self.assertEqual("fl", longest_common_prefix_v2(["flower", "flow",
+                                                        "flight"]))
+        self.assertEqual("", longest_common_prefix_v2(["dog", "racecar",
+                                                      "car"]))
         # Test third solution
-        self.assertEqual("fl", longest_common_prefix_v3(["flower","flow","flight"]))
-        self.assertEqual("", longest_common_prefix_v3(["dog","racecar","car"]))
+        self.assertEqual("fl", longest_common_prefix_v3(["flower", "flow",
+                                                        "flight"]))
+        self.assertEqual("", longest_common_prefix_v3(["dog", "racecar",
+                                                      "car"]))
+
 
 class TestFirstUniqueChar(unittest.TestCase):
     def test_first_unique_char(self):
         self.assertEqual(0, first_unique_char("leetcode"))
         self.assertEqual(2, first_unique_char("loveleetcode"))
 
+
 class TestRepeatSubstring(unittest.TestCase):
     def test_repeat_substring(self):
         self.assertTrue(repeat_substring("abab"))
         self.assertFalse(repeat_substring("aba"))
         self.assertTrue(repeat_substring("abcabcabcabc"))
 
+
 class TestAtbashCipher(unittest.TestCase):
     """[summary]
     Test for the file atbash_cipher.py
@@ -554,22 +584,19 @@ class TestAtbashCipher(unittest.TestCase):
         self.assertEqual("ZggzXP zg WzdM", atbash("AttaCK at DawN"))
 
 
-
 class TestLongestPalindromicSubstring(unittest.TestCase):
     """[summary]
     Test for the file longest_palindromic_substring.py
-    
     Arguments:
         unittest {[type]} -- [description]
     """
-    
     def test_longest_palindromic_substring(self):
         self.assertEqual("bb", longest_palindrome("cbbd"))
         self.assertEqual("abba", longest_palindrome("abba"))
         self.assertEqual("asdadsa", longest_palindrome("dasdasdasdasdasdadsa"))
         self.assertEqual("abba", longest_palindrome("cabba"))
 
-        
+
 class TestKnuthMorrisPratt(unittest.TestCase):
     """[summary]
     Test for the file knuth_morris_pratt.py
@@ -583,6 +610,8 @@ class TestKnuthMorrisPratt(unittest.TestCase):
         self.assertEqual([0, 1, 2, 3, 4], knuth_morris_pratt("aaaaaaa", "aaa"))
         self.assertEqual([0, 4], knuth_morris_pratt("abcdabc", "abc"))
         self.assertEqual([], knuth_morris_pratt("aabcdaab", "aba"))
+        self.assertEqual([0, 4], knuth_morris_pratt([0,0,1,1,0,0,1,0], [0,0]))
+
 
 class TestPanagram(unittest.TestCase):
     """[summary]
@@ -663,5 +692,33 @@ class TestPanagram(unittest.TestCase):
         self.assertEqual(True, res)
 
 
+class TestFizzbuzz(unittest.TestCase):
+    """[summary]
+    Tests for the fizzbuzz method in file fizzbuzz.py
+    """
+    def test_fizzbuzz(self):
+        # Testing that n < 0 returns a Value Error
+        self.assertRaises(ValueError, fizzbuzz.fizzbuzz, -2)
+
+        # Testing that a string returns a Type Error.
+        self.assertRaises(TypeError, fizzbuzz.fizzbuzz, "hello")
+
+        # Testing a base case, n = 3
+        result = fizzbuzz.fizzbuzz(3)
+        expected = [1, 2, "Fizz"]
+        self.assertEqual(result, expected)
+
+        # Testing a base case, n = 5
+        result = fizzbuzz.fizzbuzz(5)
+        expected = [1, 2, "Fizz", 4, "Buzz"]
+        self.assertEqual(result, expected)
+
+        # Testing a base case, n = 15 i.e. mod 3 and 5
+        result = fizzbuzz.fizzbuzz(15)
+        expected = [1, 2, "Fizz", 4, "Buzz", "Fizz", 7, 8, "Fizz", "Buzz", 11,
+                    "Fizz", 13, 14, "FizzBuzz"]
+        self.assertEqual(result, expected)
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests/test_tree.py b/tests/test_tree.py
index 170a931..c9d0f0f 100644
--- a/tests/test_tree.py
+++ b/tests/test_tree.py
@@ -65,7 +65,8 @@ class TestBTree(unittest.TestCase):
         cls.range = 10000
 
     def setUp(self):
-        self.keys_to_insert = [self.random.randrange(-self.range, self.range) for i in range(self.range)]
+        self.keys_to_insert = [self.random.randrange(-self.range, self.range)
+                               for i in range(self.range)]
 
     def test_insertion_and_find_even_degree(self):
         btree = BTree(4)
@@ -111,16 +112,18 @@ class TestBTree(unittest.TestCase):
         self.assertEqual(btree.root.keys, [])
         self.assertEqual(btree.root.children, [])
 
+
 class TestConstructTreePreorderPostorder(unittest.TestCase):
     def test_construct_tree(self):
-        
+
         # Test 1
         ctpp.pre_index = 0
         pre1 = [1, 2, 4, 8, 9, 5, 3, 6, 7]
         post1 = [8, 9, 4, 5, 2, 6, 7, 3, 1]
         size1 = len(pre1)
 
-        self.assertEqual(ctpp.construct_tree(pre1, post1, size1), [8,4,9,2,5,1,6,3,7])
+        self.assertEqual(ctpp.construct_tree(pre1, post1, size1),
+                         [8, 4, 9, 2, 5, 1, 6, 3, 7])
 
         # Test 2
         ctpp.pre_index = 0
@@ -128,7 +131,8 @@ class TestConstructTreePreorderPostorder(unittest.TestCase):
         post2 = [4, 5, 2, 6, 7, 3, 1]
         size2 = len(pre2)
 
-        self.assertEqual(ctpp.construct_tree(pre2, post2, size2), [4,2,5,1,6,3,7])
+        self.assertEqual(ctpp.construct_tree(pre2, post2, size2),
+                         [4, 2, 5, 1, 6, 3, 7])
 
         # Test 3
         ctpp.pre_index = 0
@@ -136,7 +140,8 @@ class TestConstructTreePreorderPostorder(unittest.TestCase):
         post3 = [16, 21, 7, 1, 9, 5, 12]
         size3 = len(pre3)
 
-        self.assertEqual(ctpp.construct_tree(pre3, post3, size3), [16,7,21,12,1,5,9])
+        self.assertEqual(ctpp.construct_tree(pre3, post3, size3),
+                         [16, 7, 21, 12, 1, 5, 9])
 
 
 class TestFenwickTree(unittest.TestCase):
@@ -170,5 +175,6 @@ class TestFenwickTree(unittest.TestCase):
         ft.update_bit(bit_tree, 2, 11)
         self.assertEqual(23, ft.get_sum(bit_tree, 4))
 
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/test_unix.py b/tests/test_unix.py
index e7a6c63..3cafba9 100644
--- a/tests/test_unix.py
+++ b/tests/test_unix.py
@@ -6,12 +6,18 @@ from algorithms.unix import (
 )
 import os
 import unittest
+
+
 class TestUnixPath(unittest.TestCase):
     def test_join_with_slash(self):
-        self.assertEqual("path/to/dir/file", join_with_slash("path/to/dir/", "file"))
-        self.assertEqual("path/to/dir/file", join_with_slash("path/to/dir", "file"))
-        self.assertEqual("http://algorithms/part", join_with_slash("http://algorithms", "part"))
-        self.assertEqual("http://algorithms/part", join_with_slash("http://algorithms/", "part"))
+        self.assertEqual("path/to/dir/file",
+                         join_with_slash("path/to/dir/", "file"))
+        self.assertEqual("path/to/dir/file",
+                         join_with_slash("path/to/dir", "file"))
+        self.assertEqual("http://algorithms/part",
+                         join_with_slash("http://algorithms", "part"))
+        self.assertEqual("http://algorithms/part",
+                         join_with_slash("http://algorithms/", "part"))
 
     def test_full_path(self):
         file_name = "file_name"