sudoku-solver/board.py
2019-11-30 13:55:22 +01:00

120 lines
4.1 KiB
Python

"""This module contains the Board class.
It is used to represent different elements for the whole board.
"""
from square import Square
class Board:
"""The Board class contains different elements of the board."""
def __init__(self, string):
self.lines = [""] * 9
i = 0
line = 0
while line < 9:
if string[i] == '\n':
line += 1
else:
self.lines[line] += string[i]
i += 1
self.columns = [""] * 9
for col in range(9):
for line in self.lines:
self.columns[col] += line[col]
self.__assert_lines_and_columns_have_same_values()
def __str__(self):
return "\n".join(self.lines)
def __assert_lines_and_columns_have_same_values(self):
differences = [
'X' for col, column in enumerate(self.columns)
for lin, line, in enumerate(self.lines)
if self.lines[lin][col] != self.columns[col][lin]
]
assert len(differences) == 0
def __compute_possible_values_from_lines(self):
"""Compute possible values for each number in a line.
Go through each line and add possible values to each square that hasn't
been found yet. The values are computed based on the fact that they
aren't already present in that same line.
"""
for line_index, line in enumerate(self.lines):
self.lines[line_index] = list(line)
for column in range(9):
if line[column] == '.':
self.lines[line_index][column] = {
number for number in range(1, 10)
if str(number) not in line
}
else:
self.lines[line_index][column] = {line[column]}
def __compute_possible_values_from_columns(self):
"""Compute possible values for each number in a column.
Go through each column and add possible values to each square that
hasn't been found yet. The values are computed based on the fact that
they aren't already present in that same column.
"""
for column_index, column in enumerate(self.columns):
self.columns[column_index] = list(column)
for line in range(9):
if column[line] == '.':
self.columns[column_index][line] = {
number for number in range(1, 10)
if str(number) not in column
}
else:
self.columns[column_index][line] = {column[line]}
def compute_possible_values(self):
"""Compute possible values for each square in the board."""
self.__compute_possible_values_from_lines()
self.__compute_possible_values_from_columns()
def intersect_possible_values(self):
"""Remove impossible values from possibilities in lines and columns.
Go through each line and for each square intersect the set with the set
in the same square in self.columns.
Go through each column and for each square intersect the set with the
set in the same square in self.lines.
Note: you need to run compute_possible_values first.
"""
for lin, line in enumerate(self.lines):
for col, column in enumerate(self.columns):
self.lines[lin][col] = line[col].intersection(column[lin])
self.columns[col][lin] = column[lin].intersection(line[col])
self.__assert_lines_and_columns_have_same_values()
def create_squares(self):
"""Make each square of the board a Square object."""
for lin, line in enumerate(self.lines):
for col, column in enumerate(self.columns):
self.lines[lin][col] = Square(lin, col, line[col])
self.columns[col][lin] = Square(lin, col, column[lin])
differences = [
'X' for col, column in enumerate(self.columns)
for lin, line, in enumerate(self.lines)
if self.lines[lin][col].content != self.columns[col][lin].content
]
assert len(differences) == 0