Iterating over loops in ruby?

Viewed 39

I am new to ruby. I am trying to create a letter counter. my intended output was supposed to be [2,"I"] but I keep getting [3,"D]. Any help in understanding where I went wrong would be so helpful, thank you.

class LetterCounter
      def initialize(text)
        @text = text
      end
    
      def calculate_most_common()
        counter = Hash.new(1)
        most_common = nil
        most_common_count = 1
        @text.chars.each do |char|
          next unless is_letter?(char)
          counter[char] = (counter[char] || 1) + 1
          if counter[char] > most_common_count
            most_common = char
            most_common_count += counter[char]
          end
        end
        return [most_common_count, most_common]
      end
    
      private
    
      def is_letter?(letter)
        return letter =~ /[a-z]/i
      end
    end
    
    counter = LetterCounter.new("Digital Punk")
    p counter.calculate_most_common

# Intended output:
# [2, "i"]
3 Answers

Try:

class LetterCounter
    def initialize(text)
        @text = text
    end
    
    def calculate_most_common()
        arr=@text.scan(/[a-z]/i)
        arr.each_with_object(Hash.new(0)) { |n,h| h[n] += 1 }.max_by(&:last)
    end
    
end
    
counter = LetterCounter.new("Digital Punk")
p counter.calculate_most_common

Prints:

["i", 2]

If you want to fix yours, try:

class LetterCounter
    def initialize(text)
        @text = text
    end
    
    def calculate_most_common()
        counter = Hash.new(0)
        most_common = nil
        most_common_count = 0
        @text.chars.each do |char|
            next unless is_letter?(char)
            counter[char] += 1
            if counter[char]>most_common_count
                most_common=char 
                most_common_count=counter[char]
            end 
        end
        return [most_common_count, most_common]
    end
    
    private
    
    def is_letter?(letter)
        return letter =~ /[a-z]/i
    end
end

counter = LetterCounter.new("Digital Punk")
p counter.calculate_most_common
class LetterCounter
  def initialize(text)
    @text = text
  end

  def calculate_most_common()
    counter = Hash.new(0)  # wrong initialization in your code
    most_common = nil
    most_common_count = 0
    @text.chars.each do |char|
      next unless is_letter?(char)
      counter[char] = (counter[char] || 1) + 1
      puts "#{char} #{counter[char]}"
      if counter[char] > most_common_count
        puts "most common: #{most_common_count} #{char} #{counter[char]}"
        most_common = char
        most_common_count = counter[char] # error in your code
      end
    end
    return [most_common_count, most_common]
  end

  private

  def is_letter?(letter)
    return letter =~ /[a-z]/i
  end
end

counter = LetterCounter.new("Digital Punk")
p counter.calculate_most_common

The initial counters are at 1. These should be 0 since you are incrementing inside your loop anyways.

On the First Iteration - Hash counter[char] is being initialized to 1 ( From Hash.new(1) ), Then counter[char] is increased to 1 on first loop and the most_common_count is also increased by 1. Which leads to D having value 3.

since most_common_count is already at 3 - the loop would no longer go into the if condition - as other characters would reach only 2 ( 1 from Hash.new and 1 from counter[char] +1 )

The if condition is > most_common_count and not >= - hence even if i reaches 3 - condition would not execute.

Hence the output [3, 'D']

Try this instead :

class LetterCounter def initialize(text) @text = text end

  def calculate_most_common()
    counter = Hash.new(0)
    most_common = nil
    most_common_count = 0
    @text.chars.each do |char|
      next unless is_letter?(char)

      puts char + "  ==> " + counter[char].to_s # To know the value on each iteration
      counter[char] += 1
      if counter[char] > most_common_count
        most_common = char
        most_common_count = counter[char]
        puts [most_common_count, most_common] # To know when the if condition is executed
      end
    end
    return [most_common_count, most_common]
  end

  private

  def is_letter?(letter)
    return letter =~ /[a-z]/i
  end
end

counter = LetterCounter.new("Digital Punk")
p counter.calculate_most_common
Related