Решение на Шахматни фенове от Радостин Маринов

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

Към профила на Радостин Маринов

Резултати

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

Код

from functools import total_ordering
scores = {
'r': 5,
'n': 3,
'b': 3,
'q': 9,
'k': 4,
'p': 1,
}
class ChessException(Exception):
pass
class ChessScore:
def __init__(self, pieces):
self.__score = sum(map(lambda piece: scores.get(piece, 0), pieces))
def __int__(self):
return self.__score
def __lt__(self, other):
return self.__score < int(other)
def __eq__(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)
class ChessPosition:
def __init__(self, fen):
self.__original_fen = fen
self.__parsed_fen = self.__parse_fen(fen)
@property
def __original_fen(self):
return self.__original_fen_value
@__original_fen.setter
def __original_fen(self, value):
self.__check_kings_count(value)
self.__original_fen_value = value
@property
def __parsed_fen(self):
return self.__parsed_fen_value
@__parsed_fen.setter
def __parsed_fen(self, value):
self.__check_kings_positions(value)
self.__check_pawns(value)
self.__parsed_fen_value = value
def get_white_score(self):
return ChessScore(map(str.lower, filter(lambda char: char.isupper(), self.__original_fen)))
def get_black_score(self):
return ChessScore(filter(lambda char: char.islower(), self.__original_fen))
def white_is_winning(self):
return self.get_white_score() > self.get_black_score()
def black_is_winning(self):
return self.get_black_score() > self.get_white_score()
def is_equal(self):
return self.get_black_score() == self.get_white_score()
def __str__(self):
return self.__original_fen
def __len__(self):
return len(list(filter(lambda char: char.isalpha(), self.__original_fen)))
def __getitem__(self, item):
column = ord(item[0]) - ord('A')

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

row = int(item[1]) - 1
return self.__parsed_fen[row][column]
@classmethod
def __check_kings_positions(cls, parsed_fen):
pos_w_king = cls.__position_of_piece(parsed_fen, 'K')
pos_b_king = cls.__position_of_piece(parsed_fen, 'k')
if abs(pos_w_king[0] - pos_b_king[0]) <= 1 and abs(pos_w_king[1] - pos_b_king[1]) <= 1:
raise ChessException('kings')
@classmethod
def __parse_fen(cls, fen):
return list(map(cls.__expand_numbers, fen.split('/')))[::-1]
@staticmethod
def __expand_numbers(line):
return list(map(lambda char: None if char == '-' else char,
''.join(['-' * int(char) if char.isdigit() else char for char in line])))
@staticmethod
def __check_kings_count(fen):
if fen.count('K') != 1 or fen.count('k') != 1:
raise ChessException('kings')
@staticmethod
def __check_pawns(parsed_fen):
if any(pawn in parsed_fen[0] + parsed_fen[7] for pawn in ('p', 'P')):
raise ChessException('pawns')
@staticmethod
def __position_of_piece(parsed_fen, piece):
for index, line in enumerate(parsed_fen):
if piece in line:
return index, line.index(piece)
return None

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

.................
----------------------------------------------------------------------
Ran 17 tests in 0.201s

OK

История (5 версии и 7 коментара)

Радостин обнови решението на 26.11.2022 17:20 (преди над 1 година)

