diff --git a/Search_Algorithms/Heuristics.py b/Search_Algorithms/Heuristics.py
index cf5fa56e4ecf28ebb02ed4b1b7cbdab6de3b6d7a..069822967d37b2b015a5c8934b009fab4dd1abd4 100644
--- a/Search_Algorithms/Heuristics.py
+++ b/Search_Algorithms/Heuristics.py
@@ -1,4 +1,5 @@
 import is_goal
+import Sucessors
 
 
 
@@ -16,21 +17,9 @@ def puzzle_opt(path):
 
 
 def sudoku_opt(path):
-    # state = path[-1]
-    # box_value, row_value, col_value = 0, 0, 0
-    # # check each box to see the least empty
-    # for down in range(0, 9, 3):
-    #     for across in range(0, 9, 3):
-    #         box_value += 9 - ()
-    #     box_value = 0
-    #
-    # # check each row for the one with the least zeros
-    # row_value = 0
-    #
-    # # check each column for the one with the least zeros
-    # col_value = 0
-
-    pass
+    starting_point = [Sucessors.choose_best_subsquare(path[-1]), Sucessors.choose_best_rows(path[-1]),
+                      Sucessors.choose_best_column(path[-1])]
+    return max(starting_point, key=lambda w: w[2])[-1]
 
 
 def queens_opt(path):
diff --git a/Search_Algorithms/Search_Algorithms.py b/Search_Algorithms/Search_Algorithms.py
index 6558e36bc21821219080d2e28ef2e19f9af02bee..242844794e9e912521abe6ecebd62712c4509f81 100644
--- a/Search_Algorithms/Search_Algorithms.py
+++ b/Search_Algorithms/Search_Algorithms.py
@@ -34,7 +34,6 @@ def DepthFirstSearch(state, successor, isgoal):
             if next_state not in explored:
                 explored.add(next_state)
                 path2 = path + [next_state]
-                print(path2)
                 toDo.append(path2)
     return "Error Path not found"
 
diff --git a/Search_Algorithms/Sucessors.py b/Search_Algorithms/Sucessors.py
index 0de1748da760bb55db475c1c3638c8c07ff0795f..1baefd29db00388c8318db08115f39e8c272ebc6 100644
--- a/Search_Algorithms/Sucessors.py
+++ b/Search_Algorithms/Sucessors.py
@@ -9,11 +9,8 @@ def maze_successor(state):
 
 def sudoku_successor(state):
     new_state = list(map(list, state))  # Convert state to a list of lists
-    y, x = -1, -1
-    for i, s in enumerate(state):
-        if 0 in s:
-            (y, x) = (i, s.index(0))
-            break
+    starting_point = [choose_best_subsquare(new_state), choose_best_rows(new_state), choose_best_column(new_state)]
+    x, y, dummy = max(starting_point, key=lambda w: w[2])
     next_states = []
     for j in range(1, len(new_state) + 1):
         new_state[y][x] = j
@@ -22,45 +19,6 @@ def sudoku_successor(state):
     return next_states
 
 
-def maze_allowed(state):
-    maze = [[' ', 'W', ' ', ' ', 'G'],
-            [' ', 'W', ' ', 'W', ' '],
-            [' ', 'W', ' ', ' ', ' '],
-            [' ', ' ', 'W', 'W', ' '],
-            [' ', ' ', ' ', ' ', ' ']]
-    if state[0] >= len(maze[0]) or state[0] < 0:
-        return False
-    if state[1] >= len(maze) or state[1] < 0:
-        return False
-    return maze[state[0]][state[1]] == ' ' or maze[state[0]][state[1]] == 'G'
-
-
-def sudoku_allowed(state):
-    (y, x, grid) = state
-    """I'm making the state a triple on this one"""
-    # (y, x, z): x,y is the coordinate and z is the value in the square
-
-    # check if still inside the box
-    if y < 0 or y >= len(grid[0]):
-        return False
-    if x < 0 or x >= len(grid):
-        return False
-
-    # inspect columns and rows
-    if ([row[x] for row in grid].count(grid[y][x]) > 1) or (grid[y].count(grid[y][x]) > 1):
-        return False
-
-    # inspect minor square in teh sudoku
-    inner_x = ((x - (x % 3)), (x - (x % 3) + 3))
-    inner_y = (y - (y % 3))
-    inner_square = grid[inner_y][inner_x[0]:inner_x[1]] + grid[inner_y + 1][inner_x[0]:inner_x[1]] + \
-                   grid[inner_y + 2][inner_x[0]:inner_x[1]]
-    if inner_square.count(grid[y][x]) > 1:
-        return False
-
-    return True
-
-
 def puzzle_successor(state):
     y, x = -1, -1
     for i in range(len(state)):
