Решение на Шахматни фенове от Виктор Боев

Обратно към всички решения

Към профила на Виктор Боев

Резултати

  • 9 точки от тестове
  • 0 бонус точки
  • 9 точки общо
  • 15 успешни тест(а)
  • 2 неуспешни тест(а)

Код

from enum import Enum
class ChessException(Exception):
pass
class points(Enum):
pawn = 1
knigth = 3
bishop = 3
king = 4
rook = 5
queen = 9
class ChessScore:
_sum = 0
def __init__(self, pieces):
self._pieces = pieces
for piece in pieces:
self._sum += self.__calc_points(piece.upper())
def __calc_points(self, upper_square):
match(upper_square):
case 'P':
return points.pawn.value
case 'N':
return points.knigth.value
case 'B':
return points.bishop.value
case 'R':
return points.rook.value
case 'Q':
return points.queen.value
case 'K':
return points.king.value
case _:
return 0
def __int__(self):
return self._sum
def __eq__(self, object):
return int(self) == int(object)
def __gt__(self, object):
return int(self) > int(object)
def __lt__(self, object):
return int(self) < int(object)
def __ge__(self, object):
return int(self) >= int(object)
def __le__(self, object):
return int(self) <= int(object)
def __add__(self, object):
return int(self) + int(object)
def __sub__(self, object):
return int(self) - int(object)
class ChessPosition:
_pieces_lowercase = ('p', 'n', 'b', 'r', 'q', 'k')
_white_score = 0
_black_score = 0
def __init__(self, position):
self._position = {
1: [], 2: [], 3: [], 4: [],
5: [], 6: [], 7: [], 8: [],
}
self._position_str = position
self._fill_dict(position)
self._check_num_rows_and_cols()
self._validate_kings()
self._check_pawns_location()
pieces = []
for piece in self._pieces_lowercase:
pieces.append(piece.upper())
self._white_score = self._get_score(pieces)
self._black_score = self._get_score(self._pieces_lowercase)
def _fill_dict(self, position):
count = 8
list = []
for symbol in position:
if symbol == '/':
self._position[count] = list
list = []
count -= 1
else:
if (symbol.isdigit()):
for i in range(int(symbol)):
list.append('-')
else:
list.append(symbol)
self._position[1] = list
def _count_pieces(self):
sum = 0
for row in self._position:
for letter in self._position[row]:
if letter != '-':
sum += 1
return sum
def _check_num_rows_and_cols(self):
col = 0
for row in self._position:
for symbol in self._position[row]:
col += 1
if col != 8:
raise ChessException("lines")
col = 0
def _validate_kings(self):
white_king = (-1, -1)
black_king = (-1, -1)
col = 1
for row in self._position:
for symbol in self._position[row]:
if symbol == 'K':
if white_king != (-1, -1):
raise ChessException("kings")
white_king = (row, col)
if symbol == 'k':
if black_king != (-1, -1):
raise ChessException("kings")
black_king = (row, col)
col += 1
col = 1
if (black_king == (-1, -1) or white_king == (-1, -1)):
raise ChessException("kings")
if (abs(white_king[0] - black_king[0]) <= 1 and abs(white_king[1] - black_king[1]) <= 1):
raise ChessException("kings")
def _check_pawns_location(self):
if ('p' in self._position[1] or 'P' in self._position[1]):
raise ChessException("pawns")
if ('p' in self._position[8] or 'P' in self._position[8]):
raise ChessException("pawns")
def _get_score(self, pieces):
pieces_result = []
for row in self._position:
for symbol in self._position[row]:
if symbol in pieces:
pieces_result.append(symbol)
return int(ChessScore(pieces_result))
def get_white_score(self):

Това е операция, която ще връща константа стойност всеки път, така че е добра идея да инициализираш ChessScore веднъж, да го запазиш като атрибут на инстанцията и после само да го връщаш при нужда.

return self._white_score
def get_black_score(self):
return self._black_score
def white_is_winning(self):
return self.get_white_score() - self.get_black_score() >= 1
def black_is_winning(self):
return self.get_black_score() - self.get_white_score() >= 1
def is_equal(self):
return self.get_black_score() == self.get_white_score()
def __str__(self):
return self._position_str
def __len__(self):
return self._count_pieces()
def __getitem__(self, index):
col = ord(index[0].upper()) - ord('A')
row = int(index[1])
if row < 1 or row > 8 or col < 0 or col > 7:
return None
if self._position[row][col] == '-':
return None
return self._position[row][col]

Лог от изпълнението

