Find Winner by emptying the Array by Sum Modulo Array element
Last Updated :
06 Jan, 2024
Given an array Arr[] of size N, two players A and B are playing a game on this array by taking turns and A makes the first move. On each move, they can perform the following operation on the array:
- Choose a number Arr[i]
- add the (Sum of array % Arr[i]) to their score
- then remove that number from the array.
- After removal, the length of the array is reduced by 1.
The game continues until the array becomes empty, and the player with the highest score wins the game. Your task is to determine the winner of the game or determine if the game ends with a draw.
Constraints:
1 <= N <= 20
1 <= Arr[i] <=10^9
Example:
Input: N=3, Arr=[3, 4, 5]
Output: Player B wins
Explanation:
In first move Arr=[3, 4, 5], Player A takes 5 and get score = 12 % 5 = 2
In second move Arr=[3, 4], Player B takes 4 and get score = 7 % 4 = 3
In third move Arr=[3], Player A takes 3 and get score = 3 % 3 = 0
Total score of Player B is greater than that of Player A, so winner = B
Input: N=5, Arr=[3, 1, 2, 4, 5]
Output: Player A wins
Explanation:
In the first move, Arr[] = [3, 1, 2, 4, 5], A takes 4 and gets score = 15 % 4 = 3
In the second move, Arr[] = [3, 1, 2, 5], B takes 3 and get score = 11 % 3 = 2
In the third move, Arr[] = [1, 2, 5], A takes 5 and gets score = 8 % 5 = 3
In the fourth move, Arr[] = [1, 2], B takes 2 and gets score = 3 % 2 = 1
In the fifth move, Arr[] = [1], A takes 1 and gets score = 1 % 1 = 0
Total score of Player A is higher than that of Player B, so winner = A
Input: N=4, Arr=[1, 1, 2, 2]
Output: Draw
Explanation: After the game ends both the players will have a final score of 0.
Approach: The problem can be solved using the following approach:
The problem can be solved using Dynamic Programming and Bit Manipulation. We can create bitmasks for all possible distributions of array element where if the ith bit is set, it indicates that the ith array element has already been used. When the mask has even number of set bits, it means Player A has to make a move while if the mask has odd number of set bits, then Player B makes a move.
Each player tries to maximize the score, Let the current bitmask has X set bits, then following condition is followed for this bitmask to be a winning, loosing, or draw state:
- Bitmask(X set bits) is Winning: If (Maximum score of bitmask with X set bits – Maximum score of bitmasks with X+1 set bits) is positive.
- Bitmask(X set bits) is Loosing: If (Maximum score of bitmask with X set bits – Maximum score of bitmasks with X+1 set bits) is negative.
- Bitmask(X set bits) is Draw: If (Maximum score of bitmask with X set bits – Maximum score of bitmasks with X+1 set bits) is 0.
Conclusion: The final result depends upon the maximum cumulative difference at bitmask = 0 where Player A makes the first move:
- If maximum cumulative difference of bitmask (0) > 0: Player A wins
- If maximum cumulative difference of bitmask (0) < 0: Player B wins
- If maximum cumulative difference of bitmask (0) = 0: Draw
Let us understand this using an example where Arr[] = {3, 4, 5}, the below image shows all the possible bitmask states for player A and B
Since the answer depends upon the final maximum cumulative difference for bitmask 0 based upon above mentioned formula i.e. maximum value of Xth bit – maximum value of (X+1)th bit. All possible values for bitmask 0 are listed below:
- 2 – (max(3, 1) – (max(0, 0))) = -1
- 0 – (max(3, 2) – (max(0, 0)))= -3
- 0 – (max(4, 1) – (max(0, 0))) = -4
Maximum cumulative sum for bitmask(0) = max(-1, -3, -4) = -1, which is negative, so Player B wins the game.
Steps to solve the problem:
- Define a function, say winnerOfGame(mask) which takes the current mask as input and returns the maximum sum possible with the current mask.
- Iterate over all the unset bits and for every bit which is 0, change it to 1 to get the new mask and call the recursive function winnerOfGame(new mask) with the new mask.
- After iterating over all the possible new masks, return the maximum sum possible.
- Return the result as winnerOfGame(mask), with initial mask as 0.
Below is the implementation of above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int winnerOfGame( int mask, int sum, vector< int >& arr,
map< int , int >& dp)
{
if (dp.count(mask))
return dp[mask];
if (__builtin_popcount(mask) == arr.size())
return 0;
int result = -1e9;
int n = arr.size();
for ( int i = 0; i < n; i++) {
if (((mask >> i) & 1) == 0) {
int new_mask = (mask | (1 << i));
result = max(result,
sum % arr[i]
- winnerOfGame(new_mask,
sum - arr[i],
arr, dp));
}
}
return dp[mask] = result;
}
int main()
{
vector< int > Arr = { 3, 4, 5 };
int sum = accumulate(Arr.begin(), Arr.end(), 0);
map< int , int > dp;
int result = winnerOfGame(0, sum, Arr, dp);
if (result == 0) {
cout << "Draw";
}
else if (result > 0) {
cout << "Player A wins";
}
else {
cout << "Player B wins";
}
cout << endl;
}
|
Java
import java.util.*;
class Main {
static int winnerOfGame( int mask, int sum,
ArrayList<Integer> arr,
HashMap<Integer, Integer> dp)
{
if (dp.containsKey(mask))
return dp.get(mask);
if (Integer.bitCount(mask) == arr.size())
return 0 ;
int result = Integer.MIN_VALUE;
int n = arr.size();
for ( int i = 0 ; i < n; i++) {
if (((mask >> i) & 1 ) == 0 ) {
int newMask = (mask | ( 1 << i));
result = Math.max(
result,
sum % arr.get(i)
- winnerOfGame(newMask,
sum - arr.get(i),
arr, dp));
}
}
dp.put(mask, result);
return result;
}
public static void main(String[] args)
{
ArrayList<Integer> arr
= new ArrayList<>(Arrays.asList( 3 , 4 , 5 ));
int sum = arr.stream()
.mapToInt(Integer::intValue)
.sum();
HashMap<Integer, Integer> dp = new HashMap<>();
int result = winnerOfGame( 0 , sum, arr, dp);
if (result == 0 ) {
System.out.println( "Draw" );
}
else if (result > 0 ) {
System.out.println( "Player A wins" );
}
else {
System.out.println( "Player B wins" );
}
}
}
|
Python3
def winner_of_game(mask, sum_val, arr, dp):
if mask in dp:
return dp[mask]
if bin (mask).count( '1' ) = = len (arr):
return 0
result = - 1e9
n = len (arr)
for i in range (n):
if ((mask >> i) & 1 ) = = 0 :
new_mask = mask | ( 1 << i)
result = max (result, sum_val % arr[i] - winner_of_game(new_mask, sum_val - arr[i], arr, dp))
dp[mask] = result
return result
if __name__ = = "__main__" :
Arr = [ 3 , 4 , 5 ]
sum_val = sum (Arr)
dp = {}
result = winner_of_game( 0 , sum_val, Arr, dp)
if result = = 0 :
print ( "Draw" )
elif result > 0 :
print ( "Player A wins" )
else :
print ( "Player B wins" )
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static int WinnerOfGame( int mask, int sum, List< int > arr, Dictionary< int , int > dp)
{
if (dp.ContainsKey(mask))
return dp[mask];
if (BitCount(mask) == arr.Count)
return 0;
int result = int .MinValue;
int n = arr.Count;
for ( int i = 0; i < n; i++)
{
if (((mask >> i) & 1) == 0)
{
int newMask = (mask | (1 << i));
result = Math.Max(result,
sum % arr[i]
- WinnerOfGame(newMask, sum - arr[i], arr, dp));
}
}
return dp[mask] = result;
}
static int BitCount( int n)
{
int count = 0;
while (n > 0)
{
count += n & 1;
n >>= 1;
}
return count;
}
static void Main()
{
List< int > arr = new List< int > { 3, 4, 5 };
int sum = arr.Sum();
Dictionary< int , int > dp = new Dictionary< int , int >();
int result = WinnerOfGame(0, sum, arr, dp);
if (result == 0)
{
Console.WriteLine( "Draw" );
}
else if (result > 0)
{
Console.WriteLine( "Player A wins" );
}
else
{
Console.WriteLine( "Player B wins" );
}
}
}
|
Javascript
function GFG(mask, sum, arr, dp) {
if (dp.has(mask)) {
return dp.get(mask);
}
if (countBits(mask) === arr.length) {
return 0;
}
let result = -1e9;
const n = arr.length;
for (let i = 0; i < n; i++) {
if (((mask >> i) & 1) === 0) {
const newMask = mask | (1 << i);
result = Math.max(result, sum % arr[i] - GFG(newMask, sum - arr[i], arr, dp));
}
}
dp.set(mask, result);
return result;
}
function countBits(num) {
let count = 0;
while (num) {
count += num & 1;
num >>= 1;
}
return count;
}
function main() {
const arr = [3, 4, 5];
const sum = arr.reduce((acc, curr) => acc + curr, 0);
const dp = new Map();
const result = GFG(0, sum, arr, dp);
if (result === 0) {
console.log( "Draw" );
} else if (result > 0) {
console.log( "Player A wins" );
} else {
console.log( "Player B wins" );
}
}
main();
|
Time complexity: O(N*(2^N)), where N is the size of the input array Arr[]
Auxiliary Space: O(2^N)
Share your thoughts in the comments
Please Login to comment...