Search code examples
rubyloopsacronym

Ruby Acronym Creator from string


I'm creating a function that takes a string and creates an acronym but am running into errors. When I input "Complementary metal-oxide semiconductor" I get "CS" in return when expecting "CMOS". Any suggestions why this might happen? I pass it plenty of other strings and it works, just doesn't work in this case.

class Acronym

    def self.abbreviate(phrase)
        letters = phrase.split("")
        acronym = []
        letters.each do |letter|
            previous = letters.index(letter) - 1
            if previous == -1
                acronym.push(letter)
            elsif letters[previous] == " " || letters[previous] == "-"
                acronym.push(letter)
            end
        end
        acronym.join("").upcase
    end

end

Solution

  • The issue with your code is that index() returns the first occurrence of the given letter. So, two problems:

    1. The 'm' in 'metal' is not the first occurrence of 'm' in the string. It appears in the word 'complementary'. Thus, whenever it sees an 'm' in the string, previous will always be 'o' and thus not trigger a push().
    2. Anytime the first letter in your string recurs (regardless of position), it will trigger your first condition. You can see the effect if you change the initial 'C' to 'c' in your test string. The result will be CSCC because there are two 'c's in 'semiconductor'.

    As an alternative, here is an option that uses regex:

    def self.abbreviate(phrase)
      phrase.gsub('-', ' ')
            .scan(/(\A\w|(?<=\s)\w)/)
            .flatten
            .join.upcase
    end
    

    Step by step:

    1. Borrowing the .gsub from @DollarChills to turn the '-' into a space.
    2. scan() returns an array of all matches. The regex matches the first word in the string and any word that is preceded by a space.
    3. The result of the scan is actually an array of arrays, so flatten unnests them.
    4. Combine into a string and upcase