Determine winner of game by converting two consecutive 1s to 0s
Given a binary string S of length N. Two players āAā and āBā are playing a game and at each alternate turn, the player converts two consecutive 1s to 0s. The game ends when no player can make a move, and the other player is declared the winner. The task is to determine the winner of the game.
Example:
Input: s = ā1111ā
Output: A
Explanation: Player āAā can guarantee a win by converting the middle ā11ā to become ā1001ā.Input: s = ā+ā
Output: B
Approach:
Iterating through the string and trying all possible moves. For each ā11ā convert it to ā00ā and store this move using bit masking, in this case if we are changing (i -1)th and (i)th bit of 1 to 0 then we set bit into out mask at this position. This mask will help us to not make same move again. Then recursively call to check if the second player can win from the resulting state. If the second player cannot win, it means the first player can guarantee a win by making this move.
Steps-by-step approach:
- Create a recursive function findWinnerHelper() to checks if the first player can win by exploring different moves.
- Memoization (dp map) is used to store results of previously explored states to avoid redundant computations.
- Iterate through the string to find consecutive ā1ās.
- If consecutive ā1ās are found, make a move by converting them to ā0ā.
- Convert the current state to a binary representation and check the next state recursively.
- Undo the move for backtracking to explore other possibilities.
- Memoize the result for the current state to avoid recomputation.
- The findWinner() function initializes the memoization map and calls the helper function findWinnerHelper() with the initial state.
- The result is printed based on whether āAā or āBā wins.
Below is the implementation of the above approach:
#include <bits/stdc++.h>
using namespace std;
// Recursive helper function to check if the first player can win the game
bool findWinnerHelper(string s, long convertState, unordered_map<long, bool>& dp) {
// Check if the result for the current state is already memoized
if (dp.find(convertState) != dp.end()) {
return dp[convertState];
}
// Iterate through the string to find consecutive '1's
for (int i = 1; i < s.length(); i++) {
if (s[i] == '1' && s[i - 1] == '1') {
// Flip the signs for a potential winning move
s[i] = '0';
s[i - 1] = '0';
// Convert the current state to a binary representation
long nextState = convertState | (1 << i);
nextState = nextState | (1 << (i - 1));
// Recursively check if the next player can win after the move
if (!findWinnerHelper(s, nextState, dp)) {
// If the next player cannot win, memoize and return true
dp[convertState] = true;
s[i] = '1';
s[i - 1] = '1';
return true;
}
// Undo the move for backtracking
s[i] = '1';
s[i - 1] = '1';
}
}
// Memoize the result if no winning move is found
dp[convertState] = false;
return false;
}
// Main function to check if the first player can win
bool findWinner(string s) {
unordered_map<long, bool> dp;
return findWinnerHelper(s, 0, dp);
}
int main() {
// Example test case
string s = "110100000000000000000000";
bool result = findWinner(s);
// Output the result
cout << (result ? "A Wins" : "B Wins") << endl;
return 0;
}
import java.util.HashMap;
import java.util.Map;
public class GameWinner {
// Recursive helper function to check if the first player can win the game
static boolean findWinnerHelper(String s, long convertState, Map<Long, Boolean> dp) {
// Check if the result for the current state is already memoized
if (dp.containsKey(convertState)) {
return dp.get(convertState);
}
// Iterate through the string to find consecutive '1's
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) == '1' && s.charAt(i - 1) == '1') {
// Flip the signs for a potential winning move
char[] chars = s.toCharArray();
chars[i] = '0';
chars[i - 1] = '0';
s = new String(chars);
// Convert the current state to a binary representation
long nextState = convertState | (1L << i);
nextState = nextState | (1L << (i - 1));
// Recursively check if the next player can win after the move
if (!findWinnerHelper(s, nextState, dp)) {
// If the next player cannot win, memoize and return true
dp.put(convertState, true);
chars[i] = '1';
chars[i - 1] = '1';
s = new String(chars);
return true;
}
// Undo the move for backtracking
chars[i] = '1';
chars[i - 1] = '1';
s = new String(chars);
}
}
// Memoize the result if no winning move is found
dp.put(convertState, false);
return false;
}
// Main function to check if the first player can win
static boolean findWinner(String s) {
Map<Long, Boolean> dp = new HashMap<>();
return findWinnerHelper(s, 0, dp);
}
public static void main(String[] args) {
// Example test case
String s = "1111";
boolean result = findWinner(s);
// Output the result
System.out.println(result ? "A Wins" : "B Wins");
}
}
// This code is contributed by akshitaguprzj3
using System;
using System.Collections.Generic;
public class GameWinner {
// Recursive helper function to check if the first player can win the game
static bool FindWinnerHelper(string s, long convertState, Dictionary<long, bool> dp) {
// Check if the result for the current state is already memoized
if (dp.ContainsKey(convertState)) {
return dp[convertState];
}
// Iterate through the string to find consecutive '1's
for (int i = 1; i < s.Length; i++) {
if (s[i] == '1' && s[i - 1] == '1') {
// Flip the signs for a potential winning move
char[] chars = s.ToCharArray();
chars[i] = '0';
chars[i - 1] = '0';
s = new string(chars);
// Convert the current state to a binary representation
long nextState = convertState | (1L << i);
nextState = nextState | (1L << (i - 1));
// Recursively check if the next player can win after the move
if (!FindWinnerHelper(s, nextState, dp)) {
// If the next player cannot win, memoize and return true
dp[convertState] = true;
chars[i] = '1';
chars[i - 1] = '1';
s = new string(chars);
return true;
}
// Undo the move for backtracking
chars[i] = '1';
chars[i - 1] = '1';
s = new string(chars);
}
}
// Memoize the result if no winning move is found
dp[convertState] = false;
return false;
}
// Main function to check if the first player can win
static bool FindWinner(string s) {
Dictionary<long, bool> dp = new Dictionary<long, bool>();
return FindWinnerHelper(s, 0, dp);
}
public static void Main(string[] args) {
// Example test case
string s = "1111";
bool result = FindWinner(s);
// Output the result
Console.WriteLine(result ? "A Wins" : "B Wins");
}
}
function findWinnerHelper(s, convertState, dp) {
// Check if the result for current state is already memoized
if (dp.has(convertState)) {
return dp.get(convertState);
}
// Iterate through the string to the find consecutive '1's
for (let i = 1; i < s.length; i++) {
if (s[i] === '1' && s[i - 1] === '1') {
let chars = s.split('');
chars[i] = '0';
chars[i - 1] = '0';
s = chars.join('');
// Convert the current state to binary representation
let nextState = convertState | (1 << i);
nextState = nextState | (1 << (i - 1));
if (!GFG(s, nextState, dp)) {
// If the next player cannot win, memoize and return true
dp.set(convertState, true);
chars[i] = '1';
chars[i - 1] = '1';
s = chars.join('');
return true;
}
// Undo the move for backtracking
chars[i] = '1';
chars[i - 1] = '1';
s = chars.join('');
}
}
// Memoize the result if no winning move is found
dp.set(convertState, false);
return false;
}
// Main function to check if the first player can win
function findWinner(s) {
const dp = new Map();
return findWinnerHelper(s, 0, dp);
}
// Example test case
const s = "11010101010101010011101010101010";
const result = findWinner(s);
console.log(result ? "A Wins" : "B Wins");
# Python program for the above approach
# Recursive helper function to check if the first player can win the game
def find_winner_helper(s, convert_state, dp):
# Check if the result for the current state is already memoized
if convert_state in dp:
return dp[convert_state]
# Iterate through the string to find consecutive '1's
for i in range(1, len(s)):
if s[i] == '1' and s[i - 1] == '1':
# Flip the signs for a potential winning move
s = s[:i] + '0' + s[i + 1:]
s = s[:i - 1] + '0' + s[i:]
# Convert the current state to a binary representation
next_state = convert_state | (1 << i)
next_state = next_state | (1 << (i - 1))
# Recursively check if the next player can win after the move
if not find_winner_helper(s, next_state, dp):
# If the next player cannot win, memoize and return True
dp[convert_state] = True
s = s[:i] + '1' + s[i + 1:]
s = s[:i - 1] + '1' + s[i:]
return True
# Undo the move for backtracking
s = s[:i] + '1' + s[i + 1:]
s = s[:i - 1] + '1' + s[i:]
# Memoize the result if no winning move is found
dp[convert_state] = False
return False
# Main function to check if the first player can win
def find_winner(s):
dp = {}
return find_winner_helper(s, 0, dp)
# Example test case
s = "1111"
result = find_winner(s)
# Output the result
print("A Wins" if result else "B Wins")
# This code is contributed by Susobhan Akhuli
Output
A Wins
Time Complexity: O(n), where n is the length of the input string.
Auxiliary Space: O(n), where n is the length of the input string.