Refactoring my ruby ​​solver anagram?

I recently had to write a solver anagram for an interview. Here is my code.

class Anagram

  def self.resolves?(first_word, second_word)
    @letter_counts = {}

    # Assuming that anagrams aren't case sensitive.
    first_word.downcase!
    second_word.downcase!

    count_letters(first_word, 1)
    count_letters(second_word, -1)

    (sum_of_counts == 0)
  end

  private
    def self.sum_of_counts
      @letter_counts.inject(0){|sum, n| sum + n[1]}
    end

    def self.count_letters(aword, incrementer)
      aword.each_byte {|c| @letter_counts[c].nil? ? @letter_counts[c] = 1 : @letter_counts[c]+=incrementer }
    end
end

puts Anagram.resolves?('dog','cat')
puts Anagram.resolves?('dog','god')
puts Anagram.resolves?('Jim','Jones')
puts Anagram.resolves?('Hello','olleH')

I especially don't like the count_letters method and checking for the existence of a hash value. Where can I improve this code to make it more idiomatic Ruby?

Thanks in advance.

+5
source share
5 answers

How about this ?:

def anagrams?(w1, w2)
  w1.downcase.split('').sort == w2.downcase.split('').sort
end

Anagrams have the same letters, so the array of letters for each word should be equal.

+12
source

I like this approach:

  • Take both strings as arrays of letters.
  • Sorting.
  • Compare them.
  • If they match, words are anagrams.

The code in ruby ​​looks very simple:

def self.resolves?(first_word, second_word)
  first_word.downcase!
  second_word.downcase!
  first_word.split(//).sort == second_word.split(//).sort
end

, , .

+4

, , .

, , .. O (n), n == , , .

(+1 , -1 ), .

, , , .

class Anagram
  def self.resolves?(first_word, second_word)
     return false unless first_word.size == second_word.size
     counts = Array.new(26,0)
     offset = "a"[0]
     first_word.downcase.each_byte  {|b| counts[b-offset]+=1}
     second_word.downcase.each_byte {|b| counts[b-offset]-=1}
     counts.detect{|i| i!=0}.nil?
  end
end

+3

Hash: Hash # new , :

h = Hash.new { 0 }
h[:a] += 1
h.inspect # => {:a=>1}

:

@letter_counts = Hash.new { 0 }
...
aword.each_byte { |c| @letter_counts[c] += incrementer }
0

Super late, but randomly came across this, so I will answer. I am sure there is a more efficient way to write this, but whatever ....

def anagram(str1,str2)
    str1 = str1.split("").map{|x| x.ord}.inject(:+)
    str2 = str2.split("").map{|x| x.ord}.inject(:+)
    p str1 == str2
end

anagram("iceman","cinema") # => true
0
source

All Articles