diff --git a/4_9_Exercises/Question 3.py b/4_9_Exercises/Question 3.py
index e406f0d6b888f3cb630772683fe0551960696bde..6b29cc477ec1fedad651d4d527e2d00b2b07ffc5 100644
--- a/4_9_Exercises/Question 3.py	
+++ b/4_9_Exercises/Question 3.py	
@@ -1,9 +1,29 @@
 def nsp(x, y):
+    """had to be redone with back tracking although recursion is better down there"""
+    trace = [[(0, 0)]]
+    sln = []
+    while trace:
+        current = trace.pop(-1)
+        last_position = current[-1]
+
+        if last_position == (x, y):
+            sln.append(current)
+        else:
+            up = (last_position[0] + 1, last_position[1])
+            right = (last_position[0], last_position[1] + 1)
+            if (up not in current) and ((up[0] <= x) and (up[1] <= y)):
+                trace.append(current + [up])
+            if (right not in current) and ((right[0] <= x) and (right[1] <= y)):
+                trace.append(current + [right])
+    return len(sln)
+
+
+def nsp2(x, y):
+    """Same solution but with recursion and shorter"""
     if x < 0 or y < 0:
         return 0
     if (0, 0) == (x, y):
         return 1
     else:
-        return nsp(x, y - 1) + nsp(x - 1, y)
-
+        return nsp2(x, y - 1) + nsp2(x - 1, y)
 
diff --git a/Search_Algorithms/Heuristics.py b/Search_Algorithms/Heuristics.py
index 069822967d37b2b015a5c8934b009fab4dd1abd4..1350d1e0f565a7aedd629ac6f26fac18d194d707 100644
--- a/Search_Algorithms/Heuristics.py
+++ b/Search_Algorithms/Heuristics.py
@@ -13,7 +13,12 @@ def maze_opt(path):
 
 
 def puzzle_opt(path):
-    pass
+    current_state = path[-1]
+    total = 0
+    for i in range(len(current_state)):
+        for j in range(len(current_state[i])):
+            total = total + abs(is_goal.PUZZLE_GOAL[i][j] - current_state[i][j])
+    return total
 
 
 def sudoku_opt(path):
diff --git a/Search_Algorithms/solution testing.py b/Search_Algorithms/solution testing.py
index c13ba3f853c1cc6227e5b3520b3a5320fba9dcf3..cb98f7f3ec2e89919763a5e2ddb8ba4e47c91e4d 100644
--- a/Search_Algorithms/solution testing.py	
+++ b/Search_Algorithms/solution testing.py	
@@ -2,8 +2,11 @@ import Search_Algorithms
 import Sucessors
 import is_goal
 import Heuristics
+import time
 
-
+# ===============================================================================================================
+# BREADTH FIRST SEARCH MAZE
+# ===============================================================================================================
 # Maze Problem, note, the maze is fixed in the allowed state.
 print(Search_Algorithms.BreadthFirstSearch((4, 0), Sucessors.maze_successor, is_goal.is_goal_maze))
 
@@ -18,18 +21,24 @@ grid = ((5, 3, 0, 0, 7, 0, 0, 0, 0),
         (0, 0, 0, 4, 1, 9, 0, 0, 5),
         (0, 0, 0, 0, 8, 0, 0, 0, 0))
 
+# ===============================================================================================================
+# BREADTH FIRST SEARCH SUDOKU
+# ===============================================================================================================
 sln = (Search_Algorithms.BreadthFirstSearch(grid, Sucessors.sudoku_successor, is_goal.is_goal_sudoku)[-1])
 
 for rows in sln:
     print(rows)
-print("--------------------------------")
+
+# ===============================================================================================================
+# DEPTH FIRST SEARCH SUDOKU
+# ===============================================================================================================
 sln = (Search_Algorithms.DepthFirstSearch(
      grid, Sucessors.sudoku_successor, is_goal.is_goal_sudoku)[-1])
 #
 for rows in sln:
     print(rows)
 
