automate sudoku boards
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
# Sudoku problems.
|
||||
# The CSP.ac_3() and CSP.backtrack() methods need to be implemented
|
||||
|
||||
import sys
|
||||
from io import StringIO
|
||||
from time import time
|
||||
|
||||
from csp import CSP, alldiff
|
||||
|
||||
|
||||
@@ -11,16 +15,16 @@ def print_solution(solution):
|
||||
"""
|
||||
for row in range(width):
|
||||
for col in range(width):
|
||||
print(solution[f'X{row+1}{col+1}'], end=" ")
|
||||
print(solution[f"X{row+1}{col+1}"], end=" ")
|
||||
if col == 2 or col == 5:
|
||||
print('|', end=" ")
|
||||
print("|", end=" ")
|
||||
print("")
|
||||
if row == 2 or row == 5:
|
||||
print('------+-------+------')
|
||||
print("------+-------+------")
|
||||
|
||||
|
||||
# Choose Sudoku problem
|
||||
grid = open('sudoku_easy.txt').read().split()
|
||||
grid = open(sys.argv[1] if len(sys.argv) > 1 else "sudoku_easy.txt").read().split()
|
||||
|
||||
width = 9
|
||||
box_width = 3
|
||||
@@ -28,34 +32,60 @@ box_width = 3
|
||||
domains = {}
|
||||
for row in range(width):
|
||||
for col in range(width):
|
||||
if grid[row][col] == '0':
|
||||
domains[f'X{row+1}{col+1}'] = set(range(1, 10))
|
||||
if grid[row][col] == "0":
|
||||
domains[f"X{row+1}{col+1}"] = set(range(1, 10))
|
||||
else:
|
||||
domains[f'X{row+1}{col+1}'] = {int(grid[row][col])}
|
||||
domains[f"X{row+1}{col+1}"] = {int(grid[row][col])}
|
||||
|
||||
edges = []
|
||||
for row in range(width):
|
||||
edges += alldiff([f'X{row+1}{col+1}' for col in range(width)])
|
||||
edges += alldiff([f"X{row+1}{col+1}" for col in range(width)])
|
||||
for col in range(width):
|
||||
edges += alldiff([f'X{row+1}{col+1}' for row in range(width)])
|
||||
edges += alldiff([f"X{row+1}{col+1}" for row in range(width)])
|
||||
for box_row in range(box_width):
|
||||
for box_col in range(box_width):
|
||||
cells = []
|
||||
edges += alldiff(
|
||||
[
|
||||
f'X{row+1}{col+1}' for row in range(box_row * box_width, (box_row + 1) * box_width)
|
||||
f"X{row+1}{col+1}"
|
||||
for row in range(box_row * box_width, (box_row + 1) * box_width)
|
||||
for col in range(box_col * box_width, (box_col + 1) * box_width)
|
||||
]
|
||||
)
|
||||
|
||||
csp = CSP(
|
||||
variables=[f'X{row+1}{col+1}' for row in range(width) for col in range(width)],
|
||||
variables=[f"X{row+1}{col+1}" for row in range(width) for col in range(width)],
|
||||
domains=domains,
|
||||
edges=edges,
|
||||
)
|
||||
|
||||
# funny python code to hijack and redirect stdout
|
||||
start_ac_3 = time()
|
||||
print(csp.ac_3())
|
||||
print_solution(csp.backtracking_search())
|
||||
|
||||
original_stdout = sys.stdout
|
||||
sys.stdout = StringIO()
|
||||
|
||||
start_backtracking_search = time()
|
||||
result = csp.backtracking_search()
|
||||
end_time = time()
|
||||
|
||||
data = sys.stdout.getvalue().splitlines()
|
||||
|
||||
sys.stdout = original_stdout
|
||||
|
||||
print_solution(result)
|
||||
|
||||
number_of_failures = len([x for x in data if x == "i have failed"])
|
||||
number_of_function_calls = len([x for x in data if x == "i have been called"])
|
||||
print(
|
||||
f"Backtrack failed {number_of_failures} times out of {number_of_function_calls} calls."
|
||||
)
|
||||
print(f"Running both AC-3 and backtracking search took {end_time - start_ac_3:.5f}")
|
||||
print(
|
||||
f"Running only backtracking search took {end_time - start_backtracking_search:.5f}"
|
||||
)
|
||||
|
||||
|
||||
# Expected output after implementing csp.ac_3() and csp.backtracking_search():
|
||||
# True
|
||||
|
||||
Reference in New Issue
Block a user