Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to find winner of stone game in Python
Suppose Amal and Bimal are playing a stone game where Amal goes first. The game works as follows −
There are n stones in a pile. Each player can take a stone and receive points based on their individual valuation of that stone. We have two arrays A_Values and B_Values where A_Values[i] and B_Values[i] represent how Amal and Bimal value the ith stone respectively.
The player with the highest total score wins. If scores are equal, it's a draw. Both players play optimally and know each other's valuations. Return 1 if Amal wins, -1 if Bimal wins, and 0 for a draw.
Strategy
Since both players play optimally, each player will choose the stone that maximizes their advantage. The key insight is that players should prioritize stones with the highest combined value (A_Values[i] + B_Values[i]) to prevent the opponent from gaining maximum benefit.
Algorithm Steps
- Calculate combined values for each stone
- Sort stones by combined value in descending order
- Simulate optimal play: Amal picks on even turns, Bimal on odd turns
- Compare final scores to determine the winner
Example
Let's trace through the example with A_Values = [2,4] and B_Values = [3,5] ?
def solve(A_Values, B_Values):
n = len(A_Values)
combined_values = []
# Calculate combined values for each stone
for i in range(n):
combined_val = A_Values[i] + B_Values[i]
combined_values.append([combined_val, i])
# Sort by combined value in descending order
combined_values.sort(reverse=True)
print("Sorted stones by combined value:", combined_values)
score_a, score_b = 0, 0
# Simulate optimal play
for turn in range(n):
stone_info = combined_values[turn]
stone_index = stone_info[1]
if turn % 2 == 0: # Amal's turn (even turns)
score_a += A_Values[stone_index]
print(f"Turn {turn + 1}: Amal picks stone {stone_index}, gets {A_Values[stone_index]} points")
else: # Bimal's turn (odd turns)
score_b += B_Values[stone_index]
print(f"Turn {turn + 1}: Bimal picks stone {stone_index}, gets {B_Values[stone_index]} points")
print(f"Final scores - Amal: {score_a}, Bimal: {score_b}")
if score_a > score_b:
return 1
elif score_a == score_b:
return 0
else:
return -1
# Test the function
A_Values = [2, 4]
B_Values = [3, 5]
result = solve(A_Values, B_Values)
print(f"Winner: {result}")
Sorted stones by combined value: [[9, 1], [5, 0]] Turn 1: Amal picks stone 1, gets 4 points Turn 2: Bimal picks stone 0, gets 3 points Final scores - Amal: 4, Bimal: 3 Winner: 1
Clean Implementation
Here's the final optimized solution ?
def stone_game_winner(A_Values, B_Values):
n = len(A_Values)
# Create list of (combined_value, index) pairs
combined_values = [(A_Values[i] + B_Values[i], i) for i in range(n)]
# Sort by combined value in descending order
combined_values.sort(reverse=True)
score_a, score_b = 0, 0
# Simulate optimal play
for turn in range(n):
stone_index = combined_values[turn][1]
if turn % 2 == 0: # Amal's turn
score_a += A_Values[stone_index]
else: # Bimal's turn
score_b += B_Values[stone_index]
# Determine winner
if score_a > score_b:
return 1
elif score_a == score_b:
return 0
else:
return -1
# Test cases
print(stone_game_winner([2, 4], [3, 5])) # Output: 1
print(stone_game_winner([1, 2], [3, 4])) # Output: -1
print(stone_game_winner([1, 1], [1, 1])) # Output: 0
1 -1 0
How It Works
The algorithm works by recognizing that in optimal play, each player should prioritize stones that deny the opponent the most potential points. By sorting stones by their combined value, we ensure that the most valuable stones (in terms of total benefit) are picked first.
Conclusion
This stone game solution uses a greedy approach where players prioritize stones with the highest combined value. The time complexity is O(n log n) due to sorting, and space complexity is O(n) for storing the combined values.