....F.......F....
======================================================================
FAIL: test_get_white_score (test.TestChessPosition)
Test get_white_score.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
AssertionError: 4 is not an instance of <class 'solution.ChessScore'>

======================================================================
FAIL: test_white_is_winning (test.TestChessPosition)
Test white_is_winning.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
AssertionError: 4 is not an instance of <class 'solution.ChessScore'>

----------------------------------------------------------------------
Ran 17 tests in 0.166s

FAILED (failures=2)

История (2 версии и 11 коментара)

Виктор обнови решението на 25.11.2022 19:56 (преди над 1 година)

+from enum import Enum
+
+class ChessException(Exception):
+ pass
+
+class points(Enum):
+ pawn = 1
+ knigth = 3
+ bishop = 3
+ king = 4
+ rook = 5
+ queen = 9
+
+class ChessScore:
+
+ def __calc_points(self, upper_square):
+ match(upper_square) :
+ case 'P':
+ return points.pawn.value
+ case 'N':
+ return points.knigth.value
+ case 'B':
+ return points.bishop.value
+ case 'R':
+ return points.rook.value
+ case 'Q':
+ return points.queen.value
+ case 'K':
+ return points.king.value
+ case _:
+ return 0
+
+ def __init__(self, pieces):
+ self.__pieces = pieces
+
+ def __calculate(self):

Резултатът от този метод ще е константа, така че можеш просто да го запишеш като атрибут на инстанцията и да го преизползваш, вместо да въртиш цикъла при всяко извикване на метод, който изисква сумата.

+ sum = 0
+ for piece in self.__pieces :
+ sum += self.__calc_points(piece.upper())
+ return sum
+
+ def __int__(self):
+ return self.__calculate()
+
+ def __eq__(self, object):
+ return self.__int__() == object.__int__()
+
+ def __gt__(self, object):
+ return self.__int__() > object.__int__()
+
+ def __lt__(self, object):
+ return self.__int__() < object.__int__()
+
+ def __ge__(self, object):
+ return self.__int__() >= object.__int__()
+
+ def __le__(self, object):
+ return self.__int__() <= object.__int__()
+
+ def __add__(self, object):
+ return self.__int__() + object.__int__()
+
+ def __sub__(self, object):
+ return self.__int__() - object.__int__()
+
+class ChessPosition:
+
+ __pieces_lowercase = ('p', 'n', 'b', 'r', 'q', 'k')
+
+ def __get_square_by_coordinates(self, row, col):
+
+ counter_row = 8
+ counter_col = 1
+ for square in self.__position:

Вместо да въртиш и цялата матрица, търсейки конкретен ред и колона, можеш директно да попиташ за тях. Най-добре предварително да дефинираш дъската като двумерен масив, или като речник, за да можеш лесно да манипулираш стойностите в последствие, вместо при всяко извикване на функцията да си играеш да го парсваш наново.

+ if counter_row == row and counter_col == col:
+ for letter in self.__pieces_lowercase:
+ if square.lower() == letter:
+ return square
+ return None
+
+ if square == '/':
+ counter_row -= 1
+ counter_col = 0
+
+ if (square.isdigit()):
+ counter_col += ord(square) - ord('0')
+
+ else:
+ counter_col += 1
+
+ def __count_pieces(self):
+ sum = 0
+ for square in self.__position:
+
+ for letter in self.__pieces_lowercase:
+ if square.lower() == letter:
+ sum += 1
+ break
+
+ return sum
+
+ def __check_num_rows_and_cols(self):
+ row = 8
+ col = 1
+ for square in self.__position:
+ if square == '/':
+ row -= 1
+ if col != 9:
+ raise ChessException("lines")
+ col = 0
+ if (square.isdigit()):
+ col += ord(square) - ord('0')
+ else:
+ col += 1
+
+ if row != 1:
+ raise ChessException("lines")
+
+ def __validate_kings(self):
+ row = 8
+ col = 1
+ white_king = (-1, -1)
+ black_king = (-1, -1)
+ for square in self.__position:
+ if square == '/' :
+ row -= 1
+ col = 0
+ else:
+ if square == 'K':
+ if white_king != (-1, -1):
+ raise ChessException("kings")
+ white_king = (row, col)
+ if square == 'k':
+ if black_king != (-1, -1):
+ raise ChessException("kings")
+ black_king = (row, col)
+
+ col += 1
+
+ if (black_king == (-1, -1) or white_king == (-1, -1)):
+ raise ChessException("kings")
+ if (abs(white_king[0] - black_king[0]) <= 1 and abs(white_king[1] - black_king[1]) <= 1):
+ raise ChessException("kings")
+
+ def __check_pawns_location(self):
+ row = 8
+ for square in self.__position:
+ if (row == 1 or row == 8) and square == 'P':
+ raise ChessException("pawns")
+ if square == '/' :
+ row -= 1
+
+ def __get_score(self, pieces):
+ pieces_result = []
+ for square in self.__position:
+ for letter in pieces:
+ if letter == square:
+ pieces_result.append(square)
+
+ return int(ChessScore(pieces_result))
+
+ def __init__(self, position):
+ self.__position = position
+ if not isinstance(position, str):

