Hashes "most_common_vowel" exercise

I noticed that the solution given to “most_common_vowel” in the hashes exercises doesn’t actually meet the second requirement (“If there’s a tie, return the vowel that occurs earlier in the alphabet.”)

If you run the specs on the solution, it passes, but that’s because the test for that requirement uses the test string “eeiaoa”, and if there’s a tie the given solution returns the vowel that is added to the counts hash last—“a” in this case—not the vowel that occurs first in the alphabet.

There are a lot of ways to solve this. For reference here’s the given solution:

def most_common_vowel(string)
  vowels = %w(a e i o u)
  counts = Hash.new(0) # Give the hash a default value of 0

  string.each_char do |character|
    counts[character] += 1 if vowels.include?(character)
  end

  counts.sort_by {|k, v| v}.last.first
end

And here’s the spec:

  describe "most_common_vowel" do
    it "returns the most common vowel" do
      str = "eieeoaa"
      expect(most_common_vowel(str)).to eq("e")
    end

    it "defaults to alphabetical order in case of tie" do
      str = "eeiaoa"
      expect(most_common_vowel(str)).to eq("a")
    end
  end

Here’s my solution:

def most_common_vowel(string)
  sorted_vowels = string.scan(/[aeiou]/).sort.reverse
  tallies = Hash.new(0)
  
  sorted_vowels.each { |char| tallies[char] += 1 }
  tallies.sort_by { |k, v| v }.last.first
end

And I would suggest replacing the old test string in the spec with “eeiiaaoouu”.

Nice catch! Thanks for the feedback—we’ll make updates to this exercise soon.