Can I Use A Nested For Loop For An If-else Statement With Multiple Conditions In Python?
Solution 1:
First, I would recommend outsourcing this check to a dedicated function.
Second, you can use a dict with your expected max values, and use a comprehension with all()
to perform the check more concisely.
max_counts = {
'bking': 1,
'bqueen': 1,
'brook': 2,
'bknight': 2,
'bbishop': 2,
'bpawn': 8,
'wking': 1,
'wqueen': 1,
'wrook': 2,
'wknight': 2,
'wbishop': 2,
'wpawn': 8
}
defboard_is_valid(count, board):
returnlen(board) <= 32andall(
count[piece] <= ct
for (piece, ct) in max_counts.items()
)
If you want to be slightly less verbose with max_counts
, you could try creating a dummy dict with the basic counts for king
, queen
, rook
, etc., and make max_counts
the result of adding two copies of that list, one with 'b'
prefixed to each key and the other with 'w'
. But I don't think thats necessary if this is the entire set of pieces.
Also consider that this may not be a foolproof method of validation for your chessboard. Pawns may promote into any other type of piece besides king, so having more than one queen or more than two rooks is technically possible.
Solution 2:
A simple way would be to encode the maxima for each category. The only special case is that there must be one king. Instead of having pieces
as a list
, make it a dict
that maps the piece to the number of instances at the start of the game:
pieces = {'queen': 1, 'rook': 2, 'knight': 2, 'bishop': 2, 'pawn': 8, 'king': 1}
Second, by concatenating keys, you make your life more complicated. I would recommend making a nested dictionary, or a list with two dictionaries in it to contain black and white pieces separately:
count = {'b': {'king': 1, 'pawn': 3, 'bishop': 1},
'w': {'king': 1, 'rook': 1, 'queen': 1}}
Checking is now much easier. First, verify that the keys of each dictionary in count
is a subset of the allowed keys. You can do this using the fact that dict.keys
returns a set
-like object:
count['b'].keys() < pieces.keys()
Next, check that the values for corresponding keys are within the allowed range:
all(pieces[k] >= v for k, v in count['b'].items())
And finally, check that there is a king on the board:
count['b'].get('king') == 1
You should not use count['b']['king']
because that will raise a KeyError
when there is no king on the board. It's much more consistent to return False
, as you do for all other invalid boards.
Assuming you go with the structure of count
I propose, here is how I would write the check:
def validate(count):
def check_side(side):
return side.keys() < pieces.keys() and all(pieces[k] >= v for k, v in side.items()) and side.get('king') == 1
return all(check(v) for v in count.values())
The operators and
and all
are short-circuiting, so if the answer is False
, this will return as early as possible.
Notice also that with this approach you no longer need colors
. The information is stored in count.keys()
. Redundancy of information is usually not a great idea.
Post a Comment for "Can I Use A Nested For Loop For An If-else Statement With Multiple Conditions In Python?"