Според мен това е излишно. Реално погледнато, така, както съм дефинирал условието, би могъл да работиш с всякакъв интерабъл от стрингове. Да, не е по дизайн, но би могъл, а този ред те спира и ти дава да използваш само стрингове.

+ raise ChessException("The position isn't string")
+ self.__check_num_rows_and_cols()
+ self.__validate_kings()
+ self.__check_pawns_location()
+
+ def get_white_score(self):

Това е операция, която ще връща константа стойност всеки път, така че е добра идея да инициализираш ChessScore веднъж, да го запазиш като атрибут на инстанцията и после само да го връщаш при нужда.

+ pieces = []
+ for piece in self.__pieces_lowercase:
+ pieces.append(piece.upper())
+ return self.__get_score(pieces)
+
+ def get_black_score(self):
+ return self.__get_score(self.__pieces_lowercase)
+
+ def white_is_winning(self):
+ return self.get_white_score() - self.get_black_score() >= 1
+
+ def black_is_winning(self):
+ return self.get_black_score() - self.get_white_score() >= 1
+
+ def is_equal(self):
+ return self.get_black_score() == self.get_white_score()
+
+ def __str__(self):
+ return self.__position
+
+ def __len__(self):
+ return self.__count_pieces()
+
+ def __getitem__(self, index):
+ col = ord(index[0].upper()) - ord('A') + 1
+ row = ord(index[1]) - ord('0')
+ return self.__get_square_by_coordinates(row, col)

Виктор обнови решението на 27.11.2022 17:32 (преди над 1 година)