+from functools import total_ordering
+
+scores = {
+ 'r': 5,
+ 'n': 3,
+ 'b': 3,
+ 'q': 9,
+ 'k': 4,
+ 'p': 1,
+}
+
+
+class ChessException(Exception):
+ def __init__(self, message):
+ super().__init__(message)
+ self.message = message
+
+
+@total_ordering
+class ChessScore:
+ def __init__(self, pieces):
+ self.score = sum(filter(lambda score: score is not None, map(lambda piece: scores.get(piece), pieces)))
+
+ def __int__(self):
+ return self.score
+
+ def __lt__(self, other):
+ return self.score < other.score
+
+ def __eq__(self, other):
+ return self.score == other.score
+
+ def __add__(self, other):
+ return self.__int__() + int(other)
+
+ def __sub__(self, other):
+ return self.__int__() - int(other)
+
+
+class ChessPosition:
+ def __init__(self, fen):
+ if fen.count('K') != 1 or fen.count('k') != 1:
+ raise ChessException('kings')
+
+ self.__original_fen = fen
+
+ fen = ''.join('-' * int(char) if char.isdigit() else char for char in fen)
+
+ self.__fen = fen
+
+ pos_w_king = self.__position_of_piece(fen, 'K')
+ pos_b_king = self.__position_of_piece(fen, 'k')
+
+ if pos_b_king is not None and pos_w_king is not None \
+ and abs(pos_w_king[0] - pos_b_king[0]) <= 1 and abs(pos_w_king[1] - pos_b_king[1]) <= 1:
+ raise ChessException('kings')
+
+ if any(pawn in fen[:8] + fen[-8:] for pawn in ('p', 'P')):
+ raise ChessException('pawns')
+
+ def get_white_score(self):
+ return ChessScore(map(lambda upper: upper.lower(), filter(lambda char: char.isupper(), self.__fen)))
+
+ def get_black_score(self):
+ return ChessScore(filter(lambda char: char.islower(), self.__fen))
+
+ def white_is_winning(self):
+ return self.get_white_score() > self.get_black_score()
+
+ def black_is_winning(self):
+ return self.get_black_score() > self.get_white_score()
+
+ def is_equal(self):
+ return self.get_black_score() == self.get_white_score()
+
+ def __str__(self):
+ return self.__original_fen
+
+ def __len__(self):
+ return len(list(filter(lambda char: char.isalpha(), self.__fen)))
+
+ def __getitem__(self, item):
+ column = ord(item[0]) - ord('A')
+ row = int(item[1])
+ pos = (8 - row) * 8 + column
+ result = list(filter(lambda char: char != '/', self.__fen))[pos]
+ return result if result != '-' else None
+
+ @staticmethod
+ def __position_of_piece(fen, piece):
+ index = fen.replace('/', '').index(piece)
+ if index == -1:
+ return None
+ return index // 8, index % 8

Радостин обнови решението на 26.11.2022 17:25 (преди над 1 година)

from functools import total_ordering
scores = {
'r': 5,
'n': 3,
'b': 3,
'q': 9,
'k': 4,
'p': 1,
}
class ChessException(Exception):
def __init__(self, message):
super().__init__(message)
self.message = message
@total_ordering
class ChessScore:
def __init__(self, pieces):
self.score = sum(filter(lambda score: score is not None, map(lambda piece: scores.get(piece), pieces)))
def __int__(self):
return self.score
def __lt__(self, other):
return self.score < other.score
def __eq__(self, other):
return self.score == other.score
def __add__(self, other):
return self.__int__() + int(other)
def __sub__(self, other):
return self.__int__() - int(other)
class ChessPosition:
def __init__(self, fen):
if fen.count('K') != 1 or fen.count('k') != 1:
raise ChessException('kings')
self.__original_fen = fen
fen = ''.join('-' * int(char) if char.isdigit() else char for char in fen)
self.__fen = fen
pos_w_king = self.__position_of_piece(fen, 'K')
pos_b_king = self.__position_of_piece(fen, 'k')
- if pos_b_king is not None and pos_w_king is not None \
- and abs(pos_w_king[0] - pos_b_king[0]) <= 1 and abs(pos_w_king[1] - pos_b_king[1]) <= 1:
+ if abs(pos_w_king[0] - pos_b_king[0]) <= 1 and abs(pos_w_king[1] - pos_b_king[1]) <= 1:
raise ChessException('kings')
if any(pawn in fen[:8] + fen[-8:] for pawn in ('p', 'P')):
raise ChessException('pawns')
def get_white_score(self):
return ChessScore(map(lambda upper: upper.lower(), filter(lambda char: char.isupper(), self.__fen)))
def get_black_score(self):
return ChessScore(filter(lambda char: char.islower(), self.__fen))
def white_is_winning(self):
return self.get_white_score() > self.get_black_score()
def black_is_winning(self):
return self.get_black_score() > self.get_white_score()
def is_equal(self):
return self.get_black_score() == self.get_white_score()
def __str__(self):
return self.__original_fen
def __len__(self):
return len(list(filter(lambda char: char.isalpha(), self.__fen)))
def __getitem__(self, item):
column = ord(item[0]) - ord('A')
row = int(item[1])
pos = (8 - row) * 8 + column
result = list(filter(lambda char: char != '/', self.__fen))[pos]
return result if result != '-' else None
@staticmethod
def __position_of_piece(fen, piece):
index = fen.replace('/', '').index(piece)
if index == -1:
return None
return index // 8, index % 8

