Решение на Шахматни фенове от Никола Михайлов

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

Към профила на Никола Михайлов

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 17 успешни тест(а)
  • 0 неуспешни тест(а)

Код

from collections import defaultdict
POINTS_PER_FIGURE = {
'R': 5,
'N': 3,
'B': 3,
'Q': 9,
'K': 4,
'P': 1
}
KING_EXCEPTION = 'kings'
PAWN_EXCEPTION = 'pawns'
WHITE_KING = 'K'
BLACK_KING = 'k'
PAWNS = 'P', 'p'
DELIMITER = '/'
START_ROW = 8
START_COLUMN = 0
class ChessException(Exception):
pass
class ChessPosition:
def __init__(self, FEN):
self._validate_board(FEN)
self._board = defaultdict(lambda: None)
white_figures, black_figures = self._parse_board(FEN)
self._FEN = FEN
self._number_figures = len(white_figures) + len(black_figures)
self._white_score = ChessScore(white_figures)
self._black_score = ChessScore(black_figures)
def get_white_score(self):
return self._white_score
def get_black_score(self):
return self._black_score
def white_is_winning(self):
return int(self._white_score) > int(self._black_score)
def black_is_winning(self):
return int(self._white_score) < int(self._black_score)
def is_equal(self):
return int(self._white_score) == int(self._black_score)
def __str__(self):
return self._FEN
def __len__(self):
return self._number_figures
def __getitem__(self, index):
return self._board[index]
def _king_validation(self, white_king_coord, black_king_coord):
if white_king_coord is None or black_king_coord is None:
raise ChessException(KING_EXCEPTION)
black_king_x, black_king_y = black_king_coord
white_king_x, white_king_y = white_king_coord
if abs(black_king_x - white_king_x) <= 1 and abs(black_king_y - white_king_y) <= 1:
raise ChessException(KING_EXCEPTION)
def _validate_board(self, FEN):
pawn_validation = True
kings_position = dict.fromkeys([WHITE_KING, BLACK_KING], None)
row = START_ROW
column = START_COLUMN
for char in FEN:
if char == DELIMITER:
row -= 1
column = START_COLUMN
continue
if char.isdigit():
column += int(char)
continue
if char in (WHITE_KING, BLACK_KING):
if kings_position[char] is not None:
raise ChessException(KING_EXCEPTION)
else:
kings_position[char] = row, column
column += 1
if pawn_validation and char in PAWNS and row in (1, 8):
pawn_validation = False
self._king_validation(kings_position[WHITE_KING], kings_position[BLACK_KING])
if not pawn_validation:
raise ChessException(PAWN_EXCEPTION)
def _parse_board(self, FEN):
white_figures = []
black_figures = []
row = START_ROW
column = START_COLUMN
for char in FEN:
position = f'{chr(ord("A") + column)}{row}'
if char == DELIMITER:
row -= 1
column = START_COLUMN
continue
if char.isdigit():
column += int(char)
continue
white_figures.append(char) if char.isupper() else black_figures.append(char)
self._board[position] = char
column += 1
return white_figures, black_figures
class ChessScore:
def __init__(self, figures):
self.score = sum([POINTS_PER_FIGURE[figure.upper()] for figure in figures])
def __int__(self):
return self.score
def __lt__(self, other):
return self.score < int(other)
def __le__(self, other):
return self.score <= int(other)
def __eq__(self, other):
return self.score == int(other)
def __ne__(self, other):
return self.score != int(other)
def __gt__(self, other):
return self.score > int(other)
def __add__(self, other):
return self.score + int(other)
def __sub__(self, other):
return self.score - int(other)

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

.................
----------------------------------------------------------------------
Ran 17 tests in 0.163s

OK

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

Никола обнови решението на 27.11.2022 00:07 (преди почти 2 години)

+from collections import defaultdict
+
+POINTS_PER_FIGURE = {
+ 'R': 5,
+ 'N': 3,
+ 'B': 3,
+ 'Q': 9,
+ 'K': 4,
+ 'P': 1
+}
+
+KING_EXCEPTION = 'kings'
+PAWN_EXCEPTION = 'pawns'
+WHITE_KING = 'K'
+BLACK_KING = 'k'
+PAWNS = 'P', 'p'
+DELIMITER = '/'
+
+
+class ChessException(Exception):
+ pass
+
+
+class ChessPosition:
+ def __init__(self, FEN):
+ self._board = defaultdict(lambda: None)
+
+ white_figures, black_figures = self._validate_board(FEN)

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