-# N Queens
+
 board = ((False, False, False, False, False, False, False, False, False, False),
          (False, False, False, False, False, False, False, False, False, False),
          (False, False, False, False, False, False, False, False, False, False),
@@ -41,11 +50,22 @@ board = ((False, False, False, False, False, False, False, False, False, False),
          (False, False, False, False, False, False, False, False, False, False),
          (False, False, False, False, False, False, False, False, False, False))
 
-
+# ===============================================================================================================
+# BREADTH FIRST SEARCH N QUEENS PROBLEM
+# ===============================================================================================================
 sln = (Search_Algorithms.BreadthFirstSearch(board, Sucessors.queens_successor, is_goal.is_goal_queens)[-1])
 
-# sln = (Search_Algorithms.DepthFirstSearch(
-#     board, Sucessors.queens_successor, is_goal.is_goal_queens)[-1])
+output_tuple = tuple(tuple("Q" if value else "." for value in sln)
+                     for sln in sln)
+for rows in output_tuple:
+    print(rows)
+
+
+# ===============================================================================================================
+# BREADTH FIRST SEARCH PUZZLE PROBLEM
+# ===============================================================================================================
+sln = (Search_Algorithms.DepthFirstSearch(
+    board, Sucessors.queens_successor, is_goal.is_goal_queens)[-1])
 
 output_tuple = tuple(tuple("Q" if value else "." for value in sln)
                      for sln in sln)
@@ -53,14 +73,33 @@ for rows in output_tuple:
     print(rows)
 
 
-# Sliding Puzzle
+# # Sliding Puzzle
 initial_puzzle = (
     (7, 2, 4),
     (5, 0, 6),
     (8, 3, 1)
 )
+# ===============================================================================================================
+# BREADTH FIRST SEARCH PUZZLE PROBLEM
+# ===============================================================================================================
+sln = (Search_Algorithms.BreadthFirstSearch(initial_puzzle, Sucessors.puzzle_successor, is_goal.is_goal_puzzle))
+
+if sln:
+    for rows in sln:
+        for r in rows:
+            print(r)
+else:
+    print("No solution found")
+
 
-sln = (Search_Algorithms.BreadthFirstSearch(initial_puzzle, Sucessors.puzzle_successor, is_goal.is_goal_puzzle)[-1])
+# ===============================================================================================================
+# DEPTH FIRST SEARCH PUZZLE PROBLEM
+# search was timed on Michael's computer and took 211 seconds, Please be patient
+# ===============================================================================================================
+# start_time = time.time()
+sln = (Search_Algorithms.DepthFirstSearch(initial_puzzle, Sucessors.puzzle_successor, is_goal.is_goal_puzzle)[-1])
+# end_time = time.time()
+# print(end_time - start_time)
 
 if sln:
     for rows in sln:
@@ -68,17 +107,16 @@ if sln:
 else:
     print("No solution found")
 
-#
-# sln = (Search_Algorithms.DepthFirstSearch(initial_puzzle, Sucessors.puzzle_successor, is_goal.is_goal_puzzle)[-1])
-#
-# if sln:
-#     for rows in sln:
-#         print(rows)
-# else:
-#     print("No solution found")
 
-# print(Search_Algorithms.A_StarSearch((4, 0), Sucessors.maze_successor, is_goal.is_goal_maze, Heuristics.maze_opt))
+# ===============================================================================================================
+# A* SEARCH MAZE PROBLEM
+# ===============================================================================================================
+print(Search_Algorithms.A_StarSearch((4, 0), Sucessors.maze_successor, is_goal.is_goal_maze, Heuristics.maze_opt))
+
 
+# # ===============================================================================================================
+# # A* SEARCH SUDOKU
+# # ===============================================================================================================
 sln = (Search_Algorithms.A_StarSearch(grid, Sucessors.sudoku_successor,
                                       is_goal.is_goal_sudoku, Heuristics.sudoku_opt))[-1]
 
@@ -86,8 +124,20 @@ for rows in sln:
     print(rows)
 
 
+# =================================================================================================================
+# A* SEARCH PUZZLE
+# =================================================================================================================
+sln = (Search_Algorithms.A_StarSearch(initial_puzzle, Sucessors.puzzle_successor,
+                                      is_goal.is_goal_puzzle, Heuristics.puzzle_opt))[-1]
 
+if sln:
+    for rows in sln:
+        print(rows)
+else:
+    print("No solution found")
 
 
-
+# # ===============================================================================================================
+# # A* SEARCH QUEENS
+# # ===============================================================================================================