Радостин обнови решението на 26.11.2022 21:21 (преди над 1 година)

from functools import total_ordering
scores = {
'r': 5,
'n': 3,
'b': 3,
'q': 9,
'k': 4,
'p': 1,
}
class ChessException(Exception):
def __init__(self, message):
super().__init__(message)
self.message = message
class ChessScore:
def __init__(self, pieces):
- self.score = sum(filter(lambda score: score is not None, map(lambda piece: scores.get(piece), pieces)))
+ self.__score = sum(filter(lambda score: score is not None, map(lambda piece: scores.get(piece), pieces)))

Ако не съм оплескал някоя скоба, това прави същото: sum(map(lambda piece: scores.get(piece, 0), pieces)).
Просто казваш на речника да дава нула, при невалиден ключ, с което си спестяваш филтъра.

def __int__(self):
- return self.score
+ return self.__score
def __lt__(self, other):
- return self.score < other.score
+ return self.__score < int(other)
def __eq__(self, other):
- return self.score == other.score
+ return self.__score == int(other)
def __add__(self, other):
- return self.__int__() + int(other)
+ return self.__score + int(other)
def __sub__(self, other):
- return self.__int__() - int(other)
+ return self.__score - int(other)
class ChessPosition:
def __init__(self, fen):
if fen.count('K') != 1 or fen.count('k') != 1:
raise ChessException('kings')
self.__original_fen = fen
fen = ''.join('-' * int(char) if char.isdigit() else char for char in fen)
self.__fen = fen
pos_w_king = self.__position_of_piece(fen, 'K')
pos_b_king = self.__position_of_piece(fen, 'k')
if abs(pos_w_king[0] - pos_b_king[0]) <= 1 and abs(pos_w_king[1] - pos_b_king[1]) <= 1:
raise ChessException('kings')
if any(pawn in fen[:8] + fen[-8:] for pawn in ('p', 'P')):
raise ChessException('pawns')
def get_white_score(self):
return ChessScore(map(lambda upper: upper.lower(), filter(lambda char: char.isupper(), self.__fen)))
def get_black_score(self):
return ChessScore(filter(lambda char: char.islower(), self.__fen))
def white_is_winning(self):
return self.get_white_score() > self.get_black_score()
def black_is_winning(self):
return self.get_black_score() > self.get_white_score()
def is_equal(self):
return self.get_black_score() == self.get_white_score()
def __str__(self):
return self.__original_fen
def __len__(self):
return len(list(filter(lambda char: char.isalpha(), self.__fen)))
def __getitem__(self, item):
column = ord(item[0]) - ord('A')

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

row = int(item[1])
pos = (8 - row) * 8 + column
result = list(filter(lambda char: char != '/', self.__fen))[pos]
return result if result != '-' else None
@staticmethod
def __position_of_piece(fen, piece):
index = fen.replace('/', '').index(piece)
if index == -1:
return None
return index // 8, index % 8

Радостин обнови решението на 27.11.2022 17:07 (преди над 1 година)