Съгласен съм! И на мен не ми харесва, просто не знаех кое е по-удачно първо да стане. Логично е първо да е валидирането, ама не исках два пъти да минавам през FEN-a (максималната му дължина е 71, ако не се лъжа, ама пак не ми се струваше хубаво). Ако пък първо го парснем и се окаже невалиден, язък че сме го парсвали :D Затова реших да го наблъскам всичко в едно и "да си измия ръцете" така.

+
+ self._FEN = FEN
+ self._number_figures = len(white_figures) + len(black_figures)
+ self._white_score = ChessScore(white_figures)
+ self._black_score = ChessScore(black_figures)
+
+ def get_white_score(self):
+ return self._white_score
+
+ def get_black_score(self):
+ return self._black_score
+
+ def white_is_winning(self):
+ return int(self._white_score) > int(self._black_score)
+
+ def black_is_winning(self):
+ return int(self._white_score) < int(self._black_score)
+
+ def is_equal(self):
+ return int(self._white_score) == int(self._black_score)
+
+ def __str__(self):
+ return self._FEN
+
+ def __len__(self):
+ return self._number_figures
+
+ def __getitem__(self, index):
+ return self._board[index]
+
+ def _king_validation(self, white_king_coord, black_king_coord):
+ if white_king_coord is None or black_king_coord is None:
+ raise ChessException(KING_EXCEPTION)
+
+ black_king_x, black_king_y = black_king_coord
+ white_king_x, white_king_y = white_king_coord
+
+ if abs(black_king_x - white_king_x) <= 1 and abs(black_king_y - white_king_y) <= 1:
+ raise ChessException(KING_EXCEPTION)
+
+ def _validate_board(self, FEN):
+ white_figures = []
+ black_figures = []
+ pawn_validation = True
+ kings_position = dict.fromkeys([WHITE_KING, BLACK_KING], None)
+ row = 8
+ column = 0
+
+ for char in FEN:
+ position = f'{chr(ord("A") + column)}{row}'
+
+ if char == DELIMITER:
+ row -= 1
+ column = 0
+ continue
+
+ # Should be '1' <= char <= '8' but I've signed the contract ;)
+ if char.isdigit():
+ column += int(char)
+ continue
+
+ if char in (WHITE_KING, BLACK_KING):
+ if kings_position[char] is not None:
+ raise ChessException(KING_EXCEPTION)
+ else:
+ kings_position[char] = row, column
+
+ column += 1
+
+ # If 'pawn_validation' is False there is no reason to continue with the code below
+ # because the board is invalid already
+ if not pawn_validation:
+ continue
+
+ if char in PAWNS and row in (1, 8):
+ pawn_validation = False
+ continue
+
+ white_figures.append(char) if char.isupper() else black_figures.append(char)
+ self._board[position] = char
+
+ self._king_validation(kings_position[WHITE_KING], kings_position[BLACK_KING])
+ if not pawn_validation:
+ raise ChessException(PAWN_EXCEPTION)
+
+ return white_figures, black_figures
+
+
+class ChessScore:
+ def __init__(self, figures):
+ self.score = sum([POINTS_PER_FIGURE[figure.upper()] for figure in figures])
+
+ def __int__(self):
+ return self.score
+
+ def __lt__(self, other):
+ return self.score < int(other)
+
+ def __le__(self, other):
+ return self.score <= int(other)
+
+ def __eq__(self, other):
+ return self.score == int(other)
+
+ def __ne__(self, other):
+ return self.score != int(other)
+
+ def __gt__(self, other):
+ return self.score > int(other)
+
+ def __add__(self, other):
+ return self.score + int(other)
+
+ def __sub__(self, other):
+ return self.score - int(other)

Никола обнови решението на 28.11.2022 03:20 (преди почти 2 години)