@@ -103,10 +61,52 @@ def queens_successor(state):
     return next_states
 
 
+# Allowed moves Functions
 def puzzle_allowed(state):
     return True
 
 
+
+def maze_allowed(state):
+    maze = [[' ', 'W', ' ', ' ', 'G'],
+            [' ', 'W', ' ', 'W', ' '],
+            [' ', 'W', ' ', ' ', ' '],
+            [' ', ' ', 'W', 'W', ' '],
+            [' ', ' ', ' ', ' ', ' ']]
+    if state[0] >= len(maze[0]) or state[0] < 0:
+        return False
+    if state[1] >= len(maze) or state[1] < 0:
+        return False
+    return maze[state[0]][state[1]] == ' ' or maze[state[0]][state[1]] == 'G'
+
+
+def sudoku_allowed(state):
+    (y, x, grid) = state
+    """I'm making the state a triple on this one"""
+    # (y, x, z): x,y is the coordinate and z is the value in the square
+
+    # check if still inside the box
+    if y < 0 or y >= len(grid[0]):
+        return False
+    if x < 0 or x >= len(grid):
+        return False
+
+    # inspect columns and rows
+    if ([row[x] for row in grid].count(grid[y][x]) > 1) or (grid[y].count(grid[y][x]) > 1):
+        return False
+
+    # inspect minor square in teh sudoku
+    inner_x = ((x - (x % 3)), (x - (x % 3) + 3))
+    inner_y = (y - (y % 3))
+    inner_square = grid[inner_y][inner_x[0]:inner_x[1]] + grid[inner_y + 1][inner_x[0]:inner_x[1]] + \
+                   grid[inner_y + 2][inner_x[0]:inner_x[1]]
+    if inner_square.count(grid[y][x]) > 1:
+        return False
+
+    return True
+
+
+
 def queens_allowed(state):
     """in this case the state is also y, x, grid"""
     y, x, grid = state
@@ -137,3 +137,49 @@ def queens_allowed(state):
             return False
 
     return True
+
+
+# Helper Functions
+def choose_best_rows(grid):
+    best_row = -1
+    x = -1
+    min_empty = len(grid)
+    for i in range(len(grid)):
+        empty_cells = grid[i].count(0)
+        if 0 < empty_cells < min_empty:
+            best_row = i
+            min_empty = empty_cells
+            x = grid[i].index(0)
+    return x, best_row, min_empty
+
+
+def choose_best_column(grid):
+    best_col = -1
+    y = -1
+    min_empty = len(grid)
+    for i in range(len(grid)):
+        col = [row[i] for row in grid]
+        empty_cells = col.count(0)
+        if 0 < empty_cells < min_empty:
+            best_col = i
+            min_empty = empty_cells
+            y = col.index(0)
+    return best_col, y, min_empty
+
+
+def choose_best_subsquare(grid):
+    x = -1
+    y = -1
+    best_val = len(grid)
+    for down in range(0, 9, 3):
+        for across in range(0, 9, 3):
+            subsquare = [grid[i][across: across + 3] for i in range(down, down + 3)]
+            zeros = sum([subsquare[i].count(0) for i in range(len(subsquare))])
+            if 0 < zeros < best_val:
+                best_val = zeros
+                for j in range(len(subsquare)):
+                    if 0 in subsquare[j]:
+                        x = across + subsquare[j].index(0)
+                        y = down + j
+                        break
+    return (x, y, best_val)
diff --git a/Search_Algorithms/solution testing.py b/Search_Algorithms/solution testing.py
index d34c13505f48ef42031e591b23861a05497c1c51..6a537e262497f2d05956953e95819e3a2f8807e1 100644
--- a/Search_Algorithms/solution testing.py	
+++ b/Search_Algorithms/solution testing.py	
@@ -5,26 +5,29 @@ import Heuristics
 
 
 # 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))
+print(Search_Algorithms.BreadthFirstSearch((4, 0), Sucessors.maze_successor, is_goal.is_goal_maze))
 
 # Sudoku