from functools import total_ordering
scores = {
'r': 5,
'n': 3,
'b': 3,
'q': 9,
'k': 4,
'p': 1,
}
class ChessException(Exception):
- def __init__(self, message):
- super().__init__(message)
- self.message = message
+ pass
@total_ordering
class ChessScore:
def __init__(self, pieces):
- self.__score = sum(filter(lambda score: score is not None, map(lambda piece: scores.get(piece), pieces)))
+ self.__score = sum(map(lambda piece: scores.get(piece, 0), pieces))
def __int__(self):
return self.__score
def __lt__(self, other):
return self.__score < int(other)
def __eq__(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)
class ChessPosition:
def __init__(self, fen):
- if fen.count('K') != 1 or fen.count('k') != 1:
- raise ChessException('kings')
-
self.__original_fen = fen
+ self.__parsed_fen = self.__parse_fen(fen)
- fen = ''.join('-' * int(char) if char.isdigit() else char for char in fen)
+ self.__check_kings_count()
+ self.__check_kings_positions()
+ self.__check_pawns()
- self.__fen = fen
-
- pos_w_king = self.__position_of_piece(fen, 'K')
- pos_b_king = self.__position_of_piece(fen, 'k')
-
- if abs(pos_w_king[0] - pos_b_king[0]) <= 1 and abs(pos_w_king[1] - pos_b_king[1]) <= 1:
- raise ChessException('kings')
-
- if any(pawn in fen[:8] + fen[-8:] for pawn in ('p', 'P')):
- raise ChessException('pawns')
-
def get_white_score(self):
- return ChessScore(map(lambda upper: upper.lower(), filter(lambda char: char.isupper(), self.__fen)))
+ return ChessScore(map(str.lower, filter(lambda char: char.isupper(), self.__original_fen)))
def get_black_score(self):
- return ChessScore(filter(lambda char: char.islower(), self.__fen))
+ return ChessScore(filter(lambda char: char.islower(), self.__original_fen))
def white_is_winning(self):
return self.get_white_score() > self.get_black_score()
def black_is_winning(self):
return self.get_black_score() > self.get_white_score()
def is_equal(self):
return self.get_black_score() == self.get_white_score()
def __str__(self):
return self.__original_fen
def __len__(self):
- return len(list(filter(lambda char: char.isalpha(), self.__fen)))
+ return len(list(filter(lambda char: char.isalpha(), self.__original_fen)))
def __getitem__(self, item):
column = ord(item[0]) - ord('A')
- row = int(item[1])
- pos = (8 - row) * 8 + column
- result = list(filter(lambda char: char != '/', self.__fen))[pos]
- return result if result != '-' else None
+ row = int(item[1]) - 1
+ return self.__parsed_fen[row][column]
+ def __check_kings_positions(self):
+ pos_w_king = self.__position_of_piece('K')
+ pos_b_king = self.__position_of_piece('k')
+
+ if abs(pos_w_king[0] - pos_b_king[0]) <= 1 and abs(pos_w_king[1] - pos_b_king[1]) <= 1:
+ raise ChessException('kings')
+
+ def __check_kings_count(self):
+ if self.__original_fen.count('K') != 1 or self.__original_fen.count('k') != 1:
+ raise ChessException('kings')
+
+ def __check_pawns(self):
+ if any(pawn in self.__parsed_fen[0] + self.__parsed_fen[7] for pawn in ('p', 'P')):
+ raise ChessException('pawns')
+
+ def __position_of_piece(self, piece):
+ for index, line in enumerate(self.__parsed_fen):
+ if piece in line:
+ return index, line.index(piece)
+ return None
+
+ @classmethod
+ def __parse_fen(cls, fen):
+ return list(map(cls.__expand_numbers, fen.split('/')))[::-1]
+
@staticmethod
- def __position_of_piece(fen, piece):
- index = fen.replace('/', '').index(piece)
+ def __expand_numbers(line):
- if index == -1:
+ return list(map(lambda char: None if char == '-' else char,
- return None
+ ''.join(['-' * int(char) if char.isdigit() else char for char in line])))
- return index // 8, index % 8

