S2Q2 · Print Pieces Moved from Chess Notation¶
⚡ Quick Reference
Type: Full I/O problem
Core idea: split the input into tokens, skip move numbers (ending in .), map each move to a piece name.
piece_map = {'K': 'King', 'Q': 'Queen', 'R': 'Rook',
'B': 'Bishop', 'N': 'Knight'}
for token in input().split():
if token.endswith("."):
continue
if token.startswith("O"):
print("King")
print("Rook")
else:
print(piece_map.get(token[0], "Pawn"))
Key rules:
- Move numbers end with . -skip them
- Castling starts with O -print King then Rook
- Uppercase letter at start → named piece via dict lookup
- Lowercase letter at start → Pawn
Problem Statement¶
Problem (I/O type)
Read a string of chess moves in standard algebraic notation. For each move (ignoring move numbers), print the name of the piece moved. For castling, print both King and Rook.
Example 1:
1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. O-O Qc7
Pawn
Pawn
Knight
Knight
Bishop
Pawn
King
Rook
Queen
Example 2:
1. e4 e5 2. O-O O-O-O
Pawn
Pawn
King
Rook
King
Rook
Understanding the input format¶
After split(), "1. e4 e5 2. Nf3 Nc6" becomes:
Three categories of token:
| Token pattern | Example | Action |
|---|---|---|
Ends with . |
"1.", "2." |
Skip -it's a move number |
Starts with O |
"O-O", "O-O-O" |
Print King then Rook |
Starts with K/Q/R/B/N |
"Nf3", "Bb5" |
Print the named piece |
| Starts with lowercase | "e4", "a6" |
Print Pawn |
Why lowercase = Pawn?
In standard algebraic notation, piece moves always start with an uppercase letter. Pawn moves have no prefix -they start directly with the file letter in lowercase. So anything starting with a lowercase letter is a pawn move.
Tracing Example 1¶
Input: "1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. O-O Qc7"
| Token | Action | Output |
|---|---|---|
1. |
skip | - |
e4 |
lowercase → Pawn | Pawn |
e5 |
lowercase → Pawn | Pawn |
2. |
skip | - |
Nf3 |
N → Knight |
Knight |
Nc6 |
N → Knight |
Knight |
3. |
skip | - |
Bb5 |
B → Bishop |
Bishop |
a6 |
lowercase → Pawn | Pawn |
4. |
skip | - |
O-O |
castling | King, Rook |
Qc7 |
Q → Queen |
Queen |
Solution approaches¶
piece_map = {
'K': 'King', 'Q': 'Queen', 'R': 'Rook',
'B': 'Bishop', 'N': 'Knight'
}
for token in input().split():
if token.endswith("."):
continue
if token.startswith("O"):
print("King\nRook")
else:
print(piece_map.get(token[0], "Pawn"))
dict.get(key, default) returns "Pawn" when the first character isn't in piece_map. Eliminates the explicit else branch.
piece_map = {
'K': 'King', 'Q': 'Queen', 'R': 'Rook',
'B': 'Bishop', 'N': 'Knight'
}
def get_piece(token):
if token.startswith("O"):
return "King\nRook"
return piece_map.get(token[0], "Pawn")
tokens = filter(lambda t: not t.endswith("."), input().split())
print("\n".join(map(get_piece, tokens)))
filter(lambda t: not t.endswith("."), ...) removes move numbers. map(get_piece, ...) converts each token to its piece name(s). "\n".join(...) prints all at once. Fully functional pipeline.
Key takeaways¶
dict.get(key, default) for safe lookup
piece_map.get(token[0], "Pawn") returns the piece name if the letter is in the map, or "Pawn" if not. Eliminates the explicit else branch.
Handle castling before general case
Castling tokens start with O, which isn't in the piece map. Check for castling first with token.startswith("O") before the general lookup.
filter() to skip unwanted tokens
filter(lambda t: not t.endswith("."), tokens) cleanly removes move numbers before processing. Separating filtering from processing makes both steps easier to read and test.