from enum import Enum
class ChessException(Exception):
pass
class points(Enum):
pawn = 1
knigth = 3
bishop = 3
king = 4
rook = 5
queen = 9
class ChessScore:
+ _sum = 0
+
+ def __init__(self, pieces):
+ self._pieces = pieces
+ for piece in pieces:
+ self._sum += self.__calc_points(piece.upper())
+
def __calc_points(self, upper_square):
- match(upper_square) :
+ match(upper_square):
case 'P':
return points.pawn.value
case 'N':
return points.knigth.value
case 'B':
return points.bishop.value
case 'R':
return points.rook.value
case 'Q':
return points.queen.value
case 'K':
return points.king.value
case _:
return 0
- def __init__(self, pieces):
- self.__pieces = pieces
-
- def __calculate(self):
- sum = 0
- for piece in self.__pieces :
- sum += self.__calc_points(piece.upper())
- return sum
-
def __int__(self):
- return self.__calculate()
+ return self._sum
def __eq__(self, object):
- return self.__int__() == object.__int__()
+ return int(self) == int(object)
def __gt__(self, object):
- return self.__int__() > object.__int__()
+ return int(self) > int(object)
def __lt__(self, object):
- return self.__int__() < object.__int__()
+ return int(self) < int(object)
def __ge__(self, object):
- return self.__int__() >= object.__int__()
+ return int(self) >= int(object)
def __le__(self, object):
- return self.__int__() <= object.__int__()
-
+ return int(self) <= int(object)
+
def __add__(self, object):
- return self.__int__() + object.__int__()
+ return int(self) + int(object)
def __sub__(self, object):
- return self.__int__() - object.__int__()
+ return int(self) - int(object)
class ChessPosition:
- __pieces_lowercase = ('p', 'n', 'b', 'r', 'q', 'k')
+ _pieces_lowercase = ('p', 'n', 'b', 'r', 'q', 'k')
+ _white_score = 0
+ _black_score = 0
- def __get_square_by_coordinates(self, row, col):
+ def __init__(self, position):
+ self._position = {
+ 1: [], 2: [], 3: [], 4: [],
+ 5: [], 6: [], 7: [], 8: [],
+ }
+ self._position_str = position
+ self._fill_dict(position)
+ self._check_num_rows_and_cols()
+ self._validate_kings()
+ self._check_pawns_location()
- counter_row = 8
- counter_col = 1
- for square in self.__position:
- if counter_row == row and counter_col == col:
- for letter in self.__pieces_lowercase:
- if square.lower() == letter:
- return square
- return None
+ pieces = []
+ for piece in self._pieces_lowercase:
+ pieces.append(piece.upper())
- if square == '/':
- counter_row -= 1
- counter_col = 0
+ self._white_score = self._get_score(pieces)
+ self._black_score = self._get_score(self._pieces_lowercase)
- if (square.isdigit()):
- counter_col += ord(square) - ord('0')
-
+ def _fill_dict(self, position):
+ count = 8
+ list = []
+ for symbol in position:
+ if symbol == '/':
+ self._position[count] = list
+ list = []
+ count -= 1
else:
- counter_col += 1
+ if (symbol.isdigit()):
+ for i in range(int(symbol)):
+ list.append('-')
+ else:
+ list.append(symbol)
+
+ self._position[1] = list
- def __count_pieces(self):
+ def _count_pieces(self):
sum = 0
- for square in self.__position:
-
- for letter in self.__pieces_lowercase:
- if square.lower() == letter:
+ for row in self._position:
+ for letter in self._position[row]:
+ if letter != '-':
sum += 1
- break
-
return sum
- def __check_num_rows_and_cols(self):
- row = 8
- col = 1
- for square in self.__position:
- if square == '/':
- row -= 1
- if col != 9:
- raise ChessException("lines")
- col = 0
- if (square.isdigit()):
- col += ord(square) - ord('0')
- else:
+ def _check_num_rows_and_cols(self):
+ col = 0
+ for row in self._position:
+ for symbol in self._position[row]:
col += 1
+ if col != 8:
+ raise ChessException("lines")
+ col = 0
- if row != 1:
- raise ChessException("lines")
-
- def __validate_kings(self):
- row = 8
- col = 1
+ def _validate_kings(self):
white_king = (-1, -1)
black_king = (-1, -1)
- for square in self.__position:
- if square == '/' :
- row -= 1
- col = 0
- else:
- if square == 'K':
+ col = 1
+ for row in self._position:
+ for symbol in self._position[row]:
+ if symbol == 'K':
if white_king != (-1, -1):
raise ChessException("kings")
white_king = (row, col)
- if square == 'k':
+ if symbol == 'k':
if black_king != (-1, -1):
raise ChessException("kings")
black_king = (row, col)
+ col += 1
+ col = 1
- col += 1
-
if (black_king == (-1, -1) or white_king == (-1, -1)):
raise ChessException("kings")
if (abs(white_king[0] - black_king[0]) <= 1 and abs(white_king[1] - black_king[1]) <= 1):
raise ChessException("kings")
- def __check_pawns_location(self):
- row = 8
- for square in self.__position:
- if (row == 1 or row == 8) and square == 'P':
- raise ChessException("pawns")
- if square == '/' :
- row -= 1
+ def _check_pawns_location(self):
+ if ('p' in self._position[1] or 'P' in self._position[1]):
+ raise ChessException("pawns")
+ if ('p' in self._position[8] or 'P' in self._position[8]):
+ raise ChessException("pawns")
- def __get_score(self, pieces):
+ def _get_score(self, pieces):
pieces_result = []
- for square in self.__position:
- for letter in pieces:
- if letter == square:
- pieces_result.append(square)
+ for row in self._position:
+ for symbol in self._position[row]:
+ if symbol in pieces:
+ pieces_result.append(symbol)
return int(ChessScore(pieces_result))
- def __init__(self, position):
- self.__position = position
- if not isinstance(position, str):
- raise ChessException("The position isn't string")
- self.__check_num_rows_and_cols()
- self.__validate_kings()
- self.__check_pawns_location()
-
def get_white_score(self):
- pieces = []
- for piece in self.__pieces_lowercase:
- pieces.append(piece.upper())
- return self.__get_score(pieces)
+ return self._white_score
def get_black_score(self):
- return self.__get_score(self.__pieces_lowercase)
+ return self._black_score
def white_is_winning(self):
return self.get_white_score() - self.get_black_score() >= 1
def black_is_winning(self):
return self.get_black_score() - self.get_white_score() >= 1
def is_equal(self):
return self.get_black_score() == self.get_white_score()
def __str__(self):
- return self.__position
+ return self._position_str
def __len__(self):
- return self.__count_pieces()
+ return self._count_pieces()
def __getitem__(self, index):
- col = ord(index[0].upper()) - ord('A') + 1
- row = ord(index[1]) - ord('0')
+ col = ord(index[0].upper()) - ord('A')
- return self.__get_square_by_coordinates(row, col)
+ row = int(index[1])
+ if row < 1 or row > 8 or col < 0 or col > 7:
+ return None
+ if self._position[row][col] == '-':
+ return None
+ return self._position[row][col]