Find out whether string A can be shifted to get string B The task:


  Given two strings A and B, return whether or not A can be shifted some
  number of times to get B.
  
  For example, if A is abcde and B is cdeab, return true. If A is abc
  and B is acb, return false.


Solution 1:

const haveSameLength = (a, b) =&gt; a.length === b.length;
const isSame = (a, b) =&gt; a === b;
const isFullyShifted = a =&gt; a === 0;
const shiftStringBy = i =&gt; a =&gt; `${a.substring(i)}${a.substring(0, i)}`;

const isSameAfterShifting = (strA, strB, items) =&gt; {
  if (strA.length === 0 || strB.length ===0) { return false }
  if (!haveSameLength(strA, strB)) { return false }
  if (isSame(strA, strB)) { return true }
  if (isFullyShifted(items)) { return false }

  return isSameAfterShifting(strA, shiftStringBy(1)(strB), --items)
}

const str1 = 'abcde';
const str2 = 'cdeab';

console.log(isSameAfterShifting(str1, str2, str2.length));


Solution 2

const isSameAfterShifting2 = (strA, strB) =&gt; {
  if (strA.length === 0 || strB.length ===0) { return false }
  if (!haveSameLength(strA, strB)) { return false }
  const arrB = strB.split('');
  const firstLetterA = strA.substring(0, 1);

  let shiftIndex = arrB.indexOf(firstLetterA);
  if (shiftIndex === -1) { return false }
  while (shiftIndex &lt; arrB.length) {
    const strBShifted = `${strB.substring(shiftIndex)}${strB.substring(0, shiftIndex)}`;
    if (strA === strBShifted) { return true }
    shiftIndex++;
  }
  return false;
}

console.log(isSameAfterShifting2('abc', 'acb'));


Which one is more readable and easier to understand for you?
You can check if the String is empty with !str instead of strA.length === 0, 

console.log(''); // false

i think haveSameLength and isSame are extras, you can write srtA.length === strB.length and it would still be readable,

you can get the first letter with a simpler strA[0] instead of strA.substring(0, 1);


  Which one is more readable and easier to understand for you?


a loop is easier to read and understand than a recursive function, 

But the hole approach seems like it can be simpler using a for loop, Array.some() , here's what i would suggest : 

You can generate an array of combinations moving the letters one index at a time,
for a string abc you would have ['abc, bca', 'cba'], see if one of the resulting array entries euqals the second string :



const isSameAfterShifting = (str1, str2) =&gt; {
  // check if the strings are empty or has different lengths
  if (!str1 || !str2 || str1.length !== str2.length) return false;

  // check if the strings are the same
  if (str1 === str2) return true;

  // generate the array 
  let combos = [];
  for (let i = 0; i &lt; str1.length; i++) {
    let c = str1.slice(i) + str1.slice(0, i);
    combos.push(c);
  }

  // for a string 'abc'
  // combos = ['abc', bca', 'cab']

  // check if the array has one of its entries equal to the second string  
  return combos.some(s =&gt; s === str2);
}

console.log( isSameAfterShifting('abc', 'cab') );
console.log( isSameAfterShifting('abc', 'cabaaa') );
console.log( isSameAfterShifting('abc', 'bac') );




you can replace the for loop with Array.from()



const isSameAfterShifting = (str1, str2) =&gt; {
  // check if the strings are empty or has different lengths
  if (!str1 || !str2 || str1.length !== str2.length) return false;

  // check if the strings are the same
  if (str1 === str2) return true;

  // generate the array
  let combos = Array.from({
    length: str1.length
  }, (_, i) =&gt; str1.slice(i) + str1.slice(0, i));

  // for a string 'abc'
  // combos = ['abc', bca', 'cab']

  // check if the array has one of its entries equal to the second string
  return combos.some(s =&gt; s === str2);
};

console.log(isSameAfterShifting("abc", "cab"));
console.log(isSameAfterShifting("abc", "cabaaa"));
console.log(isSameAfterShifting("abc", "bac"));