# Predict the winner of the game | Sprague-Grundy

Given a 4×4 binary matrix. Two players A and B are playing a game, at each step a player can select any rectangle with all 1’s in it and replace all 1’s with 0. The player that cannot select any rectangle loses the game. Predict the winner off the game assuming that they both play the game optimally and A starts the game.

**Examples:**

Input :

0 1 1 0

0 0 0 0

0 0 0 0

0 0 0 1

Output :A

Step 1: Player A chooses the rectangle with a single one at position (1, 2), so the new matrix becomes

0 0 1 0

0 0 0 0

0 0 0 0

0 0 0 1Step 2: Player B chooses the rectangle with a single one at position (1, 3), so the new matrix becomes

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 1Step 3: Player A chooses the rectangle with a single one at position (4, 4), so the new matrix becomes

0 0 0 0

0 0 0 0

0 0 0 0

0 0 0 0Step 4: Player B cannot move, hence A wins the game.

Input :

0 0 1 0

0 0 0 0

0 0 0 0

0 0 0 1

Output :B

**Approach: **The problem can be solved using sprague-grundy theorem. The base case for Sprague-Grundy is Grundy[0] = 0, which is all the positions in the matrix are filled with 0, then B wins it, hence 0. In grundy, recursively we call grundy function with all the states that are possible.

The 4×4 matrix can be represented as a binary 16 bit number which is 65535 in int, where every bit represents the position in a matrix. Below are the steps to solve the above problem.

- Convert the matrix into int val.
- Call the recursive function with val that generates the grundy value using memoization.
- Inside the recursive function, all the grundy states can be visited by generating all possible rectangles(using four for loops).
- Check the generated rectangle, if it is a rectangle of the matrix. Then this is a state to be visited by grundy.
- To get Grundy value using MEX, please see this.
- If the recursion return 0, then player B wins, else player A wins.

Below is the implementation of the above approach

`#include <bits/stdc++.h> ` `using` `namespace` `std; ` ` ` `// Gets the max value ` `int` `getMex(` `const` `unordered_set<` `int` `>& s) ` `{ ` ` ` `int` `mex = 0; ` ` ` `while` `(s.find(mex) != s.end()) ` ` ` `mex++; ` ` ` `return` `mex; ` `} ` ` ` `// Find check if the rectangle is a part of the ` `// the original rectangle ` `int` `checkOne(` `int` `mat, ` `int` `i, ` `int` `j, ` `int` `k, ` `int` `l) ` `{ ` ` ` ` ` `// initially create the bitset ` ` ` `// of original intValue ` ` ` `bitset<16> m(mat); ` ` ` ` ` `// Check if it is a part of the rectangle ` ` ` `for` `(` `int` `x = i; x <= j; x++) { ` ` ` `for` `(` `int` `y = k; y <= l; y++) { ` ` ` `int` `pos = 15 - ((x * 4) + y); ` ` ` ` ` `// If not set, then not part ` ` ` `if` `(!m.test(pos)) { ` ` ` `return` `-1; ` ` ` `} ` ` ` `m.reset(pos); ` ` ` `} ` ` ` `} ` ` ` ` ` `// If part of rectangle ` ` ` `// then convert to int again and return ` ` ` `int` `res = m.to_ullong(); ` ` ` `return` `res; ` `} ` ` ` `// Recursive function to get the grundy value ` `int` `getGrundy(` `int` `pos, ` `int` `grundy[]) ` `{ ` ` ` ` ` `// If state has been visited ` ` ` `if` `(grundy[pos] != -1) ` ` ` `return` `grundy[pos]; ` ` ` ` ` `// For obtaining the MEX value ` ` ` `unordered_set<` `int` `> gSet; ` ` ` ` ` `// Generate all the possible rectangles ` ` ` `for` `(` `int` `i = 0; i <= 3; i++) { ` ` ` `for` `(` `int` `j = i; j <= 3; j++) { ` ` ` `for` `(` `int` `k = 0; k <= 3; k++) { ` ` ` `for` `(` `int` `l = k; l <= 3; l++) { ` ` ` ` ` `// check if it is part of the original ` ` ` `// rectangle, if yes then get the int value ` ` ` `int` `res = checkOne(pos, i, j, k, l); ` ` ` ` ` `// If it is a part of original matrix ` ` ` `if` `(res != -1) { ` ` ` ` ` `// Store the grundy value ` ` ` `// Memorize ` ` ` `grundy[res] = getGrundy(res, grundy); ` ` ` ` ` `// Find MEX ` ` ` `gSet.insert(grundy[res]); ` ` ` `} ` ` ` `} ` ` ` `} ` ` ` `} ` ` ` `} ` ` ` ` ` `// Return the MEX ` ` ` `return` `getMex(gSet); ` `} ` ` ` `// Conver the matrix to INT ` `int` `toInt(` `int` `matrix[4][4]) ` `{ ` ` ` `int` `h = 0; ` ` ` ` ` `// Traverse in the matrix ` ` ` `for` `(` `int` `i = 0; i < 4; ++i) ` ` ` `for` `(` `int` `j = 0; j < 4; ++j) ` ` ` `h = 2 * h + matrix[i][j]; ` ` ` `return` `h; ` `} ` ` ` `// Driver Code ` `int` `main() ` `{ ` ` ` `int` `mat[4][4] = { { 0, 1, 1, 0 }, ` ` ` `{ 0, 0, 0, 0 }, ` ` ` `{ 0, 0, 0, 0 }, ` ` ` `{ 0, 0, 0, 1 } }; ` ` ` ` ` `// Get the int value of the matrix ` ` ` `int` `intValue = toInt(mat); ` ` ` ` ` `int` `grundy[intValue + 1]; ` ` ` ` ` `// Initially with -1 ` ` ` `// used for memoization ` ` ` `memset` `(grundy, -1, ` `sizeof` `grundy); ` ` ` ` ` `// Base case ` ` ` `grundy[0] = 0; ` ` ` ` ` `// If returned value is non-zero ` ` ` `if` `(getGrundy(intValue, grundy)) ` ` ` `cout << ` `"Player A wins"` `; ` ` ` `else` ` ` `cout << ` `"Player B wins"` `; ` ` ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

**Output:**

Player A wins

**Time Complexity:** O(N)

**Auxiliary Space:** O(N)

## Recommended Posts:

- Predict the winner in Coin Game
- Predict the winner of the game on the basis of absolute difference of sum by selecting numbers
- Find the winner in nim-game
- Find the winner of the game with N piles of boxes
- Coin game winner where every player has three choices
- Game Theory (Normal-form game) | Set 3 (Game with Mixed Strategy)
- Game Theory (Normal - form game) | Set 1 (Introduction)
- Combinatorial Game Theory | Set 2 (Game of Nim)
- Maximum games played by winner
- Find the winner by adding Pairwise difference of elements in the array until Possible
- Variation in Nim Game
- A modified game of Nim
- Implementation of Tic-Tac-Toe game
- Check if the game is valid or not
- Optimal Strategy for a Game | DP-31

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.