S2Q2 · Snakes and Ladders - Next Position¶
⚡ Quick Reference
Type: Full I/O problem
Core idea: move forward by dice, stay if over 100, then apply one snake/ladder lookup.
pos, dice, n = map(int, input().split())
board = {}
for _ in range(n):
parts = input().split()
kind, a, b = parts[0], int(parts[1]), int(parts[2])
if kind == 'L':
board[a] = b # bottom → top
else:
board[a] = b # head → tail
new_pos = pos + dice
if new_pos > 100:
new_pos = pos
print(board.get(new_pos, new_pos))
Key rules:
- New position = pos + dice; if > 100 → stay at pos
- L bottom top → board[bottom] = top
- S head tail → board[head] = tail
- Look up board.get(new_pos, new_pos) - returns new_pos if no snake/ladder
- Only one move applied - no chaining
Problem Statement¶
Problem (I/O type)
Given current position, dice value, and snake/ladder positions, compute the next board position following the game rules.
Example:
5 3 3
L 8 15
S 17 4
L 20 25
15
Understanding the rules¶
Current pos = 5, dice = 3
New pos = 5 + 3 = 8
board = {8: 15, ← ladder (bottom 8 → top 15)
17: 4, ← snake (head 17 → tail 4)
20: 25} ← ladder (bottom 20 → top 25)
board.get(8, 8) = 15 → print 15 ✓
Edge case - exceeds 100:
Edge case - no snake or ladder:
Snakes and ladders use the same dict
Both snakes (S head tail) and ladders (L bottom top) map a trigger position to a destination. They can live in the same board dict - the lookup logic is identical regardless of type.
Tracing the example¶
| Step | Value |
|---|---|
| Parse first line | pos=5, dice=3, n=3 |
Read L 8 15 |
board[8] = 15 |
Read S 17 4 |
board[17] = 4 |
Read L 20 25 |
board[20] = 25 |
new_pos = 5 + 3 |
8 |
8 > 100? |
No |
board.get(8, 8) |
15 |
| Output | 15 ✓ |
Solution approaches¶
pos, dice, n = map(int, input().split())
board = {}
for _ in range(n):
kind, a, b = input().split()
board[int(a)] = int(b) # works for both L and S
new_pos = pos + dice
if new_pos > 100:
new_pos = pos
print(board.get(new_pos, new_pos))
Since both snakes and ladders map trigger → destination, we don't even need to check kind - just store a → b for both.
pos, dice, n = map(int, input().split())
ladders = {}
snakes = {}
for _ in range(n):
parts = input().split()
kind, a, b = parts[0], int(parts[1]), int(parts[2])
if kind == 'L':
ladders[a] = b
else:
snakes[a] = b
new_pos = pos + dice
if new_pos > 100:
print(pos)
elif new_pos in ladders:
print(ladders[new_pos])
elif new_pos in snakes:
print(snakes[new_pos])
else:
print(new_pos)
Keeps snakes and ladders in separate dicts - more explicit, easier to extend.
first = input().split()
pos, dice, n = int(first[0]), int(first[1]), int(first[2])
parse = lambda line: (int(line[1]), int(line[2]))
board = dict(parse(input().split()) for _ in range(n))
new_pos = pos + dice
print(board.get(new_pos if new_pos <= 100 else pos,
new_pos if new_pos <= 100 else pos))
Lambda parses each line; the ternary handles the >100 case inline in the get call.
Key takeaways¶
dict.get(pos, pos) for no-move default
board.get(new_pos, new_pos) returns the mapped destination if the position is a trigger, or the position itself if not. One call handles both cases - no separate if pos in board check needed.
Snakes and ladders share the same mapping
Both map a trigger position to a destination. The kind field (`L` or `S`) only tells you whether it moves you up or down - but the lookup logic is identical. One dict handles both.
Check > 100 before the board lookup
If the dice roll would take you past 100, stay at the current position - don't check the board at all. The order matters: exceeding 100 is checked first, board lookup second.