Радостин обнови решението на 28.11.2022 09:54 (преди над 1 година)

from functools import total_ordering
scores = {
'r': 5,
'n': 3,
'b': 3,
'q': 9,
'k': 4,
'p': 1,
}
class ChessException(Exception):
pass
@total_ordering
class ChessScore:
def __init__(self, pieces):
self.__score = sum(map(lambda piece: scores.get(piece, 0), pieces))
def __int__(self):
return self.__score
def __lt__(self, other):
return self.__score < int(other)
def __eq__(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)
class ChessPosition:
def __init__(self, fen):
self.__original_fen = fen
self.__parsed_fen = self.__parse_fen(fen)
- self.__check_kings_count()
- self.__check_kings_positions()
- self.__check_pawns()
+ @property
+ def __original_fen(self):
+ return self.__original_fen_value
+ @__original_fen.setter
+ def __original_fen(self, value):
+ self.__check_kings_count(value)
+ self.__original_fen_value = value
+
+ @property
+ def __parsed_fen(self):
+ return self.__parsed_fen_value
+
+ @__parsed_fen.setter
+ def __parsed_fen(self, value):
+ self.__check_kings_positions(value)
+ self.__check_pawns(value)
+ self.__parsed_fen_value = value
+
def get_white_score(self):
return ChessScore(map(str.lower, filter(lambda char: char.isupper(), self.__original_fen)))
def get_black_score(self):
return ChessScore(filter(lambda char: char.islower(), self.__original_fen))
def white_is_winning(self):
return self.get_white_score() > self.get_black_score()
def black_is_winning(self):
return self.get_black_score() > self.get_white_score()
def is_equal(self):
return self.get_black_score() == self.get_white_score()
def __str__(self):
return self.__original_fen
def __len__(self):
return len(list(filter(lambda char: char.isalpha(), self.__original_fen)))
def __getitem__(self, item):
column = ord(item[0]) - ord('A')
row = int(item[1]) - 1
return self.__parsed_fen[row][column]
- def __check_kings_positions(self):
- pos_w_king = self.__position_of_piece('K')
- pos_b_king = self.__position_of_piece('k')
+ @classmethod
+ def __check_kings_positions(cls, parsed_fen):
+ pos_w_king = cls.__position_of_piece(parsed_fen, 'K')
+ pos_b_king = cls.__position_of_piece(parsed_fen, 'k')
if abs(pos_w_king[0] - pos_b_king[0]) <= 1 and abs(pos_w_king[1] - pos_b_king[1]) <= 1:
raise ChessException('kings')
- def __check_kings_count(self):
- if self.__original_fen.count('K') != 1 or self.__original_fen.count('k') != 1:
- raise ChessException('kings')
-
- def __check_pawns(self):
- if any(pawn in self.__parsed_fen[0] + self.__parsed_fen[7] for pawn in ('p', 'P')):
- raise ChessException('pawns')
-
- def __position_of_piece(self, piece):
- for index, line in enumerate(self.__parsed_fen):
- if piece in line:
- return index, line.index(piece)
- return None
-
@classmethod
def __parse_fen(cls, fen):
return list(map(cls.__expand_numbers, fen.split('/')))[::-1]
@staticmethod
def __expand_numbers(line):
return list(map(lambda char: None if char == '-' else char,
''.join(['-' * int(char) if char.isdigit() else char for char in line])))
+
+ @staticmethod
+ def __check_kings_count(fen):
+ if fen.count('K') != 1 or fen.count('k') != 1:
+ raise ChessException('kings')
+
+ @staticmethod
+ def __check_pawns(parsed_fen):
+ if any(pawn in parsed_fen[0] + parsed_fen[7] for pawn in ('p', 'P')):
+ raise ChessException('pawns')
+
+ @staticmethod
+ def __position_of_piece(parsed_fen, piece):
+ for index, line in enumerate(parsed_fen):
+ if piece in line:
+ return index, line.index(piece)
+ return None