Skip to content

Instantly share code, notes, and snippets.

@JFickel
Last active December 24, 2015 06:29
Show Gist options
  • Save JFickel/6757108 to your computer and use it in GitHub Desktop.
Save JFickel/6757108 to your computer and use it in GitHub Desktop.
Twitch.tv Spellchecker
require_relative "spellchecker"
spellchecker = SpellChecker.new
while true
print '> '
word = gets.chomp
puts spellchecker.suggest(word)
end
class SpellChecker
VOWELS = ['a', 'e', 'i', 'o', 'u']
attr_reader :words
def initialize
@words = File.readlines('/usr/share/dict/words').map{|word| word.downcase.chomp}
index_words
end
def index_words
@words = @words.group_by{|word| word[0]}
@words.each do |key, value|
@words[key] = value.group_by {|word| word[1] }
end
@words.each do |key, value|
value.each do |key2, value2|
@words[key][key2] = value2.group_by {|word| word[2]}
end
end
end
def suggest(word)
@repeat_variations = []
@total_variations = []
variate_repeated_letters count_letters(word.downcase.strip)
@repeat_variations.each do |possibility|
variate_vowel possibility
end
@total_variations.unshift word.downcase.strip
find_possible_word
end
def find_possible_word
@total_variations.each do |variation|
possibilities = @words[variation[0]]
if @words[variation[0]] && @words[variation[0]][variation[1]]
possibilities = @words[variation[0]][variation[1]][variation[2]]
elsif @words[variation[0]]
possibilities = @words[variation[0]][variation[1]]
end
unless possibilities.nil?
possibilities.each do |possibility|
if possibility == variation
return possibility
end
end
end
end
return "NO SUGGESTION"
end
def variate_vowel word, index=0
remaining_word = word[index..-1]
remaining_word.each_char.with_index do |char, char_i|
if VOWELS.include? char
VOWELS.each do |vowel|
possibility = word.dup
possibility[index+char_i] = vowel
forward_string = word[1+char_i+index..-1]
if VOWELS.any? {|e| forward_string.include? e}
variate_vowel possibility, index+char_i+1
else
@total_variations << possibility
end
end
return
end
end
end
def count_letters word
word.each_char.with_object([]) do |char, obj|
last_character = obj.pop
if !last_character.nil? && last_character[0] == char
last_character[1] += 1
obj.push last_character
elsif last_character.nil?
obj.push [char, 1]
else
obj.push last_character
obj.push [char, 1]
end
end
end
def variate_repeated_letters letter_counter, index=0
unless letter_counter.any? {|lcount| lcount[1] > 1}
@repeat_variations << letter_counter.each.with_object("") {|letter_count,obj| letter_count[1].times { obj << letter_count[0]}}
return
end
remaining_letters = letter_counter[index..-1]
remaining_letters.each.with_index do |lcount, i|
if lcount[1] > 1
lcount[1].times do |num|
possibility = lcount.dup
possibility[1] = num+1
forward_letters = letter_counter[1+i+index..-1]
word = letter_counter.dup
word[index+i] = possibility
if forward_letters.any? {|lcount| lcount[1] > 1}
variate_repeated_letters word, index+i+1
else
@repeat_variations << word.each.with_object("") {|letter_count,obj| letter_count[1].times { obj << letter_count[0]}}
end
end
return
end
end
end
end
require_relative "spellchecker"
describe "spellcheck" do
it "should return a word" do
expect(SpellChecker.new.suggest("people")).to eq("people")
end
it "should return a word with a misplaced vowel" do
expect(SpellChecker.new.suggest("peeple")).to eq("people")
end
it "should return a word with repeated letters" do
expect(SpellChecker.new.suggest("ppeople")).to eq("people")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment