1
\$\begingroup\$

The task:

Given a word W and a string S, find all starting indices in S which are anagrams of W.

For example, given that W is "ab", and S is "abxaba", return 0, 3, and 4.

My solution:

    const anagramOccurrencesOf = (w, s) => {
      const occurrencesCopy = [];
      let sCopy = s.slice(0);
    
      let index = 0;
      while (sCopy.length && index !== -1) {
        index = sCopy.indexOf(w);
        if (index === -1) { break; }
        occurrencesCopy.push((occurrencesCopy[occurrencesCopy.length - 1] + index + 1 || 0));
        sCopy = sCopy.slice(index + 1);
      }
      const occurrencesReverse = [];
      let sReverse = s.split('').reverse().join('');
    
      index = 0;
      while (sReverse.length && index !== -1) {
        index = sReverse.indexOf(w);
        if (index === -1) { break; }
        occurrencesReverse.push( (occurrencesReverse[occurrencesReverse.length - 1] - w.length - index + 1) || s.length - w.length);
        sReverse = sReverse.slice(index + 1);
      }
    
      return [...occurrencesCopy, ...occurrencesReverse].sort((a,b) => a -b);
    };
    
    console.log(anagramOccurrencesOf("ab", "abxaba"));

EDIT: The solution above would find indexes of palindromes. The solution below should find indexes of anagrams:

const sortAlphabetically = x => x.toLowerCase().split('').sort().join('')
const getIndexOfAnagramIn = (s, w) => {
  const wSorted = sortAlphabetically(w);
  const result = []
  for (let i = 0; i < s.length + 1 - w.length; i++) {
    if (sortAlphabetically(s.slice(i, i + w.length)) === wSorted) {
      result.push(i);
    }
  }
  return result;
}

console.log(getIndexOfAnagramIn('abxaba', 'ab'));

\$\endgroup\$
  • \$\begingroup\$ Notice that anagrams are not only reverses. For a word abc there are 6 anagrams. \$\endgroup\$ – vnp Feb 16 '19 at 17:22
  • \$\begingroup\$ Ah, i mistook them with palindromes \$\endgroup\$ – thadeuszlay Feb 16 '19 at 18:50
  • \$\begingroup\$ Shouldn’t the example indices be: 0, 1, 3, 4, 5? \$\endgroup\$ – morbusg Feb 17 '19 at 12:11
  • \$\begingroup\$ Not from what I understood. Why do you think so? @morbusg \$\endgroup\$ – thadeuszlay Feb 17 '19 at 13:23
  • \$\begingroup\$ @thadeuszlay: well, the 4th index confuses me in the example as it is ba, but the 1st index would also be when backwards. \$\endgroup\$ – morbusg Feb 17 '19 at 14:09
2
\$\begingroup\$

This code looks pretty good. I don't see much I would change. This code makes good use of const and let where appropriate.

The only thing that stands out is that splitting a string into an array can be done with the spread syntax instead of calling split().

The first instance:

let sReverse = s.split('').reverse().join('');

Could be changed to

let sReverse = [...s].reverse().join('');

And the other instance:

const sortAlphabetically = x => x.toLowerCase().split('').sort().join('')

Could be changed to:

const sortAlphabetically = x => [...x.toLowerCase()].sort().join('')
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.