4

I am trying to transform a string by removing a letter A with an adjacent letter B or by removing a letter C toghether with an adjacent letter D.

For example 1, given a string "CBACD", it should be transformed as

CBACD -> CCD -> C

Example 2: given a string "CABABD", it should return nothing as the transformation goes like below:

CABABD -> CABD -> CD -> 

Example 3: "ACBDACBD", There are no corresponding adjacent characters to A & C so the entire string should be returned

"ACBDACBD" -> "ACBDACBD"

I have written the following code to do the operation:

object RemoveCharsABCD {

    val s = scala.io.StdIn
    def adjacent(s: String): String = {
        val charSet = ArrayBuffer("AB","BA","CD","DC")
        var i   = 0
        var ret:String = ""
        while(i < s.length-1) {
            if(charSet.contains(s"${s.charAt(i)}${s.charAt(i+1)}")) {
                s.slice(i+2, s.length)
                i += 2
                if(i == s.length-1) ret = s"$ret${s.charAt(i).toString}"
            } else {
                    ret = s"$ret${s.charAt(i).toString}"
                    i += 1
                    if(i == s.length-1) ret = s"$ret${s.charAt(i).toString}"
            }
        }
        println("Ret: " + ret)
        ret
    }

    def main(args: Array[String]): Unit = {
        println("Enter a String: ")
        var s = scala.io.StdIn.readLine().toString
        adjacent(s)
    }
}

The above code works fine for the first iteration which is: CABABD -> CABD For the inputs: ACBDACBD, CBACD, the output is correct but for ACBDACBD, the output is CD. I called the method adjacent before the print statement as below:

if(ret.length >= 2) {
    adjacent(ret)
}
println("Ret: " + ret)

But this goes to infinite loop and give stackoverflow exception. I am unable to call the method: adjacent recursively so that it can work until the end of the string ? Could anyone let me know how can I properly call the method: adjacent recursively so that the entire string is processed until the end ?

5
  • You have s.slice(i+2, s.length), shouldn't you assign the result of that to a variable? Commented Nov 27, 2019 at 7:11
  • If I assign it to 'ret', the output is 'DD' for 'CABABD' Commented Nov 27, 2019 at 7:24
  • 2
    I'm just saying that line by itself does nothing, so you either need to remove it or make use of the result Commented Nov 27, 2019 at 7:26
  • Actually I have tried to use it in the first 'IF' of the while loop as: i += 2 solution(s.slice(i, s.length)) But I still see the same output for CABABD -> CD Commented Nov 27, 2019 at 9:52
  • Also @jwvh answer is good but I want to try my attempt first and as a last resort I will use the answer. Commented Nov 27, 2019 at 9:54

6 Answers 6

8

Seems pretty straight forward.

@annotation.tailrec 
def adjacent(s: String): String = {
  val next = s.replaceAll("AB|BA|CD|DC", "")
  if (s == next) s else adjacent(next)
}

adjacent("CBACD")     //res0: String = C
adjacent("CABABD")    //res1: String =
adjacent("ACBDACBD")  //res2: String = ACBDACBD
Sign up to request clarification or add additional context in comments.

1 Comment

can you provide same answer in python
2

This could be done in Java, as follows :

public static String remove(String str)
{
    if (str == null) {
        return null;
    }

    char[] chars = str.toCharArray();
    int i = 0, k = 0;

    while (i < str.length())
    {
        if (    chars[i] == 'B' && (k > 0 && chars[k - 1] == 'A') ||
                chars[i] == 'A' && (k > 0 && chars[k - 1] == 'B') ||
                chars[i] == 'C' && (k > 0 && chars[k - 1] == 'D') || 
                chars[i] == 'D' && (k > 0 && chars[k - 1] == 'C'))
        {
            --k;
            ++i;
        }   
        else {
            chars[k++] = chars[i++];
        }
    }

    return new String(chars).substring(0, k);
}

Comments

0
private static String stringAfterRemove(String str,int val,int lengthOfString) {
    
    String nStr = str.replaceAll("CD", "").replaceAll("DC", "").replaceAll("AB", "").replaceAll("BA", "");
    if(val==lengthOfString)
        return str;
    return stringAfterRemove(nStr,++val,lengthOfString);
}

In main method, initialize int val =0.

1 Comment

You can probably loop length/2 times, since we remove two chars at a time.
0
public static String solution(String str) {
    String next = str.replaceAll("AB|CD|DC|BA", "");
    if(str.equals(next))
        return str;
    else
        return solution(next);
}

1 Comment

I don't understand what's wrong with this solution ? Why are people downvoting it ?
0

Here's a version in Kotlin:

fun solution(input: String): String {
   val result = input.replace("AB|CD|DC|BA".toRegex(), "")
   return if (result == input)
      input
    else
      solution(result)
}
    
solution("CBACD")     //output = C
solution("CABABD")    //output =
solution("ACBDACBD")  //output = ACBDACBD

Comments

0

Python solution using stack:

def solution(S):
    stack = []
    for i, val in enumerate(S):
        if stack and ((stack[-1] == "A" and val == "B") or (stack[-1] == "B" and val == "A") or
        (stack[-1] == "C" and val == "D") or (stack[-1] == "D" and val == "C")):
            stack.pop()
        else:
            stack.append(val)        
    return "".join(stack)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.