Open In App

Determine winner of game by converting two consecutive 1s to 0s

Last Updated : 16 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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:

C++
#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;
}
Java
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
C#
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");
    }
}
Javascript
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");
Python3
# 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.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads