Repeating Letters

A typical question asked in "History of JavaScript" classes where the teacher mistakenly believes they are teaching programming.

Question:

Write a JavaScript function that takes a sentence as an argument and determines which word in that sentence has the greatest number of repeated letters (the repeated letters do not have to be consecutive). If the sentence has multiple words with the same max of repeated letters, return them all in an Array.

To make comparing the answers easierr I'll use the same names for the two functions in both alternatives. With the modern example I'll give two versions of one function as the exact requirements from the question are a little ambiguous regarding how the repeats are to be counted.

``````function repLetters(elements) {
var bins = {};
for (var i = 0; i < elements.length; i++) {
bins[elements[i]] = (bins[elements[i]] || 0) + 1;
}
var max = 0;
for (var c in bins) {
max = Math.max(max, bins[c]);
}
return max;
}
function mostRepeats(string) {
var maxRepChars = 0, wordsWithMaxRepChars = [];
var words = string.split(/\s/);
for (var w = 0; w < words.length; w++) {
var word = words[w];
var numRepChars = repLetters(word);
if (maxRepChars < numRepChars) {
maxRepChars = numRepChars;
wordsWithMaxRepChars = [word];
} else if (maxRepChars == numRepChars) {
wordsWithMaxRepChars.push(word);
}
}
return wordsWithMaxRepChars;
}``````

With this one the code isn't all that old but does predate 2009 when all the new methods were added to arrays. This version uses object properties to count the repetitions of each letter in the word and then a loop with lots of if statements to work out which words have a letter repeated the most times.

The ambiguity in the question is whether we looking for words with the maximum occurrences of a single letter (whatever letter that may be) or whether we looking at all the letters that occur more than once in the word? For example "success" has three "s" and two "c" in it - are we only interested in the "s" because it occurs the most times in the word or are we interested in all the repeating characters? The above code assumes the first alternative. The code in the first function would need a rewrite if it were the second we wanted.

``````var repLetters = function(s) {
s = s.split('').sort().join('');
return s.length - s.replace(/(.)\1+/g,'\$1').length;
};
var mostRepeats = function(s) {
var n,v;
s = s.split(/\s/);
n = s.map(function(n) {return repLetters(n);});
v = Math.max.apply(null,n);
return s.filter(function(a,b) {return (n[b]===v);});
};``````

This much shorter code doesn't do the same thing as the above code because here I assumed that all repetitions in a word and not just the most common letter are to be counted. We can easily use a regular expression to get rid of all the duplicated letters and then the amount the length is reduced by is the number of repeated letters. I think this is actually a far more reasonable interpretation of the question (although much harder to achieve with the historical approach).

The second function maps these to an array with the numbers in this array corresponding to the word in the corresponding position in the original sentence (which we converted to an array of words in both versions of the code). We then find the maximum number of repeated letters in a word using Math.max (but without the unnecessary loop in the older code). Finally we replace all of those if statements in the loop with a single call to filter which filters out just the words with the maximum number of repetitions.

To duplicate the historic code for if it did turn out that only the letter repeated the most times in a word was meant then we can still do that with a regular expression and have shorter code that still doesn't need a loop. The second function doesn't need to be changed.

``````var repLetter = function(s) {
var max = 0;
s = s.split('').sort().join('');
s.replace(/(.)\1+/g,function(a){
if (max < a.length) {max = a.length;}});
return max;
};``````

Whatever the exact requirements of the original question, no loop and at most one if statement are needed to get the answer using modern JavaScript.