1
\$\begingroup\$

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) => a.length === b.length;
const isSame = (a, b) => a === b;
const isFullyShifted = a => a === 0;
const shiftStringBy = i => a => `${a.substring(i)}${a.substring(0, i)}`;
const isSameAfterShifting = (strA, strB, items) => {
 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) => {
 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 < 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?

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Feb 12, 2019 at 13:19
\$\endgroup\$
2
  • \$\begingroup\$ I think this needs only a one liner const isShifted = (a, b) => a.length === b.length && a === b || (a + a).includes(b); \$\endgroup\$ Commented Feb 12, 2019 at 21:15
  • \$\begingroup\$ This is quite genius. Lol \$\endgroup\$ Commented Feb 14, 2019 at 17:55

1 Answer 1

1
\$\begingroup\$

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) => {
 // 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 < 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 => 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) => {
 // 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) => 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 => s === str2);
};
console.log(isSameAfterShifting("abc", "cab"));
console.log(isSameAfterShifting("abc", "cabaaa"));
console.log(isSameAfterShifting("abc", "bac"));

answered Feb 12, 2019 at 15:05
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.