2011-08-23 14 views
14

Sto cercando di scrivere un risolutore di tipo anagramma in Ruby, ma funzionerà contro un elenco di parole, in questo modo.Ruby solver anagramma

Elenco di parole è:

the 
these 
one 
owner 

mi permetterebbe all'utente di inserire alcune lettere, ad esempio, noe, e sarebbe cercare l'elenco di parole per le parole che si può fare utilizzando le lettere che l'utente ha di ingresso e porterebbe indietro one e se sono entrati "et" o anche "il" si sarebbe riportato the. Ho cercato di pensare a un modo efficace per farlo, ma ho fatto il giro di ogni parola, ho abbinato una lettera alla parola, ho controllato la parola per ogni lettera e entrambe le lunghezze corrispondono. Qualcuno può dare consigli su un modo migliore e più efficiente per farlo?

risposta

30

La grande idea è che tutti gli anagrammi sono identiche quando ordinato. Quindi se costruisci un hash (non so cosa Ruby li chiama) di liste, dove le chiavi sono parole ordinate e il valore è l'elenco di parole che ordina la chiave data, puoi trovare gli anagrammi molto velocemente ordinando parola e guardando nel tuo hash.

+1

Ottima idea. Che ne dici di multi word anagram solver? Come 'rrenaud' =>' Ad Rerun'? –

+0

@KimmoLeh per dividere le frasi in array e quindi rimuovere tutte le istanze di carattere spazio dagli array. Quindi, ordina gli array e poi abbinalo. –

2

non ho potuto resistere risolvere questo rubino 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 

L'idea di base è che si crea e matrice e utilizza la sua funzione di permutazione a venire con il risultato. Potrebbe non essere efficiente ma lo trovo elegante. : D risposta

+0

oh mio amore! – thelastinuit

9

di rrenaud è grande, ed ecco un esempio di come costruire un tale hash in Ruby, dato un array di nome "words", che contiene tutte le parole nel dizionario:

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

Il codice sopra assume rubino 1.9.2. Se si sta utilizzando una versione precedente, allora chars non esiste ma è possibile utilizzare .split('').sort.

L'oggetto predefinito dell'hash è impostato per essere l'array vuoto, il che rende la codifica più semplice in alcuni casi perché non devi preoccuparti dell'hash che ti dà zero.

Fonte: https://github.com/DavidEGrayson/anagram/blob/master/david.rb

+3

Questo è identico a 'words.group_by {| word | word.chars.sort} ' –

+0

Fantastico, ma in realtà dovresti farlo:' @words_hash = words.group_by {| word | word.chars.sort}; @ words_hash.default = [] ' –

4

Una soluzione potrebbe essere:

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

Ecco abbastanza simile dei miei. Lettura da un file di dizionario e confronto di caratteri ordinati come una matrice. L'ordinamento viene fatto su candidati preselezionati.

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 
Problemi correlati