s_tyagi
s_tyagi

Reputation: 43

Check if two strings are rotationally equal to each other

I need your help with the following: I'm trying to develop a function that is supposed to check whether two argument strings are rotationally equal to each other. Like, 'abcd' would become 'cdab' if we rotate that clockwise twice, so my function is supposed to return 'true' if the above strings are supplied as arguments. My initial idea to solve this was to check whether the constant shift between each character in both strings exists, so I tried

function areRotEq (str1, str2) {
    var shift = null;
    for(char of str1){
        if(!shift) shift = str2.indexOf(char);
        else if (shift != str2.indexOf(char)) return false
    }
    return true;
}

But, it fails to evaluate even the above simple strings properly and returns 'false'. If you could point me to the right direction to figure out why my code is not working or maybe suggest some more effective method to solve my problem that would be much appreciated. Thank you in advance!

Upvotes: 4

Views: 2151

Answers (8)

H S W
H S W

Reputation: 7129

This function will check if two strings are rotationally equal to each other and if two strings are rotationally equal then it will return number of elememts require to rotate to make them equal.

const areRotEq= (first, second) => {
  let result = -1;
  const lengthUnmatch = first.length != second.length
  if (lengthUnmatch)
    return result
  else
   const temp = second.concat(second)
    if (temp.includes(first))
        return temp.indexOf(first) 
    else
        return result 
 }

This function will check if two strings are rotationally equal to each other and if two strings are rotationally equal then it will return true and if not then it will return false.

const areRotEq= (first, second) => {
  let result = false;
  const lengthUnmatch = first.length != second.length
  if (lengthUnmatch)
    return result
  else
   const temp = second.concat(second)
    if (temp.includes(first))
        return true 
    else
        return result 
 }

Upvotes: 0

Hamidreza Soltani
Hamidreza Soltani

Reputation: 624

If two strings are a rotation of each other, one string exists in the other string which is repeated twice continuous! Implementing of this logic is vary easy:

function rotEq(str1, str2) {
  var str = str1 + str1;
  return str.includes(str2);
}

console.log(rotEq("abcd", "bcda"));
console.log(rotEq("abcde", "cdeab"));
console.log(rotEq("abcd", "acdb"));

Upvotes: 1

user3297291
user3297291

Reputation: 23372

Here's an alternative approach:

First, do the "quick" checks that are absolutely true or false.

Then, check for the first char of str1 in str2. Split it at this point and paste the first part behind the last. If the two are equal, they are rotational.

warning: this won’t work for strings that contain the same character multiple times.

function areRotEq (str1, str2) {
    if (str1 === str2) return true;
    if (str1.length !== str2.length) return false;
    
    var start2 = str2.indexOf(str1[0]);
    if (start2 === -1) return false;

    return str1 === str2.slice(start2) + str2.slice(0, start2)
}

console.log(
  areRotEq("abcd", "abcd"),
  areRotEq("abcd", "acdb"),
  areRotEq("abcd", "dabc"),
  areRotEq("dcab", "abdc")
);

Upvotes: 4

Alex
Alex

Reputation: 1849

Your solution does not work because you calculate shift incorrectly, here is how you can fix it:

function areRotEq (str1, str2) {
    var shift = null;
    let i = 0;
    for(char of str1){
        if(!shift) shift = str2.indexOf(char);
        else {
            const currentShift = Math.abs(str2.indexOf(char) - i);
            if (shift != currentShift) return false;
        } 
        i++;
    }
    return true;
}

Here is concatenation trick solution:

function areRotEq (str1, str2) {
    if (str1.length != str2.length) return false;
    return (str1 + str1).indexOf(str2) != -1;
}

Upvotes: 1

zhulien
zhulien

Reputation: 5715

You can present the string as a deck structure, namelly a deck of characters(being able to put elements in the beginning and at the end of the collection, just like a deck of cards). Pretty conveniently, the JavaScript array provides this functionality out of the box(through the queue's and stack's methods shift and push. Basically, we take out the first character in the string and move it at the last position and make a new equality check. We repeat this operation until the string get shifted(or rotated) to its initial value:

function areRotEq(str1, str2) {
    if (str1.length !== str2.length) {
        return false;
    }

    if (str1 === str2) {
        return true;
    }

    let str1Array = str1.split('');
    let tempEl;

    for (let i = 0; i < str1.length - 1; i++) {
        tempEl = str1Array.shift();
        str1Array.push(tempEl);

        if (str1Array.join('') === str2) {
            return true;
        }
    }

    return false;
}

Upvotes: 0

Scriptkiddy1337
Scriptkiddy1337

Reputation: 791

i would use findIndex for strings with more then 1 occurs of letters and delete them out

function areRotEq(str1, str2) {
    const str1Array = str1.split('');
    const str2Array = str2.split('');
    for (let i = str1Array.length - 1; i >= 0 ; i--) {
        const index = str2Array.findIndex(letter => letter === str1Array[i]);
        if (index === -1) {
            return false;
        }
        str2Array.splice(index, 1);
    }
    return str2Array.length === 0;
}
console.log(areRotEq('abcda', 'cdaba'));

Upvotes: 0

JasperV
JasperV

Reputation: 321

This is how I solved this problem. I Basically keep shifting str1 until it matches str2, or until I've tried every shift combination.

function areRotEq (str1, str2) {
    for(let i=0; i<str1.length; ++i) {
        // shift str1
        str1 = str1[str1.length-1] + str1.substring(0, str1.length-1);
        if(str1 === str2) {
            return true;
        }
    }
    return false;
}


console.log(
    areRotEq('12345', '34512'), // true
    areRotEq('12345', '23451'), // true
    areRotEq('12345', '12354') // false
);

Upvotes: 2

obscure
obscure

Reputation: 12891

You can use a for-loop and increment the index for the first string from 0 onwards and decrement the second string's index from it's length. With this two indexes you can compare the specific chars inside the string.

function areRotEq(str1, str2) {
  for (var a = 0; a < str1.length; a++) {
    if (str1.charAt(a) != str2.charAt(str2.length - (a + 1))) {
      return false;
    }
  }
  return true;
}
console.log(areRotEq("abcd", "dcba"));

Upvotes: 0

Related Questions