Я написал этот код для решения Судоку, он использует программирование возврата и ограничения. Первоначально моя функция удовлетворенная () заняла ВСЕ время. Я сделал это намного быстрее, взгляни. В общем, я просто хочу получить общие советы о том, как настроить sh программу, ускорить выполнение любых медленных функций и т. Д. c, общую обратную связь и т. Д. c. Спасибо!
from typing import Generic, TypeVar, Dict, List, Optional, NamedTuple
from abc import ABC, abstractmethod
V = TypeVar('V')
D = TypeVar('D')
class Constraint(Generic[V,D], ABC):
def __init__(self, variables: List[V]) -> None:
self.variables = variables
@abstractmethod
def satisfied(self, assignment: Dict [V,D], last: D) -> bool:
...
class CSP(Generic[V,D]):
def __init__(self, variables: List[V], domains: Dict[V, List[D]]) -> None:
self.variables: List[V] = variables
self.domains: Dict[V, List[D]] = domains
self.constraints: Dict[V, List[Constraint[V,D]]] = {}
for variable in self.variables:
self.constraints[variable] = []
if variable not in self.domains:
raise LookupError("Every variable needs a domain to it")
def add_constraint(self,constraint: Constraint[V,D]) -> None:
for variable in constraint.variables:
if variable not in self.variables:
raise LookupError("Not in CSP")
else:
self.constraints[variable].append(constraint)
def consistent(self, variable: V, assignment: Dict[V,D], last: D)-> bool:
for constraint in self.constraints[variable]:
if not constraint.satisfied(assignment, last):
return False
return True
def backtracking(self, assignment: Dict[V,D] = {}) -> Optional[Dict[V,D]]:
if len(assignment) == len(self.variables):
return assignment
unassigned: List[V] = [v for v in self.variables if v not in assignment]
first: V = unassigned[0]
for value in self.domains[first]:
local_assignment = assignment.copy()
local_assignment[first] = value
#print(local_assignment)
if self.consistent(first, local_assignment, value):
result: Optional[Dict[V,D]] = self.backtracking(local_assignment)
if result is not None:
#print(first, "*", result)
return result
#print(first, "stuck")
return None
class SudokuCell(NamedTuple):
row: int
column: int
class SudokuConstraint(Constraint[SudokuCell, int]):
def __init__(self, cells: List[SudokuCell]) -> None:
super().__init__(cells)
self.cells: List[str] = cells
def satisfied(self, assignment: Dict[SudokuCell,int], last: int) -> bool:
vlast = [cell for cell,val in assignment.items() if val == last]
nlast = len(vlast)
vrows = [cell.row for cell in vlast]
if len(set(vrows)) < nlast:
return False
vcolumns = [cell.column for cell in vlast]
if len(set(vcolumns)) < nlast:
return False
vblock = [(cell.row//3, cell.column//3) for cell in vlast]
if len(set(vblock)) < nlast:
return False
return True
def solve_sudoku(start_assignm: Dict[SudokuCell, int] = {}):
cells: List[SudokuCell] = []
values: Dict[SudokuCell, List[int]] = {}
for i in range(0,9):
for l in range (0,9):
cells.append(SudokuCell(i,l))
values[SudokuCell(i,l)] = list(range(1,10))
csp_sudoku: CSP[SudokuCell,int] = CSP(cells,values)
csp_sudoku.add_constraint(SudokuConstraint(cells))
sol_sudoku: Optional[Dict[SudokuCell,int]] = csp_sudoku.backtracking(start_assignm)
if sol_sudoku is None:
print("No solution")
else:
print(str_sudoku(sol_sudoku))
def str_sudoku(sol_sudoku: Dict[SudokuCell,int]) -> str:
output: str = "\n"
for i in range(0,9):
if (i%3 == 0):
output+= "║═══╬═══╬═══║\n"
for l in range(0,9):
if(l%3 == 0):
output+= "║"
v = sol_sudoku.get(SudokuCell(i,l))
if v is None:
output += " "
else:
output += str(v)
output += "║\n"
output += "╚═══╩═══╩═══╝\n"
return output
def try_to_solve_sudoku(fname = ""):
try:
fd = open(fname)
rows = fd.read().split()
fd.close()
except IOError:
rows = ["xx5xxxx1x", "xx3xxx29x", "x4xx6xxx8",
"57xxx4xxx", "x9xxxxxxx", "xxx2x8x5x",
"x69x7xxxx", "xxxxxx74x", "x3x9xx6xx"]
print("Using default puzzle")
start_assignment: Dict[SudokuCell,int] = {}
for i in range(0,9):
for l in range (0,9):
if rows[i][l].isdigit():
start_assignment[SudokuCell(i,l)] = int(rows[i][l])
print(str_sudoku(start_assignment))
solve_sudoku(start_assignment)