0

Few days ago I got a problem which goes like this:

We have two strings A and B with the same super set of characters. We need to change these strings to obtain two equal strings. In each move we can perform one of the following operations:

1- swap two consecutive characters of a string 2- swap the first and the last characters of a string

A move can be performed on either string. What is the minimum number of moves that we need in order to obtain two equal strings? Input Format and Constraints: The first and the second line of the input contains two strings A and B. It is guaranteed that the superset their characters are equal. 1 <= length(A) = length(B) <= 2000 All the input characters are between 'a' and 'z'

Output Format: Print the minimum number of moves to the only line of the output

Sample input: aab baa

Sample output: 1

Explanation: Swap the first and last character of the string aab to convert it to baa. The two strings are now equal.

I have been trying different algorithms but without success. I always have been done something which makes them equal but never with minimum movement.

Edit: My pseudo code is:

swap=>moves++

begin

 if(A[0]!=B[0]){
  if(A[0]==B[length-1]){
   swap(B[0], B[length-1]);
  }
  else if(B[0]==A[length-1]){
   swap(A[0],A[length-1]);
  }
 }
for(int i=0;i<A.length();i++){
 if(A[i]==B[i]){
  continue;
 }
 for(int j=i+1;j<A.length();j++){
  if(A[i]==B[j]){
   for(int k=j;k>i;k--){
    swap(B[k],B[k-1]);
   }
 break;
  else if(B[i]=A[j]){
   for(int k=j;k>i;k--){
    swap(A[k],A[k-1]);
   }
 break;
 }
}if(A==B){
break;
}

For some which is not clear about this, my question is how to make it work, any idea, anything. Because at the moment, I'm pretty clueless.

EDIT: So here is the best idea I did so far:

    public static void swap(char aChar, char bChar) {
        char cChar;
        cChar = aChar;
        aChar = bChar;
        bChar = cChar;
    }

    public static void main(String[] args) {
        int moves = 0;
        Scanner scanner = new Scanner(System.in);
        System.out.println("Enter the string A:");
        while (!scanner.hasNext("[A-Za-z]+")) {
            System.out
                    .println("Nope, that's not it! Enter the value from \"a\" to \"z\"."
                            + "Enter your string A again!");
            scanner.nextLine();
        }
        String a = scanner.nextLine();
        a.toLowerCase();
        System.out.println("Enter the string B:");
        while (!scanner.hasNext("[A-Za-z]+")) {
            System.out
                    .println("Nope, that's not it! Enter the value from \"a\" to \"z\"."
                            + "Enter your string B again!");
            scanner.nextLine();
        }
        String b = scanner.nextLine();
        b.toLowerCase();
        scanner.close();
        char[] aChar = a.toCharArray();
        char[] bChar = b.toCharArray();
        if ((a.length() >= 1 && a.length() <= 2000) && a.length() == b.length()) {
            if (aChar[0] != bChar[0]) {
                if (aChar[0] == bChar[bChar.length - 1]) {
                    swap(bChar[0], bChar[bChar.length - 1]);
                    moves++;
                } else if (bChar[0] == aChar[aChar.length - 1]) {
                    swap(aChar[0], aChar[bChar.length - 1]);
                    moves++;
                }
            }
            for (int i = 0; i < aChar.length; i++) {
                if (aChar[i] == bChar[i]) {
                    continue;
                }
                for (int j = i + 1; j < aChar.length; j++) {
                    if (aChar[i] == bChar[j]) {
                        for (int k = j; k > i; k--) {
                            swap(bChar[k], bChar[k - 1]);
                            moves++;
                        }
                        break;
                    } else if (bChar[i] == aChar[j]) {
                        for (int k = j; k > i; k--) {
                            swap(aChar[k], aChar[k - 1]);
                            moves++;
                        }
                        break;
                    }
                }
                if (aChar == bChar) {
                    break;
                }
            }
            System.out.println("Minimum moves: " + moves);
        }
    }
}

The problem is that it doesn't give the minimum number of movements. Sadly. :)

Will try some more stuff to add into this code and it might work, but for now, this is all I have...

  • What is your question? – JLRishe Sep 19 '14 at 12:49
  • 2
    Show us one of the algorithms you tried and we can help you. This isn't a coding service. – AndersNS Sep 19 '14 at 12:50
  • I think (but am not sure) you can proof by induction that it's sufficient to only operate on one of the two strings, let's say the second. This allows you to think of one of the two strings as fixed. – Giulio Franco Sep 19 '14 at 14:23
  • Also, swapping the first and last character can be seen as swapping two consecutive characters, if the string is considered circular. This further restricts the possible logical set of moves to picking one character of the first string and swapping it with the one immediately following. – Giulio Franco Sep 19 '14 at 14:25
  • Given these two conditions, the problem is reduced to selecting a index in the first string at every operation, and swapping it. Now, it sounds really like a BFS in a tree of moves. http://en.wikipedia.org/wiki/Breadth-first_search – Giulio Franco Sep 19 '14 at 14:28
  • @GiulioFranco Franco thanks for your activity and ideas. But if I fix one string, isn't that making more moves to make them equal. Becouse sometimes is better to make swap in string A and other times in B, depending on how the characters are set in some string. – Dusan Punosevac Sep 19 '14 at 14:52
  • @DusanPunosevac that's why I wrote I am not sure you can proof it. That's a prejudice of mine, which may also be wrong. The thing is I think that every time you make a swap on string A, there is a possible swap on string B that would bring you at the same step-distance. – Giulio Franco Sep 19 '14 at 15:16
  • @GiulioFranco I know Franco. Well I guess there is no other way, then keep trying and trying until I get the right solution. Thank you anyway. – Dusan Punosevac Sep 19 '14 at 15:19
  • 2
    As far as I can see, this is a duplicate of http://stackoverflow.com/questions/7797540/counting-the-swaps-required-to-convert-one-permutation-into-another – Marco13 Sep 19 '14 at 15:51
  • @Marco13 It's very similar, but this one allows the first and last to be transposed, messing up the proof of correctness for the accepted answer. – David Eisenstat Sep 19 '14 at 18:01
  • So practicly noone has any idea how to do this... :D – Dusan Punosevac Sep 21 '14 at 13:49

1 Answers1

0
public int findMinimumStringMovement() {
    int moves = 0;
    char[] aChar = a.toCharArray();
    char[] bChar = b.toCharArray();
    char cChar;

    if (aChar != bChar) {
        for (int i = 0; i < aChar.length; i++) {
            for (int j = i + 1; j < aChar.length; j++) {
                if (aChar[i] != bChar[i]) {
                    /*
                     * It checks if some character from the array of aChar
                     * is same as other character from the array of B and if
                     * it's j less then the length of the array. If it's
                     * true, then swap the characters and count moves
                     */
                    if (aChar[j] == bChar[i] && j < aChar.length) {
                        for (int k = j; k > i; k--) {
                            cChar = aChar[k];
                            aChar[k] = aChar[k - 1];
                            aChar[k - 1] = cChar;
                            moves++;
                        }
                        /*
                         * In other case, if the last character of array
                         * aChar same as the some character of bChar and
                         * vice versa, then we should check if the i is
                         * equal to 0, in that case we swap 1st and last
                         * character of array and count as 1 move else if i
                         * value is less then the value of length of array
                         * divided with 2 then it swaps that character to
                         * the first one and then swaps with last and counts
                         * the moves.
                         */
                    } else if (aChar[aChar.length - 1] == bChar[i]) {
                        if (i == 0) {
                            cChar = aChar[aChar.length - 1];
                            aChar[aChar.length - 1] = aChar[i];
                            aChar[i] = cChar;
                            moves++;
                        } else if (i < (aChar.length - 1) / 2) {
                            for (int k = i; k > 0; k--) {
                                cChar = aChar[k];
                                aChar[k] = aChar[k - 1];
                                aChar[k - 1] = cChar;
                                moves++;
                            }
                            cChar = aChar[i];
                            aChar[i] = aChar[aChar.length - 1];
                            aChar[aChar.length - 1] = cChar;
                        }
                    } else if (bChar[bChar.length - 1] == aChar[i]) {
                        if (i == 0) {
                            cChar = bChar[bChar.length - 1];
                            bChar[bChar.length - 1] = bChar[i];
                            bChar[i] = cChar;
                            moves++;
                        } else if (i < (aChar.length - 1) / 2) {
                            for (int k = i; k > 0; k--) {
                                cChar = aChar[k];
                                aChar[k] = aChar[k - 1];
                                aChar[k - 1] = cChar;
                                moves++;
                            }
                            cChar = aChar[i];
                            aChar[i] = aChar[aChar.length - 1];
                            aChar[aChar.length - 1] = cChar;
                            moves++;
                        }
                        /*
                         * And the last case is if there is no other option,
                         * then we asks if some characters in array with
                         * positions i and j are different and if the j
                         * value is less then length of the array and do the
                         * swap.
                         */
                    } else {
                        if (aChar[j] != aChar[i] && j < aChar.length) {
                            if (aChar[j] == bChar[j]) {
                                cChar = bChar[j];
                                bChar[j] = bChar[i];
                                bChar[i] = cChar;
                                moves++;
                            }
                            cChar = aChar[j];
                            aChar[j] = aChar[i];
                            aChar[i] = cChar;
                            moves++;
                        } else if (bChar[j] != bChar[i] && j < aChar.length) {
                            if (aChar[j] == bChar[j]
                                    && aChar[j] != aChar[i]) {
                                cChar = aChar[j];
                                aChar[j] = aChar[i];
                                aChar[i] = cChar;
                                moves++;
                            }
                            cChar = bChar[j];
                            bChar[j] = bChar[i];
                            bChar[i] = cChar;
                            moves++;
                        }
                    }
                    /*
                     * At the end, if arrays are equal, then it is done.
                     */
                    if (aChar == bChar) {
                        break;
                    }
                }
            }
        }
    }
    return moves;
}

I hope that you'll find it helpfull guys. Sorry for taking so long to get it posted. Best regards.