Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions lib/adagrams.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
require 'csv'

# returns an array of 10 letters
def draw_letters
letter_frequencies =
{
"A" => 9,
"B" => 2,
"C" => 2,
"D" => 4,
"E" => 12,
"F" => 2,
"G" => 3,
"H" => 2,
"I" => 9,
"J" => 1,
"K" => 1,
"L" => 4,
"M" => 2,
"N" => 6,
"O" => 8,
"P" => 2,
"Q" => 1,
"R" => 6,
"S" => 4,
"T" => 6,
"U" => 4,
"V" => 2,
"W" => 2,
"X" => 1,
"Y" => 2,
"Z" => 1,
}

pool_of_letters = []

letter_frequencies.each do |letter, freq|

freq.times do
pool_of_letters << letter
end

end

return pool_of_letters.sample(10)

end


# Boolean method that verifies input is valid
def uses_available_letters?(input, letters_in_hand)

input_array = input.upcase.chars

letters_in_hand.each do |letter|

if input_array.include? letter
index = input_array.index(letter)
input_array.delete_at(index)
end
end

return input_array.length == 0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this -- returning true or false based off of this evaluation.

I think you could still have added above this

if input_array.include? letter
  ...
else
  return false
end

so that the method could jump out of the iteration sooner than looping all the way through, but yeah, this is great!


end


# returns word score based on letter value and word length
def score_word(word)

score = 0

word.upcase.each_char do |letter|

case letter
when "A", "E", "I", "O", "U", "L", "N", "R", "S", "T"
score += 1
when "D", "G"
score += 2
when "B", "C", "M", "P"
score += 3
when "F", "H", "V", "W", "Y"
score += 4
when "K"
score += 5
when "J", "X"
score += 8
when "Q", "Z"
score += 10
end

end

if word.length >= 7
score += 8
end

return score

end


# returns hash of highest scoring word and its score
# applies rules for breaking ties
def highest_score_from(words)

best_word = {
word: [],
score: 0
}

words.each do |word|

score = score_word(word)

if score > best_word[:score]
best_word[:word].clear
best_word[:word] << word
best_word[:score] = score
end

if score == best_word[:score]
best_word[:word] << word
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this approach -- shoveling word into best_word hash on a tied score, or clearing it if the score is clearly better


end

# applies rules for ties:
# - shortest word wins unless there is a 10 letter word
# - if multiple 10 letter words, the first word wins
shortest_word = best_word[:word].min_by do |word|
word.length
end

all_tiles_words = best_word[:word].select do |word|
word.length == 10
end

if all_tiles_words.empty?
best_word[:word] = shortest_word
else
best_word[:word] = all_tiles_words[0]
end

return best_word

end


# Boolean method that verifies word is in game dictionary
def is_in_english_dict?(input)

CSV.read('assets/dictionary-english.csv', headers: true).each do |word|

if input.downcase == word[0]
return true
end

end

return false
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always returning false if it gets to this point (aka hasn't returned true beforehand) is great!


end
31 changes: 31 additions & 0 deletions specs/adagrams_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,35 @@
expect(best_word[:score]).must_equal 18
end
end

describe 'is_in_english_dict? method' do
it 'returns true if submitted word is in game dictionary' do
word = 'aardvark'

is_valid = is_in_english_dict?(word)

expect(is_valid).must_equal true
end

it 'returns true if submitted word is in game dictionary - case insensitive' do
word = 'AARDVARK'

is_valid = is_in_english_dict?(word)

expect(is_valid).must_equal true
end

it 'returns false if submitted word is not in game dictionary' do

expect(is_in_english_dict?('niugfdfl')).must_equal false
expect(is_in_english_dict?('hippopotamus')).must_equal false
expect(is_in_english_dict?('#&*123')).must_equal false
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are all really good edge cases that I would expect! Nicely done


end

it 'returns false if given empty input' do
expect(is_in_english_dict?('')).must_equal false
end

end
end