Number of ways for playing first move optimally in a NIM game

Two players A and B are playing NIM Game with each other. Both are playing optimally. Player A starts the game. The task is to find the number of ways of playing 1st move for A to ensure a winning strategy for A if possible, otherwise print -1.

Examples:

Input: arr[] = {1, 2, 3}
Output: -1
There is no winning strategy for A no matter how optimally he plays.

Input: arr[] = {2, 4, 5}
Output: 1
In order to play optimally, A will pick one coin from first pile and that’s the only optimal move.

Approach:

  1. First check who will win the game by taking XOR of all the array elements if XOR is zero then no matter how optimally A play, A will always lose. If XOR is non-zero then go to Step 2.
  2. We will check for every pile if we can remove some coins from that pile so that after this move, XOR of all the array elements will be zero. So for all piles, one by one we will take xor of all remaining elements of the array and will check if XOR value is greater than the number of coins in the pile. If so, it is not possible to play the first move using this pile because we can only remove coins from the pile in a move, and cannot add coins. Otherwise, we will increment the number of ways.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
// Utility function to return the XOR
// of all the array elements
int xorArray(int arr[], int n)
{
    int res = 0;
    for (int i = 0; i < n; i++)
        res = res ^ arr[i];
  
    return res;
}
  
// Function to return the count of ways
// to play the first move optimally
int getTotalWays(int arr[], int n)
{
  
    // XOR of all the array elements
    int xorArr = xorArray(arr, n);
  
    // The player making the first move
    // can't win the game no matter
    // how optimally he plays
    if (xorArr == 0)
        return -1;
  
    // Initialised with zero
    int numberOfWays = 0;
  
    for (int i = 0; i < n; i++) {
  
        // requiredCoins is the number of coins
        // the player making the move must leave
        // in the current pile in order to play optimally
        int requiredCoins = xorArr ^ arr[i];
  
        // If requiredCoins is less than the current
        // amount of coins in the current pile
        // then only the player can make an optimal move
        if (requiredCoins < arr[i])
            numberOfWays++;
    }
  
    return numberOfWays;
}
  
// Driver code
int main()
{
  
    // Coins in each pile
    int arr[] = { 3, 4, 4, 2 };
    int n = sizeof(arr) / sizeof(arr[0]);
  
    cout << getTotalWays(arr, n);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
class GFG
{
      
// Utility function to return the XOR
// of all the array elements
static int xorArray(int arr[], int n)
{
    int res = 0;
    for (int i = 0; i < n; i++)
        res = res ^ arr[i];
  
    return res;
}
  
// Function to return the count of ways
// to play the first move optimally
static int getTotalWays(int arr[], int n)
{
  
    // XOR of all the array elements
    int xorArr = xorArray(arr, n);
  
    // The player making the first move
    // can't win the game no matter
    // how optimally he plays
    if (xorArr == 0)
        return -1;
  
    // Initialised with zero
    int numberOfWays = 0;
  
    for (int i = 0; i < n; i++)
    {
  
        // requiredCoins is the number of coins
        // the player making the move must leave
        // in the current pile in order to play optimally
        int requiredCoins = xorArr ^ arr[i];
  
        // If requiredCoins is less than the current
        // amount of coins in the current pile
        // then only the player can make an optimal move
        if (requiredCoins < arr[i])
            numberOfWays++;
    }
    return numberOfWays;
}
  
// Driver code
public static void main(String[] args)
{
  
    // Coins in each pile
    int arr[] = { 3, 4, 4, 2 };
    int n =arr.length;
  
    System.out.println(getTotalWays(arr, n));
}
}
  
// This code is contributed by Code_Mech

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation of the approach
  
# Utility function to return the
# XOR of all the array elements
def xorArray(arr, n):
  
    res = 0
    for i in range(0, n):
        res = res ^ arr[i]
  
    return res
  
# Function to return the count of ways
# to play the first move optimally
def getTotalWays(arr, n):
  
    # XOR of all the array elements
    xorArr = xorArray(arr, n)
  
    # The player making the first move
    # can't win the game no matter
    # how optimally he plays
    if xorArr == 0:
        return -1
  
    # Initialised with zero
    numberOfWays = 0
  
    for i in range(0, n): 
  
        # requiredCoins is the number of coins the
        # player making the move must leave in the
        # current pile in order to play optimally
        requiredCoins = xorArr ^ arr[i]
  
        # If requiredCoins is less than the current
        # amount of coins in the current pile
        # then only the player can make an optimal move
        if requiredCoins < arr[i]:
            numberOfWays += 1
  
    return numberOfWays
  
# Driver code
if __name__ == "__main__":
  
    # Coins in each pile
    arr = [3, 4, 4, 2]
    n = len(arr)
  
    print(getTotalWays(arr, n))
      
# This code is contributed by Rituraj Jain

chevron_right


C#

// C# implementation of the approach
using System;

class GFG
{

// Utility function to return the XOR
// of all the array elements
static int xorArray(int []arr, int n)
{
int res = 0;
for (int i = 0; i < n; i++) res = res ^ arr[i]; return res; } // Function to return the count of ways // to play the first move optimally static int getTotalWays(int []arr, int n) { // XOR of all the array elements int xorArr = xorArray(arr, n); // The player making the first move // can't win the game no matter // how optimally he plays if (xorArr == 0) return -1; // Initialised with zero int numberOfWays = 0; for (int i = 0; i < n; i++) { // requiredCoins is the number of coins // the player making the move must leave // in the current pile in order to play optimally int requiredCoins = xorArr ^ arr[i]; // If requiredCoins is less than the current // amount of coins in the current pile // then only the player can make an optimal move if (requiredCoins < arr[i]) numberOfWays++; } return numberOfWays; } // Driver code static public void Main () { // Coins in each pile int []arr = { 3, 4, 4, 2 }; int n = arr.Length; Console.Write(getTotalWays(arr, n)); } } // This code is contributed by ajit. [tabby title="PHP"]

filter_none

edit
close

play_arrow

link
brightness_4
code

<?php
// PHP implementation of the approach
  
// Utility function to return the XOR
// of all the array elements
function xorArray($arr, $n)
{
    $res = 0;
    for ($i = 0; $i < $n; $i++)
        $res = $res ^ $arr[$i];
  
    return $res;
}
  
// Function to return the count of ways
// to play the first move optimally
function getTotalWays($arr, $n)
{
  
    // XOR of all the array elements
    $xorArr = xorArray($arr, $n);
  
    // The player making the first move
    // can't win the game no matter
    // how optimally he plays
    if ($xorArr == 0)
        return -1;
  
    // Initialised with zero
    $numberOfWays = 0;
  
    for ($i = 0; $i < $n; $i++)
    {
  
        // requiredCoins is the number of coins
        // the player making the move must leave
        // in the current pile in order to play optimally
        $requiredCoins = $xorArr ^ $arr[$i];
  
        // If requiredCoins is less than the current
        // amount of coins in the current pile
        // then only the player can make an optimal move
        if ($requiredCoins < $arr[$i])
            $numberOfWays++;
    }
  
    return $numberOfWays;
}
  
// Driver code
  
// Coins in each pile
$arr = array(3, 4, 4, 2 );
$n = sizeof($arr);
  
echo getTotalWays($arr, $n);
  
// This code is contributed 
// by Akanksha Rai
?>

chevron_right


Output:

1

Time Complexity: O(N)



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.