from collections import defaultdict
POINTS_PER_FIGURE = {
'R': 5,
'N': 3,
'B': 3,
'Q': 9,
'K': 4,
'P': 1
}
KING_EXCEPTION = 'kings'
PAWN_EXCEPTION = 'pawns'
WHITE_KING = 'K'
BLACK_KING = 'k'
PAWNS = 'P', 'p'
DELIMITER = '/'
+START_ROW = 8
+START_COLUMN = 0
class ChessException(Exception):
pass
class ChessPosition:
def __init__(self, FEN):
+ self._validate_board(FEN)
+
self._board = defaultdict(lambda: None)
+ white_figures, black_figures = self._parse_board(FEN)
- white_figures, black_figures = self._validate_board(FEN)
-
self._FEN = FEN
self._number_figures = len(white_figures) + len(black_figures)
self._white_score = ChessScore(white_figures)
self._black_score = ChessScore(black_figures)
def get_white_score(self):
return self._white_score
def get_black_score(self):
return self._black_score
def white_is_winning(self):
return int(self._white_score) > int(self._black_score)
def black_is_winning(self):
return int(self._white_score) < int(self._black_score)
def is_equal(self):
return int(self._white_score) == int(self._black_score)
def __str__(self):
return self._FEN
def __len__(self):
return self._number_figures
def __getitem__(self, index):
return self._board[index]
def _king_validation(self, white_king_coord, black_king_coord):
if white_king_coord is None or black_king_coord is None:
raise ChessException(KING_EXCEPTION)
black_king_x, black_king_y = black_king_coord
white_king_x, white_king_y = white_king_coord
if abs(black_king_x - white_king_x) <= 1 and abs(black_king_y - white_king_y) <= 1:
raise ChessException(KING_EXCEPTION)
def _validate_board(self, FEN):
- white_figures = []
- black_figures = []
pawn_validation = True
kings_position = dict.fromkeys([WHITE_KING, BLACK_KING], None)
- row = 8
- column = 0
+ row = START_ROW
+ column = START_COLUMN
for char in FEN:
- position = f'{chr(ord("A") + column)}{row}'
-
if char == DELIMITER:
row -= 1
- column = 0
+ column = START_COLUMN
continue
- # Should be '1' <= char <= '8' but I've signed the contract ;)
if char.isdigit():
column += int(char)
continue
if char in (WHITE_KING, BLACK_KING):
if kings_position[char] is not None:
raise ChessException(KING_EXCEPTION)
else:
kings_position[char] = row, column
column += 1
- # If 'pawn_validation' is False there is no reason to continue with the code below
- # because the board is invalid already
- if not pawn_validation:
+ if pawn_validation and char in PAWNS and row in (1, 8):
+ pawn_validation = False
+
+ self._king_validation(kings_position[WHITE_KING], kings_position[BLACK_KING])
+ if not pawn_validation:
+ raise ChessException(PAWN_EXCEPTION)
+
+ def _parse_board(self, FEN):
+ white_figures = []
+ black_figures = []
+ row = START_ROW
+ column = START_COLUMN
+
+ for char in FEN:
+ position = f'{chr(ord("A") + column)}{row}'
+
+ if char == DELIMITER:
+ row -= 1
+ column = START_COLUMN
continue
- if char in PAWNS and row in (1, 8):
- pawn_validation = False
+ if char.isdigit():
+ column += int(char)
continue
white_figures.append(char) if char.isupper() else black_figures.append(char)
self._board[position] = char
-
- self._king_validation(kings_position[WHITE_KING], kings_position[BLACK_KING])
- if not pawn_validation:
- raise ChessException(PAWN_EXCEPTION)
+ column += 1
return white_figures, black_figures
class ChessScore:
def __init__(self, figures):
self.score = sum([POINTS_PER_FIGURE[figure.upper()] for figure in figures])
def __int__(self):
return self.score
def __lt__(self, other):
return self.score < int(other)
def __le__(self, other):
return self.score <= int(other)
def __eq__(self, other):
return self.score == int(other)
def __ne__(self, other):
return self.score != int(other)
def __gt__(self, other):
return self.score > int(other)
def __add__(self, other):
return self.score + int(other)
def __sub__(self, other):
return self.score - int(other)