Given strings s1 and s2 consisting of ‘A’, ‘B’ and ‘#’, where:
- ‘#’ represents an empty cell
- ‘A’ represents robots that can move in the left direction and
- ‘B’ represents robots that can move in the right direction
The task is to check if s1 can be converted to s2 by movement of the robots.
Examples:
Input: s1 = “#B#A#”, s2 = “##BA#”
Output: Yes
Explanation: In one step ‘B’ moves one position to the right.
So the string becomes “##BA#” which is same as the final s2 stringInput: s1 = “#B#A#”, s2 = “#A#B#”
Output: No
Explanation: As the robots cannot cross each other.
Approach: The idea to solve the problem is based on the following observation:
The robots can reach the final position when the strings satisfy the condition:
- If the empty spaces ‘#’ are removed from string then both the strings should be identical as no crossing of A and B are allowed.
- After removing the ‘#’ from both the strings, if positions of A is lesser in s2 than in s1 and positions of ‘B’ is greater in s2 than in s1.
Follow the steps mentioned below to implement the above observation:
- Iterate the array from the start:
- Remove the empty spaces (‘#’) from both the strings.
- Store the position of A and B in both the strings
- If the modified strings s1 and s2 are exactly the same then they can reach the final state when:
- Position of ‘A’ in s1 is greater than or equal to the position of ‘A’ in s2 and the position of ‘B’ in s1 is less than or equal to the position of ‘B’ in s2.
- In all other cases, the robots cannot reach the final positions mentioned in s2.
Below is the implementation for the above approach.
C++
// C++ code for the above approach: #include <bits/stdc++.h> using namespace std; // Function to check if robots can move string moveRobots(string s1, string s2) { // Strings to save s1 and s2 without '#' string a, b; for ( int i = 0; i < s1.size(); i++) if (s1[i] != '#' ) a += s1[i]; for ( int i = 0; i < s2.size(); i++) if (s2[i] != '#' ) b += s2[i]; // Condition 1: strings s1 and s2 // without empty spaces should be // exactly same if (a == b) { int n = a.size(); // v1 and v2 will store the // positions of 'A' or 'B' // in s1 and s2 respectively vector< int > v1; vector< int > v2; for ( int i = 0; i < s1.size(); i++) { if (s1[i] != '#' ) v1.push_back(i); } for ( int i = 0; i < s2.size(); i++) if (s2[i] != '#' ) v2.push_back(i); // Condition 2: // Position of 'A' in s1 should be // greater than or equal to // Position of 'A' in s2 and // Position of 'B' in s1 should be // less than or equal to // Position of 'B' in s2 if (a[0] == 'A' and v1[0] < v2[0]) return "No" ; if (a[0] == 'B' and v1[0] > v2[0]) return "No" ; for ( int i = 1; i < n; i++) { if (a[i] == 'A' ) { if (v1[i] < v2[i]) return "No" ; } else { if (v1[i] > v2[i]) return "No" ; } } return "Yes" ; } return "No" ; } // Driver code int main() { string s1 = "#B#A#" ; string s2 = "##BA#" ; cout << moveRobots(s1, s2) << endl; return 0; } |
Java
// Java code for the above approach: import java.util.*; class GFG { // Function to check if robots can move static String moveRobots(String s1, String s2) { // Strings to save s1 and s2 without '#' String a = "" , b = "" ; for ( int i = 0 ; i < s1.length(); i++) if (s1.charAt(i) != '#' ) a += s1.charAt(i); for ( int i = 0 ; i < s2.length(); i++) if (s2.charAt(i) != '#' ) b += s2.charAt(i); // Condition 1: strings s1 and s2 // without empty spaces should be // exactly same if (a.equals(b)) { int n = a.length(); // v1 and v2 will store the // positions of 'A' or 'B' // in s1 and s2 respectively ArrayList<Integer> v1 = new ArrayList<Integer>(); ArrayList<Integer> v2 = new ArrayList<Integer>(); for ( int i = 0 ; i < s1.length(); i++) { if (s1.charAt(i) != '#' ) v1.add(i); } for ( int i = 0 ; i < s2.length(); i++) if (s2.charAt(i) != '#' ) v2.add(i); // Condition 2: // Position of 'A' in s1 should be // greater than or equal to // Position of 'A' in s2 and // Position of 'B' in s1 should be // less than or equal to // Position of 'B' in s2 if (a.charAt( 0 ) == 'A' && ( int )v1.get( 0 ) < ( int )v2.get( 0 )) return "No" ; if (a.charAt( 0 ) == 'B' && ( int )v1.get( 0 ) > ( int )v2.get( 0 )) return "No" ; for ( int i = 1 ; i < n; i++) { if (a.charAt(i) == 'A' ) { if (( int )v1.get(i) < ( int )v2.get(i)) return "No" ; } else { if (( int )v1.get(i) > ( int )v2.get(i)) return "No" ; } } return "Yes" ; } return "No" ; } // Driver code public static void main(String[] args) { String s1 = "#B#A#" ; String s2 = "##BA#" ; System.out.println(moveRobots(s1, s2)); } } // This code is contributed by ukasp. |
Python3
# python3 code for the above approach: # Function to check if robots can move def moveRobots(s1, s2): # Strings to save s1 and s2 without '#' a, b = " ", " " for i in range ( 0 , len (s1)): if (s1[i] ! = '#' ): a + = s1[i] for i in range ( 0 , len (s2)): if (s2[i] ! = '#' ): b + = s2[i] # Condition 1: strings s1 and s2 # without empty spaces should be # exactly same if (a = = b): n = len (a) # v1 and v2 will store the # positions of 'A' or 'B' # in s1 and s2 respectively v1 = [] v2 = [] for i in range ( 0 , len (s1)): if (s1[i] ! = '#' ): v1.append(i) for i in range ( 0 , len (s2)): if (s2[i] ! = '#' ): v2.append(i) # Condition 2: # Position of 'A' in s1 should be # greater than or equal to # Position of 'A' in s2 and # Position of 'B' in s1 should be # less than or equal to # Position of 'B' in s2 if (a[ 0 ] = = 'A' and v1[ 0 ] < v2[ 0 ]): return "No" if (a[ 0 ] = = 'B' and v1[ 0 ] > v2[ 0 ]): return "No" for i in range ( 1 , n): if (a[i] = = 'A' ): if (v1[i] < v2[i]): return "No" else : if (v1[i] > v2[i]): return "No" return "Yes" return "No" # Driver code if __name__ = = "__main__" : s1 = "#B#A#" s2 = "##BA#" print (moveRobots(s1, s2)) # This code is contributed by rakeshsahni |
C#
// C# code for the above approach: using System; using System.Collections; class GFG { // Function to check if robots can move static string moveRobots( string s1, string s2) { // Strings to save s1 and s2 without '#' string a = "" , b = "" ; for ( int i = 0; i < s1.Length; i++) if (s1[i] != '#' ) a += s1[i]; for ( int i = 0; i < s2.Length; i++) if (s2[i] != '#' ) b += s2[i]; // Condition 1: strings s1 and s2 // without empty spaces should be // exactly same if (a == b) { int n = a.Length; // v1 and v2 will store the // positions of 'A' or 'B' // in s1 and s2 respectively ArrayList v1 = new ArrayList(); ArrayList v2 = new ArrayList(); for ( int i = 0; i < s1.Length; i++) { if (s1[i] != '#' ) v1.Add(i); } for ( int i = 0; i < s2.Length; i++) if (s2[i] != '#' ) v2.Add(i); // Condition 2: // Position of 'A' in s1 should be // greater than or equal to // Position of 'A' in s2 and // Position of 'B' in s1 should be // less than or equal to // Position of 'B' in s2 if (a[0] == 'A' && ( int )v1[0] < ( int )v2[0]) return "No" ; if (a[0] == 'B' && ( int )v1[0] > ( int )v2[0]) return "No" ; for ( int i = 1; i < n; i++) { if (a[i] == 'A' ) { if (( int )v1[i] < ( int )v2[i]) return "No" ; } else { if (( int )v1[i] > ( int )v2[i]) return "No" ; } } return "Yes" ; } return "No" ; } // Driver code public static void Main() { string s1 = "#B#A#" ; string s2 = "##BA#" ; Console.Write(moveRobots(s1, s2)); } } // This code is contributed by Samim Hossain Mondal. |
Javascript
<script> // JavaScript code for the above approach: // Function to check if robots can move const moveRobots = (s1, s2) => { // Strings to save s1 and s2 without '#' let a, b; for (let i = 0; i < s1.length; i++) if (s1[i] != '#' ) a += s1[i]; for (let i = 0; i < s2.length; i++) if (s2[i] != '#' ) b += s2[i]; // Condition 1: strings s1 and s2 // without empty spaces should be // exactly same if (a == b) { let n = a.length; // v1 and v2 will store the // positions of 'A' or 'B' // in s1 and s2 respectively let v1 = []; let v2 = []; for (let i = 0; i < s1.length; i++) { if (s1[i] != '#' ) v1.push(i); } for (let i = 0; i < s2.length; i++) if (s2[i] != '#' ) v2.push(i); // Condition 2: // Position of 'A' in s1 should be // greater than or equal to // Position of 'A' in s2 and // Position of 'B' in s1 should be // less than or equal to // Position of 'B' in s2 if (a[0] == 'A' && v1[0] < v2[0]) return "No" ; if (a[0] == 'B' && v1[0] > v2[0]) return "No" ; for (let i = 1; i < n; i++) { if (a[i] == 'A' ) { if (v1[i] < v2[i]) return "No" ; } else { if (v1[i] > v2[i]) return "No" ; } } return "Yes" ; } return "No" ; } // Driver code let s1 = "#B#A#" ; let s2 = "##BA#" ; document.write(moveRobots(s1, s2)); // This code is contributed by rakeshsahni </script> |
Yes
Time Complexity: O(N)
Auxiliary Space: O(N)
Method 2 :- Optimized Solution
Approach: The idea to solve the problem is based on the following observation:
Step 1 :- Take a pointer (say i) at the first string and another pointer (say j) for the second string.
Step 2 :- Increment the pointer of the both the string until you found any of the BOTS.
Step 2 , CASE 1 :- If the BOTS pointed by the respective pointers are not same then in that case the answer is NO.
Reason :- Let us consider two string namely S1 = ##A##B# and S2 = ##B##A#
In order to achieve the state represented by S2 , It is sure that during this transition the BOTS have crossed each other then only it can achieve the state. But according to question BOTS should not cross each other and hence the answer will be NO.
Hence if S1[i] == ‘A’ and S2[j] == ‘B’ , then in this case return NO.
Step 2, CASE 2 :- If the two BOTS pointed by the two pointers are same and Let’s say A is the bot that is encountered then it should be in the following case :-
Reason :- Let us consider two string namely S1 = ##A##B# and S2 = ###A#B#
We can see that in order to achieve the state represented by the S2 A has to move right BUT According to question A can only move left so we can’t achieve this state.
Hence if S1[i] == ‘A’ and S2[j] == ‘A’ and i<j , then in this case return NO.
Step 2, CASE 3 :- If the two BOTS pointed by the two pointers are same and Let’s say B is the bot that is encountered then it should be in the following case :-
Reason :- Let us consider two string namely S1 = ##A##B# and S2 = ##AB###
We can see that in order to achieve the state represented by the S2 B has to move left BUT According to question B can only move right so we can’t achieve this state.
Hence if S1[i] == ‘B’ and S2[j] == ‘B’ and i>j , then in this case return NO.
For the other cases it is possible to achieve the state represented by S2.
Below is the implementation of the above approach :-
C++
// cpp program to check if we can transit from state // represented by S1 to state represented by State S2 #include <bits/stdc++.h> using namespace std; void moveRobots(string s1, string s2) { int i = 0, j = 0, n = s1.size(); while (i < n && j < n) { if (s1[i] == '#' ) i++; else if (s2[j] == '#' ) j++; // Step 2 CASE 1 else if (s1[i] != s2[j]) cout << "No" ; // Step 2 CASE 2 else if (s1[i] == 'A' && i < j) cout << "No" ; // Step 2 CASE 3 else if (s1[i] == 'B' && i > j) cout << "No" ; else { i++; j++; } } cout << "Yes" ; } int main() { string s1 = "#B#A#" , s2 = "##BA#" ; moveRobots(s1, s2); return 0; } // This code is contributed by Aditya Kumar (adityakumar129) |
C
// c program to check if we can transit from state // represented by S1 to state represented by State S2 #include <stdio.h> #include <string.h> void moveRobots( char s1[], char s2[]) { int i = 0, j = 0, n = strlen (s1); while (i < n && j < n) { if (s1[i] == '#' ) i++; else if (s2[j] == '#' ) j++; // Step 2 CASE 1 else if (s1[i] != s2[j]) printf ( "No" ); // Step 2 CASE 2 else if (s1[i] == 'A' && i < j) printf ( "No" ); // Step 2 CASE 3 else if (s1[i] == 'B' && i > j) printf ( "No" ); else { i++; j++; } } printf ( "Yes" ); } int main() { char s1[] = "#B#A#" ; char s2[] = "##BA#" ; moveRobots(s1, s2); return 0; } // This code is contributed by Aditya Kumar (adityakumar129) |
Java
// java program to check if we can transit from state // represented by S1 to state represented by State S2 import java.io.*; import java.util.*; class BOTS { public static void moveRobots(String s1, String s2) { int i = 0 , j = 0 ; int n = s1.length(); while (i < n && j < n) { if (s1.charAt(i) == '#' ) i++; else if (s2.charAt(j) == '#' ) j++; // Step 2 CASE 1 else if (s1.charAt(i) != s2.charAt(j)) System.out.println( "No" ); // Step 2 CASE 2 else if (s1.charAt(i) == 'A' && i < j) System.out.println( "No" ); // Step 2 CASE 3 else if (s1.charAt(i) == 'B' && i > j) System.out.println( "No" ); else { i++; j++; } } System.out.println( "Yes" ); } } class GFG { public static void main(String args[]) { String s1 = "#B#A#" ; String s2 = "##BA#" ; BOTS obj = new BOTS(); obj.moveRobots(s1, s2); } } // This code is contributed by Aditya Kumar (adityakumar129) |
Python
# Python program to check if we can transit from state # represented by S1 to state represented by State S2 def moveRobots(s1, s2) : i = 0 j = 0 n = len (s1) while i < n and j < n : if s1[i] = = '#' : i + = 1 elif s2[j] = = '#' : j + = 1 # Step 2 CASE 1 elif s1[i] ! = s2[j] : print ( "No" ) # Step 2 CASE 2 elif s1[i] = = 'A' and i < j : print ( "No" ) # Step 2 CASE 3 elif s1[i] = = 'B' and i > j : print ( "No" ) else : i + = 1 j + = 1 print ( "Yes" ) # Driver Code if __name__ = = '__main__' : s1 = "#B#A#" s2 = "##BA#" moveRobots(s1, s2) # This code has been contributed by Sachin Sahara (sachin801) |
Javascript
<script> // Javascript program to check if we can transit from state // represented by S1 to state represented by State S2 const moveRobots = (s1, s2) => { let i=0, j=0, n=s1.length; while (i<n && j<n){ if (s1[i]== '#' ) i++; else if (s2[j]== '#' ) j++; // Step 2 CASE 1 else if (s1[i] != s2[j]) document.write( "No" ); // Step 2 CASE 2 else if (s1[i] == 'A' && i < j) document.write( "No" ); // Step 2 CASE 3 else if (s1[i] == 'B' && i > j) document.write( "No" ); else { i++; j++; } } document.write( "Yes" ); } // Driver code let s1 = "#B#A#" ; let s2 = "##BA#" ; moveRobots(s1, s2); // This code is contributed by adityapatil12 </script> |
C#
// C# program to implement above approach using System; using System.Collections; using System.Collections.Generic; class GFG { // Driver code public static void Main( string [] args){ String s1 = "#B#A#" ; String s2 = "##BA#" ; BOTS obj = new BOTS(); obj.moveRobots(s1, s2); } } public class BOTS { public void moveRobots(String s1, String s2) { int i = 0, j = 0; int n = s1.Length; while (i < n && j < n) { if (s1[i] == '#' ) i++; else if (s2[j] == '#' ) j++; // Step 2 CASE 1 else if (s1[i] != s2[j]) Console.WriteLine( "No" ); // Step 2 CASE 2 else if (s1[i] == 'A' && i < j) Console.WriteLine( "No" ); // Step 2 CASE 3 else if (s1[i] == 'B' && i > j) Console.WriteLine( "No" ); else { i++; j++; } } Console.WriteLine( "Yes" ); } } |
Yes
Time Complexity: O(N)
Auxiliary Space: O(1)