Stateless Maximum Beauty of String implementation
How can I remove the state in the reducer for mapLettersByCount?


Return a new object on each iteration. Not optimal, but we're talking functional anyways. You can use object destructuring to do a shallow copy of the object. A more verbose version would be Object.assign. Then use computed keys to assign a dynamic key.

function mapLettersByCount(sentence) {
  return sentence.split(EMPTY_STRING)
                 .filter(letter =&gt; LETTERS_ONLY.test(letter))
                 .map(letter =&gt; [letter.toUpperCase(), 1])
                 .reduce((letterCount, [key, count]) =&gt; ({
                   ...letterCount,
                   [key]: (letterCount[key] || 0) + count
                 }), {});
}



  How can one use generators without assigning it to a variable? (see points variable in the maxBeauty function) Is this even considered state in this situation?


I believe that it is stateful since one call to points.next() does not return the same result as the next call. But I may be wrong.

One way you could do this is compute the points by subtracting the reducer's index from a constant 26. I believe it won't violate the rules of functional programming because


this 26 is a constant value
it's technically a closure scenario, similar to your other constants and
index is provided as an argument to the callback.


And it would look like this:

const POINTS = 26;

export function maxBeauty(sentence = "") {
  return Object.values(mapLettersByCount(sentence))
               .sort()
               .reverse()
               .reduce((score, count, index) =&gt; score + count * (POINTS - index), 0);
}