Ruby anagram solver [закрыто]

Я хочу написать решатель типа анаграммы в Ruby, но он будет работать со списком слов, например.

список слов:

the
these
one
owner

Я бы позволил пользователю ввести некоторые буквы, e.G noe, и он будет искать в списке слов слова, которые он может сделать, используя буквы, введенные пользователем, и вернет one и если они войдут в " eth "или даже" the", это вернет the. Я пытаюсь придумать эффективный способ сделать это, но я обводил вокруг каждого слова, соответствовал букве в слове, проверяя слово для каждой буквы, и обе длины совпадают. Может ли кто-нибудь дать совет лучшего и более эффективного способа сделать это?

7 ответов


большая идея заключается в том, что все анаграммы идентичны при сортировке. Поэтому, если вы создадите хэш (не знаю, что Ruby называет это) списков, где ключи сортируются словами, а значение-это список слов, которые сортируются по данному ключу, то вы можете найти анаграммы очень быстро, сортируя Слово и глядя в свой хэш.


ответ rrenaud велик, и вот пример того, как построить такой хэш в ruby, учитывая массив с именем "words", который содержит все слова в своем словаре:

@words_hash = words.each_with_object(Hash.new []) do |word, hash|
  hash[word.chars.sort] += [word]
end

код выше предполагает ruby 1.9.2. Если вы используете более старую версию, то chars не существует, но вы можете использовать .split('').sort.

объектом по умолчанию хэша является пустой массив, что облегчает кодирование в некоторых случаях, потому что вам не нужно беспокоиться о гашиш дает тебе ноль.

источник:https://github.com/DavidEGrayson/anagram/blob/master/david.rb


одним из решений может быть:

def combine_anagrams(words)
  output_array = Array.new(0)
  words.each do |w1|
    temp_array = []
    words.each do |w2|
      if (w2.downcase.split(//).sort == w1.downcase.split(//).sort)
        temp_array.push(w2)
      end
    end
    output_array.push(temp_array)
  end
  return output_array.uniq
end

Я не мог устоять перед решением этой ruby quiz:)

class String

  def permutation(&block)
    arr = split(//)
    arr.permutation { |i| yield i.join }
  end
end


wordlist = ["one", "two"]

"noe".permutation do |i|
  puts "match found: #{i}" if wordlist.include?(i)
end

основная идея заключается в том, что он создает и массив и использует его функцию перестановки, чтобы придумать результат. Это может быть не эффективно, но я нахожу это элегантным. : D


Это может быть то, что вы ищете: Решение Анаграмм В Ruby

вот еще один подход (это лучший ответ): Анаграмма Решатель В Python


def combine_anagrams(words)
  cp = 0
  hash = Hash.new []
  words.each do |word|
    cp += 1
    (cp..words.count).each do |i|
      hash[word.to_s.chars.sort.join] += [word]
    end
    hash[word.to_s.chars.sort.join] = hash[word.to_s.chars.sort.join].uniq
  end
  return hash
end

вот довольно похожий на мой. Чтение из файла словаря и сравнение отсортированных символов в виде массива. Сортировка производится по заранее выбранным кандидатам.

def anagrams(n)
  text = File.open('dict.txt').read

  candidates = []
  text.each_line do |line|
    if (line.length - 1) == n.length
      candidates << line.gsub("\n",'')
    end
  end

  result = []

  candidates.each do |word|
    if word.chars.sort == n.chars.sort
      result << word
    end
  end

  result

end