-grid = ((1, 0, 0, 0, 0, 0, 0, 0, 0),
-        (0, 0, 0, 0, 0, 0, 0, 0, 0),
-        (0, 0, 0, 0, 0, 0, 0, 0, 0),
-        (0, 0, 0, 0, 0, 0, 0, 0, 0),
-        (0, 0, 0, 0, 0, 0, 0, 0, 0),
-        (0, 0, 0, 0, 0, 0, 0, 0, 0),
-        (0, 0, 0, 0, 0, 0, 0, 0, 0),
-        (0, 0, 0, 0, 0, 0, 0, 0, 0),
+grid = ((5, 3, 0, 0, 7, 0, 0, 0, 0),
+        (6, 0, 0, 1, 9, 5, 0, 0, 0),
+        (0, 9, 8, 0, 0, 0, 0, 6, 0),
+        (8, 0, 0, 0, 6, 0, 0, 0, 3),
+        (4, 0, 0, 8, 0, 3, 0, 0, 1),
+        (7, 0, 0, 0, 2, 0, 0, 0, 6),
+        (0, 6, 0, 0, 0, 0, 2, 8, 0),
+        (0, 0, 0, 4, 1, 9, 0, 0, 5),
         (0, 0, 0, 0, 8, 0, 0, 0, 0))
 
-# sln = (Search_Algorithms.BreadthFirstSearch(grid, Sucessors.sudoku_successor, is_goal.is_goal_sudoku)[-1])
+sln = (Search_Algorithms.BreadthFirstSearch(grid, Sucessors.sudoku_successor, is_goal.is_goal_sudoku)[-1])
 
-# sln = (Search_Algorithms.DepthFirstSearch(
-#     grid, Sucessors.sudoku_successor, is_goal.is_goal_sudoku)[-1])
+for rows in sln:
+    print(rows)
+print("--------------------------------")
+sln = (Search_Algorithms.DepthFirstSearch(
+     grid, Sucessors.sudoku_successor, is_goal.is_goal_sudoku)[-1])
 #
-# for rows in sln:
-#     print(rows)
+for rows in sln:
+    print(rows)
 
 # N Queens
 board = ((False, False, False, False, False, False, False, False, False),
@@ -38,15 +41,15 @@ board = ((False, False, False, False, False, False, False, False, False),
          (False, False, False, False, False, False, False, False, False))
 
 
-# sln = (Search_Algorithms.BreadthFirstSearch(board, Sucessors.queens_successor, is_goal.is_goal_queens)[-1])
-#
+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)
+
+output_tuple = tuple(tuple("Q" if value else "." for value in sln)
+                     for sln in sln)
+for rows in output_tuple:
+    print(rows)
 
 
 # Sliding Puzzle
@@ -55,14 +58,14 @@ initial_puzzle = (
     (5, 0, 6),
     (8, 3, 1)
 )
-#
-# sln = (Search_Algorithms.BreadthFirstSearch(initial_puzzle, Sucessors.puzzle_successor, is_goal.is_goal_puzzle)[-1])
-#
-# if sln:
-#     for rows in sln:
-#         print(rows)
-# else:
-#     print("No solution found")
+
+sln = (Search_Algorithms.BreadthFirstSearch(initial_puzzle, Sucessors.puzzle_successor, is_goal.is_goal_puzzle)[-1])
+
+if sln:
+    for rows in sln:
+        print(rows)
+else:
+    print("No solution found")
 
 #
 # sln = (Search_Algorithms.DepthFirstSearch(initial_puzzle, Sucessors.puzzle_successor, is_goal.is_goal_puzzle)[-1])
@@ -73,7 +76,13 @@ initial_puzzle = (
 # else:
 #     print("No solution found")
 
-print(Search_Algorithms.A_StarSearch((4, 0), Sucessors.maze_successor, is_goal.is_goal_maze, Heuristics.maze_opt))
+# print(Search_Algorithms.A_StarSearch((4, 0), Sucessors.maze_successor, is_goal.is_goal_maze, Heuristics.maze_opt))
+
+sln = (Search_Algorithms.A_StarSearch(grid, Sucessors.sudoku_successor,
+                                      is_goal.is_goal_sudoku, Heuristics.sudoku_opt))[-1]
+
+for rows in sln:
+    print(rows)