1

I'm trying to write a function that takes in two string parameters and check if the second parameter is a rotated version of the first string.

So the following would be the results:

checkRotationStrings('waterbottle', 'lewaterbott'); // true checkRotationStrings('waterbottle', 'bottlewater'); // true checkRotationStrings('waterbottle', 'erbottlewat'); // true checkRotationStrings('waterbottle', 'lewaterbottx'); // false

I wrote the following code, but there are some edge cases that I can't seem to figure out:

function checkRotationStrings(string, rotatedString) {
  let result;
  let rotationCheck
  let stringArr = string.split('');
  let rotatedStringArr = rotatedString.split('')

  for (let i = 0; i < string.length - 1; i++) {
    if (rotatedString[0] === stringArr[i]) {
       result = stringArr.slice(i);
       rotationCheck = stringArr.slice(0, i).concat(result).join('');
    }
  }
  console.log(rotationCheck)
  if (rotationCheck === string){
    return true;
  } else {
    return false;
  }
}

Any help would be appreciated.

גלעד ברקן
  • 23,602
  • 3
  • 25
  • 61
  • 4
    Which edge cases? – chevybow Apr 25 '18 at 19:42
  • 1
    For example, I'm breaking the strings where the first letter in the rotatedString is found in the original string. Let's say it's `waterbottle` and `ttlewaterb`. The letter `t` will be found in index `2` first instead of index `7` which is where I want to slice. –  Apr 25 '18 at 19:43
  • 1
    `checkRotationStrings('waterbottle', 'erbottllewat'); // true` should be `false` – Nina Scholz Apr 25 '18 at 19:48
  • @NinaScholz Thanks for the correction, edited the post. –  Apr 25 '18 at 19:52
  • 2
    I would recommend avoiding using `string` as a variable name, as it is *very* close to the [`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) object. – Herohtar Apr 25 '18 at 19:53
  • 2
    Here you have it https://stackoverflow.com/questions/2553522/interview-question-check-if-one-string-is-a-rotation-of-other-string – algrid Apr 25 '18 at 21:52

7 Answers7

5

You could use String#repeat with rotated and two as parameter and check with String#includes.

function checkRotationStrings(string, rotated) {
    return string.length === rotated.length && rotated.repeat(2).includes(string);
}

console.log(checkRotationStrings('waterbottle', 'lewaterbott'));  //  true
console.log(checkRotationStrings('waterbottle', 'bottlewater'));  //  true
console.log(checkRotationStrings('waterbottle', 'erbottllewat')); // false
console.log(checkRotationStrings('waterbottle', 'lewaterbottx')); // false
console.log(checkRotationStrings('waterbottle', 'ttlewaterb'));   // false
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

This is a somewhat strange solution, as it uses some only for the index parameter. But each iteration in some simply compares two strings, one which is a rotation of the first, and the other is the second one.

const checkRotationStrings = (str, rot) => 
    str.split('').some((s, i) => str.slice(i) + str.slice(0, i) == rot);

[
  ['waterbottle', 'lewaterbott'],   // true 
  ['waterbottle', 'bottlewater'],   // true 
  ['waterbottle', 'erbottllewat'],  // false  -- ORIGINAL
  ['waterbottle', 'erbottlewat'],   // true   -- CORRECTED
  ['waterbottle', 'lewaterbottx']   // false
].forEach(([s, r]) => console.log(`'${s}', '${r}': ${checkRotationStrings(s, r)}`))
Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
  • 1
    And this reminds me how much I hate the name `some`. It really should be `any`. And I have no idea *why* I feel strongly about this! – Scott Sauyet Apr 25 '18 at 20:00
2

You could use substring and rotate until you find a match. Like this:

function checkRotationStrings(string, rotatedString) {

  let match = false;
  for (let i = 0;
    (i < string.length - 1) & !match; i++) {

    match = rotatedString.substring(i, rotatedString.length) + rotatedString.substring(0, i) === string;

  }
  return match

}


console.log(checkRotationStrings('waterbottle', 'lewaterbott')); // true
console.log(checkRotationStrings('waterbottle', 'bottlewater')); // true 
console.log(checkRotationStrings('waterbottle', 'erbottlewat')); // true 
console.log(checkRotationStrings('waterbottle', 'lewaterbottx')); // false
Julien Grégoire
  • 16,864
  • 4
  • 32
  • 57
0

You can do the following:

    checkRotationStrings(str1: string, str2: string) {

    if (str1.length !== str2.length) {

      return false;
    } else {

      for (var i = 0; i < str2.length; i++) {

        if (str2[i] === str1[0]) {

          var substring1 = str2.substring(0,i);
          var substring2 = str2.substring(i,str2.length);
          var concatWord = substring2.concat(substring1);

          if(str1 === concatWord){

            console.log(str1 + " matches " + concatWord)
            return true;

          }else{
            console.log(str1 + " not matches " + concatWord)

          }


        }

      }

      return false;

    }


  }
Rak2018
  • 935
  • 6
  • 16
0

Stack Overflow questions often receive answers in the form of completely new code (and/or ideas) on how to achieve the desired result. Usually, there's at least an attempt to help the questioner with their actual question, which in this case seemed to ask for some help with your code (one issue at least had to do with "slicing," as you commented).

I also love to offer new code or ideas if I particularly like it so I'm only partly critical here, but the answers so far have suffered from a complete lack of relating to the question.

There's nothing wrong with how you have conceived of checking for string rotation. You just have a couple of bugs:

First, since rotationCheck is meant to rotate string in order to compare it with rotatedString, you got the string-building reversed. It should be:

rotationCheck = result.concat(stringArr.slice(0, i)).join('');

Secondly, once you've built the rotation-check, you need to compare it with rotatedString, not string. So:

if (rotationCheck === rotatedString){
גלעד ברקן
  • 23,602
  • 3
  • 25
  • 61
0

I might be late for this, but here is my solution and it include all edge cases.

function checkRotation(str1,str2){
  const char0 = str1[0];
  let ind = str2.indexOf(char0);
  while(ind>-1){
    const start = str2.substring(0,ind);
    const end = str2.substring(ind,str2.length);
    if(end+start === str1){
      return true;
    }
    ind = str2.indexOf(char0,ind+1)
  }
  return false
}
console.log(checkRotation("assads","adsass"))
-1

Instead of trying to break it in random pieces and do different checks, you could instead do a count of the letters. This would be much simpler:

const countLetters = a => Array.prototype.reduce.call(a, (r, l) => Object.assign(r, { [l]: (r[l] || 0) + 1 }), {});

function checkRotatedString(a, b) {
  const countA = countLetters(a);
  const countB = countLetters(b);
  
  return Object.keys(countA).length === Object.keys(countB).length 
    && Object.entries(countA).every(([key, value]) => value === countB[key]);
}

// Tests
[['waterbottle', 'lewaterbott'], ['waterbottle', 'bottlewater'], ['waterbottle', 'erbottlewat'], ['waterbottle', 'lewaterbottx']]
  .forEach(a => console.log(a, checkRotatedString.apply(null, a)));
samanime
  • 25,408
  • 15
  • 90
  • 139