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 list

  • Define a function difference(left, right) that returns the maximum score difference

  • If left is same as right, return candies[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 True when difference(0, N - 1) > 0, otherwise False

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.

Updated on: 2026-03-25T14:00:38+05:30

228 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements