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\$
9
  • \$\begingroup\$ Notice that anagrams are not only reverses. For a word abc there are 6 anagrams. \$\endgroup\$
    – vnp
    Commented Feb 16, 2019 at 17:22
  • \$\begingroup\$ Ah, i mistook them with palindromes \$\endgroup\$ Commented Feb 16, 2019 at 18:50
  • \$\begingroup\$ Shouldn’t the example indices be: 0, 1, 3, 4, 5? \$\endgroup\$
    – morbusg
    Commented Feb 17, 2019 at 12:11
  • \$\begingroup\$ Not from what I understood. Why do you think so? @morbusg \$\endgroup\$ Commented Feb 17, 2019 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
    Commented Feb 17, 2019 at 14:09

1 Answer 1

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('')
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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