Problem: Swap Adjacent in LR String

In a string composed of `'L'`, `'R'`, and `'X'` characters, like
`"RXXLRXRXL"`, a move consists of either replacing one occurrence of `"XL"`
with `"LX"`, or replacing one occurrence of `"RX"` with `"XR"`. Given the
starting string `start` and the ending string `end`, return `True` if and only
if there exists a sequence of moves to transform one string to the other.


Python solution:
import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def canTransform(self, start: str, end: str) -> bool:
    if start.replace('X', '') != end.replace('X', ''):
      return False

    i = 0
    j = 0

    while i < len(start) and j < len(end):
      while i < len(start) and start[i] == 'X':
        i += 1
      while j < len(end) and end[j] == 'X':
        j += 1
      if i == len(start) and j == len(end):
        return True
      if i == len(start) or j == len(end):
        return False
      if start[i] == 'L' and i < j:
        return False
      if start[i] == 'R' and i > j:
        return False
      i += 1
      j += 1

    return True


Java solution:
class Solution {
  public boolean canTransform(String start, String end) {
    if (!start.replace("X", "").equals(end.replace("X", "")))
      return false;

    int i = 0; // start's index
    int j = 0; // end's index

    while (i < start.length() && j < end.length()) {
      while (i < start.length() && start.charAt(i) == 'X')
        ++i;
      while (j < end.length() && end.charAt(j) == 'X')
        ++j;
      if (i == start.length() && j == end.length())
        return true;
      if (i == start.length() || j == end.length())
        return false;
      // L can only move to left.
      if (start.charAt(i) == 'L' && i < j)
        return false;
      // R can only move to right.
      if (start.charAt(i) == 'R' && i > j)
        return false;
      ++i;
      ++j;
    }

    return true;
  }
}


C++ solution:
class Solution {
 public:
  bool canTransform(string start, string end) {
    if (removeX(start) != removeX(end))
      return false;

    int i = 0;  // start's index
    int j = 0;  // end's index

    while (i < start.length() && j < end.length()) {
      while (i < start.length() && start[i] == 'X')
        ++i;
      while (j < end.length() && end[j] == 'X')
        ++j;
      if (i == start.length() && j == end.length())
        return true;
      if (i == start.length() || j == end.length())
        return false;
      // L can only move to left.
      if (start[i] == 'L' && i < j)
        return false;
      // R can only move to right.
      if (start[i] == 'R' && i > j)
        return false;
      ++i;
      ++j;
    }

    return true;
  }

 private:
  string removeX(const string& s) {
    string t = s;
    std::erase(t, 'X');
    return t;
  }
};