Реальный алгоритм Ruby
Я хочу написать решатель типа анаграммы в Ruby, но он будет работать против списка слов, например.
Список слов:
the
these
one
owner
Я бы позволил пользователю ввести несколько букв, например noe, и он будет искать список слов для слов, которые он может сделать, используя буквы, которые пользователь вводит, и вернет one
, и если они войдут в "eth", или даже "это" оно вернет the
. Я пытался подумать об эффективном способе сделать это, но я зацикливал каждое слово, сопоставлял букву в слове, проверяя слово для каждой буквы и обе длины совпадали. Может ли кто-нибудь дать совет о более эффективном и эффективном способе сделать это?
Ответы
Ответ 1
Большая идея состоит в том, что все анаграммы идентичны при сортировке. Поэтому, если вы создаете хэш (не знаете, что Ruby называет этим) списков, где ключи сортируются словами, а значение представляет собой список слов, которые сортируются по заданному ключу, то вы можете быстро найти анаграммы, сортируя слово и поиск в вашем хеше.
Ответ 2
rrenaud answer is great, и вот пример того, как построить такой хэш в 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
Ответ 3
Одним из решений может быть:
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
Ответ 4
Я не мог удержаться от решения этой рубиновой викторины:)
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
Ответ 5
Это может быть то, что вы ищете: Решение анаграмм в Ruby
Здесь другой подход (это верхний ответ): Anagram Solver в Python
Ответ 6
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
Ответ 7
Здесь очень похоже. Чтение из файла словаря и сравнение отсортированных символов в виде массива. Сортировка выполняется по предварительно выбранным кандидатам.
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