2011-08-23 6 views
14

Chcę napisać narzędzie do rozwiązywania anagramów w Ruby, ale będzie ono działało na liście słów, tak jak to.Solwery z anionami rubowymi

Lista słów jest:

the 
these 
one 
owner 

bym pozwalają użytkownikowi na wejście niektóre litery, np Noe, i byłoby przeszukać listę słów do słów, że może to zrobić za pomocą liter użytkownik posiada wejścia i przyniosłoby one, a jeśli wprowadzono "eth" lub nawet "the" to przyniosłoby the. Próbowałem wymyślić skuteczny sposób, aby to zrobić, ale pętlę wokół każdego słowa, dopasowuję literę do słowa, sprawdzając słowo dla każdej litery i obie długości pasujące do siebie. Czy ktoś może doradzić lepszy i bardziej skuteczny sposób na zrobienie tego?

Odpowiedz

30

Big idea jest taka, że ​​wszystkie anagramy są identyczne, gdy sortowane. Więc jeśli zbudujesz hasz (nie wiesz, co Ruby nazywa) listami, gdzie klucze są posortowanymi słowami, a wartość jest listą słów, które sortuje do danego klucza, to możesz szybko znaleźć anagramy, sortując słowo i patrząc w hasz.

+1

Świetny pomysł. A co powiesz na multi-word anagram solver? Jak 'rrenaud' =>' Ad Rerun'? –

+0

@KimmoLehto podziel zdania na tablice, a następnie usuń wszystkie wystąpienia spacji z tablic. Następnie posortuj tablice i dopasuj je. –

2

nie mogłem się oprzeć rozwiązania tego rubinowy quizu :)

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 

Podstawowym założeniem jest to, że tworzy i tablicą i wykorzystuje to funkcja permutacji wymyślić wyniku. To może nie być wydajne, ale uważam, że jest eleganckie. : D Odpowiedź

+0

o mój, po prostu uwielbiam to! – thelastinuit

9

rrenaud jest wielki, a tutaj jest przykładem, jak zbudować taki hash w Ruby, biorąc pod tablicą nazwie „words”, który zawiera wszystkie słowa w słowniku:

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

Powyższy kod zakłada ruby ​​1.9.2. Jeśli używasz starszej wersji, chars nie istnieje, ale możesz użyć .split('').sort.

Domyślnym obiektem skrótu jest pusta tablica, co czyni kodowanie łatwiejszym w niektórych przypadkach, ponieważ nie musisz się martwić, że hasz daje zero.

Źródło: https://github.com/DavidEGrayson/anagram/blob/master/david.rb

+3

To jest identyczne z 'words.group_by {| word | word.chars.sort} ' –

+0

Fajnie, ale tak naprawdę musisz to zrobić:' @words_hash = words.group_by {| word | word.chars.sort}; @ words_hash.default = [] ' –

4

Jednym z rozwiązań mogłoby być:

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 
0
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 
0

Oto dość podobne z kopalni. Czytanie z pliku słownika i porównywanie posortowanych znaków jako tablicy. Sortowanie odbywa się na wstępnie wybranych kandydatów.

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