added docstring to all functions and methods
This commit is contained in:
parent
b2fb7bb25b
commit
b1070f42f9
1 changed files with 170 additions and 18 deletions
188
sources/grid.py
188
sources/grid.py
|
@ -18,12 +18,17 @@ __author__ = 'gaugendre'
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
def string_from_list(line) -> str:
|
def string_from_list(line):
|
||||||
"""
|
"""
|
||||||
Makes a string from a line of squares.
|
Makes a string from a line of squares.
|
||||||
|
|
||||||
:param line: A line (list) of squares to make a string from.
|
:param line: A line (list) of squares to make a string from.
|
||||||
:type line: list
|
:type line: list
|
||||||
:return: A string containing all the states of the squares in the list.
|
:return: A string containing all the states of the squares in the list.
|
||||||
|
:rtype: str
|
||||||
|
|
||||||
|
.. warnings:: The items of the list must be squares or have an attribute
|
||||||
|
called 'state'.
|
||||||
"""
|
"""
|
||||||
string = ""
|
string = ""
|
||||||
for square in line:
|
for square in line:
|
||||||
|
@ -31,12 +36,18 @@ def string_from_list(line) -> str:
|
||||||
return string
|
return string
|
||||||
|
|
||||||
|
|
||||||
def non_space_element(line) -> str:
|
def non_space_element(line):
|
||||||
"""
|
"""
|
||||||
Returns the number of non space characters in a string.
|
Returns the number of non space characters in a string.
|
||||||
|
|
||||||
:param line: The line where to count characters.
|
:param line: The line where to count characters.
|
||||||
:type line: str
|
:type line: str
|
||||||
:return: The number of non space characters.
|
:return: The number of non space characters.
|
||||||
|
:rtype: str
|
||||||
|
|
||||||
|
:Example:
|
||||||
|
>>> non_space_element('Ceci est un test')
|
||||||
|
13
|
||||||
"""
|
"""
|
||||||
return len(line.replace(' ', ''))
|
return len(line.replace(' ', ''))
|
||||||
|
|
||||||
|
@ -53,7 +64,7 @@ class Square:
|
||||||
self.vert = vert
|
self.vert = vert
|
||||||
self.switched = False
|
self.switched = False
|
||||||
self.base = base
|
self.base = base
|
||||||
if isinstance(grid, Grid):
|
if not grid or isinstance(grid, Grid):
|
||||||
self.grid = grid
|
self.grid = grid
|
||||||
else:
|
else:
|
||||||
print("Warning : Attribute grid not instance of Grid",
|
print("Warning : Attribute grid not instance of Grid",
|
||||||
|
@ -67,22 +78,54 @@ class Square:
|
||||||
self._state = ' '
|
self._state = ' '
|
||||||
|
|
||||||
def next_horiz(self):
|
def next_horiz(self):
|
||||||
if self.horiz == self.grid.size - 1:
|
"""
|
||||||
|
A method to get the next square horizontally.
|
||||||
|
|
||||||
|
:return: The next square, horizontally.
|
||||||
|
:rtype: Square
|
||||||
|
|
||||||
|
.. warnings:: The square must be part of a grid
|
||||||
|
"""
|
||||||
|
if not self.grid or self.horiz == self.grid.size - 1:
|
||||||
return None
|
return None
|
||||||
return self.grid.square(self.horiz + 1, self.vert)
|
return self.grid.square(self.horiz + 1, self.vert)
|
||||||
|
|
||||||
def prev_horiz(self):
|
def prev_horiz(self):
|
||||||
if self.horiz == 0:
|
"""
|
||||||
|
A method to get the previous square horizontally.
|
||||||
|
|
||||||
|
:return: The previous square, horizontally.
|
||||||
|
:rtype: Square
|
||||||
|
|
||||||
|
.. warnings:: The square must be part of a grid
|
||||||
|
"""
|
||||||
|
if not self.grid or self.horiz == 0:
|
||||||
return None
|
return None
|
||||||
return self.grid.square(self.horiz - 1, self.vert)
|
return self.grid.square(self.horiz - 1, self.vert)
|
||||||
|
|
||||||
def next_vert(self):
|
def next_vert(self):
|
||||||
if self.vert == self.grid.size - 1:
|
"""
|
||||||
|
A method to get the next square vertically.
|
||||||
|
|
||||||
|
:return: The next square, vertically.
|
||||||
|
:rtype: Square
|
||||||
|
|
||||||
|
.. warnings:: The square must be part of a grid
|
||||||
|
"""
|
||||||
|
if not self.grid or self.vert == self.grid.size - 1:
|
||||||
return None
|
return None
|
||||||
return self.grid.square(self.horiz, self.vert + 1)
|
return self.grid.square(self.horiz, self.vert + 1)
|
||||||
|
|
||||||
def prev_vert(self):
|
def prev_vert(self):
|
||||||
if self.vert == 0:
|
"""
|
||||||
|
A method to get the previous square vertically.
|
||||||
|
|
||||||
|
:return: The previous square, vertically.
|
||||||
|
:rtype: Square
|
||||||
|
|
||||||
|
.. warnings:: The square must be part of a grid
|
||||||
|
"""
|
||||||
|
if not self.grid or self.vert == 0:
|
||||||
return None
|
return None
|
||||||
return self.grid.square(self.horiz, self.vert - 1)
|
return self.grid.square(self.horiz, self.vert - 1)
|
||||||
|
|
||||||
|
@ -98,14 +141,17 @@ class Square:
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "({}, {}) : '{}'".format(self.horiz, self.vert, self.state)
|
return "({}, {}) : '{}'".format(self.horiz, self.vert, self.state)
|
||||||
|
|
||||||
def _get_state(self):
|
@property
|
||||||
|
def state(self):
|
||||||
"""
|
"""
|
||||||
Allow to get square state.
|
Allow to get square state.
|
||||||
|
|
||||||
:return: The square state. Either ' ', 'R' or 'B'
|
:return: The square state. Either ' ', 'R' or 'B'
|
||||||
"""
|
"""
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
def _set_state(self, new_state):
|
@state.setter
|
||||||
|
def state(self, new_state):
|
||||||
"""
|
"""
|
||||||
Changes square state. Accepts only 'R', 'B', or ' '.
|
Changes square state. Accepts only 'R', 'B', or ' '.
|
||||||
Other values are not accepted and the square is not modified.
|
Other values are not accepted and the square is not modified.
|
||||||
|
@ -116,9 +162,22 @@ class Square:
|
||||||
else:
|
else:
|
||||||
print("Error :", new_state, "not in ('R', 'B', ' ').")
|
print("Error :", new_state, "not in ('R', 'B', ' ').")
|
||||||
|
|
||||||
state = property(_get_state, _set_state)
|
|
||||||
|
|
||||||
def opposite_state(self):
|
def opposite_state(self):
|
||||||
|
"""
|
||||||
|
Returns the opposite state of the current Square.
|
||||||
|
|
||||||
|
The opposite state of 'R' is 'B', and vice-versa.
|
||||||
|
The opposite state of ' ' is ' '.
|
||||||
|
|
||||||
|
:return: The opposite state of the current square.
|
||||||
|
:rtype: str
|
||||||
|
|
||||||
|
:Example:
|
||||||
|
>>> Square(None, 0, 0, 'R').opposite_state()
|
||||||
|
'B
|
||||||
|
>>> Square(None, 0, 0, ' ').opposite_state()
|
||||||
|
' ''
|
||||||
|
"""
|
||||||
if self.state == 'R':
|
if self.state == 'R':
|
||||||
return 'B'
|
return 'B'
|
||||||
elif self.state == 'B':
|
elif self.state == 'B':
|
||||||
|
@ -127,17 +186,48 @@ class Square:
|
||||||
return ' '
|
return ' '
|
||||||
|
|
||||||
def is_empty(self):
|
def is_empty(self):
|
||||||
|
"""
|
||||||
|
Simply tells if the square contains nothing or not.
|
||||||
|
|
||||||
|
:return: True if the square contains ' ', else False.
|
||||||
|
:rtype: bool
|
||||||
|
|
||||||
|
:Example:
|
||||||
|
>>> Square(None, 0, 0, ' ').is_empty()
|
||||||
|
True
|
||||||
|
>>> Square(None, 0, 0, 'R').is_empty()
|
||||||
|
False
|
||||||
|
"""
|
||||||
return self.state == ' '
|
return self.state == ' '
|
||||||
|
|
||||||
def all_prev_horiz(self):
|
def all_prev_horiz(self):
|
||||||
|
"""
|
||||||
|
Get the list of all previous squares, horizontally.
|
||||||
|
|
||||||
|
:return: A list containing all the previous squares horizontally.
|
||||||
|
:rtype: list
|
||||||
|
|
||||||
|
.. seealso:: prev_horiz()
|
||||||
|
.. warnings:: The square must be part of a grid.
|
||||||
|
"""
|
||||||
h_prev = self.prev_horiz()
|
h_prev = self.prev_horiz()
|
||||||
all_prev_horiz_list = []
|
all_prev_horiz_list = []
|
||||||
while h_prev:
|
while h_prev:
|
||||||
all_prev_horiz_list.append(h_prev)
|
all_prev_horiz_list.append(h_prev)
|
||||||
h_prev = h_prev.prev_horiz()
|
h_prev = h_prev.prev_horiz()
|
||||||
|
|
||||||
return all_prev_horiz_list
|
return all_prev_horiz_list
|
||||||
|
|
||||||
def all_next_horiz(self):
|
def all_next_horiz(self):
|
||||||
|
"""
|
||||||
|
Get the list of all next squares, horizontally.
|
||||||
|
|
||||||
|
:return: A list containing all the next squares horizontally.
|
||||||
|
:rtype: list
|
||||||
|
|
||||||
|
.. seealso:: next_horiz()
|
||||||
|
.. warnings:: The square must be part of a grid.
|
||||||
|
"""
|
||||||
h_next = self.next_horiz()
|
h_next = self.next_horiz()
|
||||||
all_next_horiz_list = []
|
all_next_horiz_list = []
|
||||||
while h_next:
|
while h_next:
|
||||||
|
@ -146,6 +236,15 @@ class Square:
|
||||||
return all_next_horiz_list
|
return all_next_horiz_list
|
||||||
|
|
||||||
def all_prev_vert(self):
|
def all_prev_vert(self):
|
||||||
|
"""
|
||||||
|
Get the list of all previous squares, vertically.
|
||||||
|
|
||||||
|
:return: A list containing all the previous squares vertically.
|
||||||
|
:rtype: list
|
||||||
|
|
||||||
|
.. seealso:: prev_vert()
|
||||||
|
.. warnings:: The square must be part of a grid.
|
||||||
|
"""
|
||||||
v_prev = self.prev_vert()
|
v_prev = self.prev_vert()
|
||||||
all_prev_vert_list = []
|
all_prev_vert_list = []
|
||||||
while v_prev:
|
while v_prev:
|
||||||
|
@ -154,6 +253,15 @@ class Square:
|
||||||
return all_prev_vert_list
|
return all_prev_vert_list
|
||||||
|
|
||||||
def all_next_vert(self):
|
def all_next_vert(self):
|
||||||
|
"""
|
||||||
|
Get the list of all next squares, vertically.
|
||||||
|
|
||||||
|
:return: A list containing all the next squares vertically.
|
||||||
|
:rtype: list
|
||||||
|
|
||||||
|
.. seealso:: next_vert()
|
||||||
|
.. warnings:: The square must be part of a grid.
|
||||||
|
"""
|
||||||
v_next = self.next_vert()
|
v_next = self.next_vert()
|
||||||
all_next_vert_list = []
|
all_next_vert_list = []
|
||||||
while v_next:
|
while v_next:
|
||||||
|
@ -165,7 +273,11 @@ class Square:
|
||||||
"""
|
"""
|
||||||
List of squares in the same line.
|
List of squares in the same line.
|
||||||
Does not include the considered square.
|
Does not include the considered square.
|
||||||
|
|
||||||
:return: The list of the squares in the same line.
|
:return: The list of the squares in the same line.
|
||||||
|
|
||||||
|
.. seealso:: all_prev_horiz(), all_next_horiz()
|
||||||
|
.. warnings:: The square must be part of a grid.
|
||||||
"""
|
"""
|
||||||
line_list = []
|
line_list = []
|
||||||
line_list.extend(self.all_prev_horiz())
|
line_list.extend(self.all_prev_horiz())
|
||||||
|
@ -177,7 +289,11 @@ class Square:
|
||||||
"""
|
"""
|
||||||
List of squares in the same column.
|
List of squares in the same column.
|
||||||
Does not include the considered square.
|
Does not include the considered square.
|
||||||
|
|
||||||
:return: The list of the squares in the same column.
|
:return: The list of the squares in the same column.
|
||||||
|
|
||||||
|
.. seealso:: all_prev_vert(), all_next_vert()
|
||||||
|
.. warnings:: The square must be part of a grid.
|
||||||
"""
|
"""
|
||||||
line_list = []
|
line_list = []
|
||||||
line_list.extend(self.all_prev_vert())
|
line_list.extend(self.all_prev_vert())
|
||||||
|
@ -186,13 +302,17 @@ class Square:
|
||||||
return line_list
|
return line_list
|
||||||
|
|
||||||
|
|
||||||
def solve_three_square(square) -> bool:
|
def solve_three_square(square):
|
||||||
"""
|
"""
|
||||||
|
Prevent 'three in a row'.
|
||||||
|
|
||||||
Checks before and after the square if there are two squares of the
|
Checks before and after the square if there are two squares of the
|
||||||
same color in order to prevent 'three in a row'.
|
same color in order to prevent 'three in a row'.
|
||||||
|
|
||||||
:param square: The Square to check
|
:param square: The Square to check
|
||||||
:type square: Square
|
:type square: Square
|
||||||
:return: A boolean : True if something has been done, else False.
|
:return: A boolean : True if something has been done, else False.
|
||||||
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
solved = False
|
solved = False
|
||||||
if square.is_empty():
|
if square.is_empty():
|
||||||
|
@ -284,10 +404,11 @@ class Grid:
|
||||||
self.squares_to_modify = squares_to_modify
|
self.squares_to_modify = squares_to_modify
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def squares(self) -> list:
|
def squares(self):
|
||||||
"""
|
"""
|
||||||
A method to get the squares in the grid.
|
A method to get the squares in the grid.
|
||||||
:return: The squares in the grid.
|
:return: The squares in the grid.
|
||||||
|
:rtype: list
|
||||||
"""
|
"""
|
||||||
return self._squares
|
return self._squares
|
||||||
|
|
||||||
|
@ -295,9 +416,12 @@ class Grid:
|
||||||
def squares(self, array):
|
def squares(self, array):
|
||||||
"""
|
"""
|
||||||
Replace the squares in the grid with the one provided in the array.
|
Replace the squares in the grid with the one provided in the array.
|
||||||
The array must be a list of list of characters (square array).
|
|
||||||
:param array: The array to replace the squares.
|
:param array: The array to replace the squares.
|
||||||
:type array: list
|
:type array: list
|
||||||
|
|
||||||
|
.. warnings:: The array must be a list containing
|
||||||
|
lists of characters (square array).
|
||||||
"""
|
"""
|
||||||
squares = []
|
squares = []
|
||||||
i = 0
|
i = 0
|
||||||
|
@ -311,14 +435,16 @@ class Grid:
|
||||||
i += 1
|
i += 1
|
||||||
self._squares = squares
|
self._squares = squares
|
||||||
|
|
||||||
def square(self, horiz, vert) -> Square:
|
def square(self, horiz, vert):
|
||||||
"""
|
"""
|
||||||
Used to get a specific square in the grid.
|
Used to get a specific square in the grid.
|
||||||
|
|
||||||
:param horiz: The horizontal position of the square to get.
|
:param horiz: The horizontal position of the square to get.
|
||||||
:type horiz: int
|
:type horiz: int
|
||||||
:param vert: The vertical position of the square to get.
|
:param vert: The vertical position of the square to get.
|
||||||
:type vert: int
|
:type vert: int
|
||||||
:return: The square at the given position
|
:return: The square at the given position
|
||||||
|
:rtype: Square
|
||||||
"""
|
"""
|
||||||
return self._squares[vert][horiz]
|
return self._squares[vert][horiz]
|
||||||
|
|
||||||
|
@ -333,33 +459,39 @@ class Grid:
|
||||||
representation += "\n"
|
representation += "\n"
|
||||||
return representation
|
return representation
|
||||||
|
|
||||||
def squares_on_line(self, line_number) -> list:
|
def squares_on_line(self, line_number):
|
||||||
"""
|
"""
|
||||||
Returns the squares on a line specified by the number
|
Returns the squares on a line specified by the number
|
||||||
(starting from zero).
|
(starting from zero).
|
||||||
|
|
||||||
:param line_number: The line to get.
|
:param line_number: The line to get.
|
||||||
:type line_number: int
|
:type line_number: int
|
||||||
:return: The list containing the squares on the required line.
|
:return: The list containing the squares on the required line.
|
||||||
|
:rtype: list
|
||||||
"""
|
"""
|
||||||
return self.squares[line_number]
|
return self.squares[line_number]
|
||||||
|
|
||||||
def squares_on_column(self, col_number) -> list:
|
def squares_on_column(self, col_number):
|
||||||
"""
|
"""
|
||||||
Returns the squares on a column specified by the number
|
Returns the squares on a column specified by the number
|
||||||
(starting from zero).
|
(starting from zero).
|
||||||
|
|
||||||
:param col_number: The column to get.
|
:param col_number: The column to get.
|
||||||
:type col_number: int
|
:type col_number: int
|
||||||
:return: The list containing the squares on the required column.
|
:return: The list containing the squares on the required column.
|
||||||
|
:rtype: list
|
||||||
"""
|
"""
|
||||||
col = []
|
col = []
|
||||||
for line in self.squares:
|
for line in self.squares:
|
||||||
col.append(line[col_number])
|
col.append(line[col_number])
|
||||||
return col
|
return col
|
||||||
|
|
||||||
def solve_threes(self) -> bool:
|
def solve_threes(self):
|
||||||
"""
|
"""
|
||||||
Solves the grid recursively to prevent 'three in a row'.
|
Solves the grid recursively to prevent 'three in a row'.
|
||||||
|
|
||||||
:return: True if a square has been modified, else False.
|
:return: True if a square has been modified, else False.
|
||||||
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
solved = False
|
solved = False
|
||||||
for square in self.squares_to_modify:
|
for square in self.squares_to_modify:
|
||||||
|
@ -368,6 +500,10 @@ class Grid:
|
||||||
return solved
|
return solved
|
||||||
|
|
||||||
def solve(self):
|
def solve(self):
|
||||||
|
"""
|
||||||
|
Solves the grid using 'three in a row', 'same number of red and blue
|
||||||
|
on the same line or column' and, later, 'no identical line or column'.
|
||||||
|
"""
|
||||||
solved = True
|
solved = True
|
||||||
while solved:
|
while solved:
|
||||||
if not self.solve_threes():
|
if not self.solve_threes():
|
||||||
|
@ -377,6 +513,13 @@ class Grid:
|
||||||
# self.solve_different_lines_or_columns()
|
# self.solve_different_lines_or_columns()
|
||||||
|
|
||||||
def solve_same_number(self):
|
def solve_same_number(self):
|
||||||
|
"""
|
||||||
|
Solves the grid implementing the fact that there is always the same
|
||||||
|
number of red and blue on the same line or column.
|
||||||
|
|
||||||
|
:return: True if a square has been modified, else False.
|
||||||
|
:rtype: bool
|
||||||
|
"""
|
||||||
solved = False
|
solved = False
|
||||||
for square in self.square_list:
|
for square in self.square_list:
|
||||||
if square.is_empty():
|
if square.is_empty():
|
||||||
|
@ -414,6 +557,15 @@ class Grid:
|
||||||
return solved
|
return solved
|
||||||
|
|
||||||
def solve_different_lines_or_columns(self):
|
def solve_different_lines_or_columns(self):
|
||||||
|
"""
|
||||||
|
Solves the grid implementing the fact that there isn't two identical
|
||||||
|
lines or columns.
|
||||||
|
|
||||||
|
:return: True if a square has been modified, else False.
|
||||||
|
:rtype: bool
|
||||||
|
|
||||||
|
.. warnings:: Function still not finished. DOESN'T WORK.
|
||||||
|
"""
|
||||||
for square in self.square_list:
|
for square in self.square_list:
|
||||||
line = string_from_list(square.same_line())
|
line = string_from_list(square.same_line())
|
||||||
col = string_from_list(square.same_column())
|
col = string_from_list(square.same_column())
|
||||||
|
|
Loading…
Reference in a new issue