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 check whether first player can take more candies than other or not in Python
Suppose we have a list of numbers called candies and two persons are racing to collect the most number of candies. This is a turn-based game where person 1 starts first, and in each turn a player can pick candies from either the front or the back of the list. We need to check whether person 1 can collect more candies than person 2.
So, if the input is like candies = [1, 4, 3, 8], then the output will be True. Person 1 can take 8 candies in the first round, and regardless of whether person 2 picks 1 or 3, person 1 can win by taking the remaining larger value.
Algorithm Approach
To solve this problem, we will use a recursive approach with minimax strategy ?
N:= size of candies listDefine a function
difference(left, right)that returns the maximum score differenceIf
leftis same asright, returncandies[left](only one candy left)-
Otherwise, return maximum of:
candies[left] - difference(left + 1, right)(take from front)candies[right] - difference(left, right - 1)(take from back)
Return
Truewhendifference(0, N - 1) > 0, otherwiseFalse
Example
class Solution:
def solve(self, candies):
N = len(candies)
def difference(left, right):
# Base case: only one candy left
if left == right:
return candies[left]
# Choose the better option: take from front or back
take_left = candies[left] - difference(left + 1, right)
take_right = candies[right] - difference(left, right - 1)
return max(take_left, take_right)
# Person 1 wins if they can achieve positive score difference
return difference(0, N - 1) > 0
# Test the solution
ob = Solution()
candies = [1, 4, 3, 8]
print(f"Can person 1 win? {ob.solve(candies)}")
Can person 1 win? True
How It Works
The algorithm uses the minimax principle. When it's person 1's turn, they try to maximize their advantage. When it's person 2's turn, they try to minimize person 1's advantage. The difference function calculates the maximum score difference person 1 can achieve assuming both players play optimally.
Step-by-Step Example
def solve_with_steps(candies):
print(f"Initial candies: {candies}")
def difference(left, right, depth=0):
indent = " " * depth
print(f"{indent}Evaluating range [{left}, {right}]: {candies[left:right+1]}")
if left == right:
print(f"{indent}Base case: return {candies[left]}")
return candies[left]
take_left = candies[left] - difference(left + 1, right, depth + 1)
take_right = candies[right] - difference(left, right - 1, depth + 1)
result = max(take_left, take_right)
print(f"{indent}Max of {take_left} and {take_right} = {result}")
return result
final_diff = difference(0, len(candies) - 1)
print(f"\nFinal difference: {final_diff}")
return final_diff > 0
# Example with detailed steps
candies = [1, 4, 3, 8]
result = solve_with_steps(candies)
print(f"Person 1 can win: {result}")
Initial candies: [1, 4, 3, 8]
Evaluating range [0, 3]: [1, 4, 3, 8]
Evaluating range [1, 3]: [4, 3, 8]
Evaluating range [2, 3]: [3, 8]
Evaluating range [3, 3]: [8]
Base case: return 8
Evaluating range [2, 2]: [3]
Base case: return 3
Max of -5 and 5 = 5
Evaluating range [1, 2]: [4, 3]
Evaluating range [2, 2]: [3]
Base case: return 3
Evaluating range [1, 1]: [4]
Base case: return 4
Max of 1 and -1 = 1
Max of -1 and 7 = 7
Evaluating range [0, 2]: [1, 4, 3]
Evaluating range [1, 2]: [4, 3]
Evaluating range [2, 2]: [3]
Base case: return 3
Evaluating range [1, 1]: [4]
Base case: return 4
Max of 1 and -1 = 1
Evaluating range [0, 1]: [1, 4]
Evaluating range [1, 1]: [4]
Base case: return 4
Evaluating range [0, 0]: [1]
Base case: return 1
Max of -3 and 3 = 3
Max of 0 and -2 = 0
Max of 6 and 1 = 6
Final difference: 6
Person 1 can win: True
Optimized Version with Memoization
For larger inputs, we can optimize using dynamic programming to avoid recalculating the same subproblems ?
class OptimizedSolution:
def solve(self, candies):
N = len(candies)
memo = {}
def difference(left, right):
if (left, right) in memo:
return memo[(left, right)]
if left == right:
memo[(left, right)] = candies[left]
return candies[left]
take_left = candies[left] - difference(left + 1, right)
take_right = candies[right] - difference(left, right - 1)
result = max(take_left, take_right)
memo[(left, right)] = result
return result
return difference(0, N - 1) > 0
# Test optimized solution
optimized = OptimizedSolution()
test_cases = [[1, 4, 3, 8], [2, 7, 9, 4, 4], [1, 5, 2]]
for candies in test_cases:
result = optimized.solve(candies)
print(f"Candies: {candies} ? Person 1 wins: {result}")
Candies: [1, 4, 3, 8] ? Person 1 wins: True Candies: [2, 7, 9, 4, 4] ? Person 1 wins: True Candies: [1, 5, 2] ? Person 1 wins: True
Conclusion
This problem demonstrates the minimax algorithm where each player plays optimally. The recursive solution calculates the maximum score difference person 1 can achieve, and memoization improves efficiency for larger inputs.
