Prerequisites:
Sprague Grundy theorem
Grundy Numbers
Nim is a famous game in which two players take turns removing items from distinct piles. During each turn, a player must remove one or more items from a single, non-empty pile. The winner of the game is whichever player removes the last item from the last non-empty pile.
Now, For each non-empty pile, either player can remove zero items from that pile and have it count as their move; however, this move can only be performed once per pile by either player.
Given the number of items in each pile, determine who will win the game; Player 1 or player 2. If player 1 starts the game and both plays optimally.
Examples:
Input : 3 [18, 47, 34]
Output : Player 2 wins
G = g(18)^g(47)^g(34) = (17)^(48)^(33) = 0
Grundy number(G), for this game is zero.
Player 2 wins.
Input : 3 [32, 49, 58]
Output : Player 1 wins
G = g(31)^g(50)^g(57) = (17)^(48)^(33) = 20
Grundy number(G), for this game is non-zero.
Player 1 wins.
Approach:
Grundy number for each pile is calculated based on the number of stones.To compensate the zero move we will have to modify grundy values we used in standard nim game.
If pile size is odd; grundy number is size+1 and
if pile size is even; grundy number is size-1.
We XOR all the grundy number values to check if final Grundy number(G) of game is non zero or not to decide who is winner of game.
Explanation:
Grundy number of a state is the smallest positive integer that cannot be reached in one valid move.
So, we need to calculate mex value for each n, bottom up wise so that we can induce the grundy number for each n. where n is the pile size.
Winning state: A tuple of values from where the current player will win the game no matter what opponent does. (If G!=0)
Losing state: A tuple of values from where the current player will lose the game no matter what opponent does. (If G=0)
For a given pile size n, we have two states:
(1) n with no zero moves available,
grundy number will same as standard nim game.
(2) n with zero moves available, we can
reach above state and other states with
zero moves remaining.
For, n = 0, g(0) = 0, empty pile
For, n = 1, we can reach two states:
(1) n = 0 (zero move not used)
(2) n = 1 (zero move used)
Therefore, g(1) = mex{0, 1} which implies
that g(1)=2.
For, n = 2, we can reach :
(1) n = 0 (zero move not used) state
because this is a valid move.
(2) n = 1 (zero move not used) is a valid
move, whose grundy number is 2.
Therefore, g(2) = mex{0,2} which implies
that g(2)=1.
note that n=1 (zero move used) is not a valid
move.
If we try to build a solution bottom-up
like this, it turns out that if n is even,
the grundy number is n - 1 and when it is odd,
the grundy is n + 1.
Below is the implementation of above approach:
C++
// CPP program for the variation
// in nim game
#include <bits/stdc++.h>
using namespace std;
// Function to return final
// grundy Number(G) of game
int solve(int p[], int n)
{
int G = 0;
for (int i = 0; i < n; i++) {
// if pile size is odd
if (p[i] & 1)
// We XOR pile size+1
G ^= (p[i] + 1);
else // if pile size is even
// We XOR pile size-1
G ^= (p[i] - 1);
}
return G;
}
// driver program
int main()
{
// Game with 3 piles
int n = 3;
// pile with different sizes
int p[3] = { 32, 49, 58 };
// Function to return result of game
int res = solve(p, n);
if (res == 0) // if G is zero
cout << "Player 2 wins";
else // if G is non zero
cout << "Player 1 wins";
return 0;
}
Java
// Java program for the variation
// in nim game
class GFG {
// Function to return final
// grundy Number(G) of game
static int solve(int p[], int n)
{
int G = 0;
for (int i = 0; i < n; i++) {
// if pile size is odd
if (p[i]%2!=0)
// We XOR pile size+1
G ^= (p[i] + 1);
else // if pile size is even
// We XOR pile size-1
G ^= (p[i] - 1);
}
return G;
}
//Driver code
public static void main (String[] args)
{
// Game with 3 piles
int n = 3;
// pile with different sizes
int p[] = { 32, 49, 58 };
// Function to return result of game
int res = solve(p, n);
if (res == 0) // if G is zero
System.out.print("Player 2 wins");
else // if G is non zero
System.out.print("Player 1 wins");
}
}
// This code is contributed by Anant Agarwal.
Python3
# Python3 program for the
# variation in nim game
# Function to return final
# grundy Number(G) of game
def solve(p, n):
G = 0
for i in range(n):
# if pile size is odd
if (p[i] % 2 != 0):
# We XOR pile size+1
G ^= (p[i] + 1)
# if pile size is even
else:
# We XOR pile size-1
G ^= (p[i] - 1)
return G
# Driver code
# Game with 3 piles
n = 3
# pile with different sizes
p = [32, 49, 58]
# Function to return result of game
res = solve(p, n)
if (res == 0): # if G is zero
print("Player 2 wins")
else: # if G is non zero
print("Player 1 wins")
# This code is contributed by Anant Agarwal.
C#
// C# program for the variation
// in nim game
using System;
class GFG {
// Function to return final
// grundy Number(G) of game
static int solve(int[] p, int n)
{
int G = 0;
for (int i = 0; i < n; i++) {
// if pile size is odd
if (p[i] % 2 != 0)
// We XOR pile size+1
G ^= (p[i] + 1);
else // if pile size is even
// We XOR pile size-1
G ^= (p[i] - 1);
}
return G;
}
// Driver code
public static void Main()
{
// Game with 3 piles
int n = 3;
// pile with different sizes
int[] p = { 32, 49, 58 };
// Function to return result of game
int res = solve(p, n);
if (res == 0) // if G is zero
Console.WriteLine("Player 2 wins");
else // if G is non zero
Console.WriteLine("Player 1 wins");
}
}
// This code is contributed by vt_m.
PHP
<?php
// php program for the variation
// in nim game
// Function to return final
// grundy Number(G) of game
function solve($p,$n)
{
$G = 0;
for ($i = 0; $i < $n; $i++)
{
// if pile size is odd
if ($p[$i] & 1)
// We XOR pile size+1
$G ^= ($p[$i] + 1);
else // if pile size is even
// We XOR pile size-1
$G ^= ($p[$i] - 1);
}
return $G;
}
// Driver Code
// Game with 3 piles
$n = 3;
// pile with different sizes
$p= array( 32, 49, 58 );
// Function to return result of game
$res = solve($p, $n);
if ($res == 0) // if G is zero
echo "Player 2 wins";
else // if G is non zero
echo "Player 1 wins";
// This code is contributed by mits
?>
JavaScript
<script>
// Javascript program for the variation
// in nim game
// Function to return final
// grundy Number(G) of game
function solve(p, n)
{
let G = 0;
for(let i = 0; i < n; i++)
{
// If pile size is odd
if (p[i] % 2 != 0)
// We XOR pile size+1
G ^= (p[i] + 1);
// If pile size is even
else
// We XOR pile size-1
G ^= (p[i] - 1);
}
return G;
}
// Driver code
// Game with 3 piles
let n = 3;
// Pile with different sizes
let p = [ 32, 49, 58 ];
// Function to return result of game
let res = solve(p, n);
// If G is zero
if (res == 0)
document.write("Player 2 wins");
// If G is non zero
else
document.write("Player 1 wins");
// This code is contributed by sanjoy_62
</script>
Output:
Player 1 wins
Time Complexity: O(n)
Space Complexity: O(n)
Similar Reads
Find the winner in nim-game You are given an array A[] of n-elements. There are two players Alice and Bob. A Player can choose any of element from array and remove it. If the bitwise XOR of all remaining elements equals 0 after removal of selected element, then that player loses. This problem is variation of nim-game. Note: Ea
7 min read
A modified game of Nim Given an array arr[] of integers, two players A and B are playing a game where A can remove any number of non-zero elements from the array that are multiples of 3. Similarly, B can remove multiples of 5. The player who can't remove any element loses the game. The task is to find the winner of the ga
7 min read
Random Number Memory Game in C In this article, will design a simple number memory game in the C programming language. It is a simple memory number game where a random number is displayed and is hidden after some time. The task is to guess that displayed number to continue the game. How to Play This Game: Press 1 on your keyboard
2 min read
Minimum Players required to win the game Given N questions and K options for each question, where 1\leq N \leq 1000000000 and 1\leq K \leq 1000000000 . The task is to determine the sum of total number of player who has attempted ith question for all 1 \leq i \leq N to win the game anyhow. You have to minimize the sum of a total number of p
6 min read
Game of stones Given an integer N which is the number of stones in a pile and the game of stones is being played between you and your friend, the task is to find out whether you'll win or not. A player (on his/her turn) can remove 1 2 or 3 stones, the game continues in alternating turns. The one who is not able to
4 min read
Game of Matchsticks Two friends, A and B, are playing the game of matchsticks. In this game, a group of N matchsticks is placed on the table. The players can pick any number of matchsticks from 1 to 4 (both inclusive) during their chance. The player who takes the last match stick wins the game. If A starts first, how m
6 min read