Skip to content
Open
80 changes: 80 additions & 0 deletions lib/adagrams.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
require 'pry'


def draw_letters
letters_in_hand = ARRAY_OF_LETTERS.shuffle.slice(1..10)
return letters_in_hand
end

ARRAY_OF_LETTERS = ["A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "C", "C", "D", "D", "D", "D", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "F", "F", "G", "G", "G", "H", "H", "I", "I", "I", "I", "I", "I", "I", "I", "I", "J", "K", "L", "L", "L", "L", "M", "M", "N", "N", "N", "N", "N", "N", "O", "O", "O", "O", "O", "O", "O", "O", "P", "P", "Q", "R", "R", "R", "R", "R", "R", "S", "S", "S", "S", "T", "T", "T", "T", "T", "T", "U", "U", "U", "U", "V", "V", "W", "W", "X", "Y", "Y", "Z"]

Choose a reason for hiding this comment

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

It's advisable to store the frequency information in a hash, and then use that hash to create an array. Also, it's best to put this global at the top of your script.

letter_counts = {
  "A"=>9, "B"=>2, ...
}
letters = []
letter_counts.each do |letter, count|
  count.times do
    letters << letter
  end
end


def uses_available_letters? (input, letters_in_hand)
input = input.upcase.chars
dup_letters_in_hand = letters_in_hand.clone


input.each do |chars|
if dup_letters_in_hand.include?(chars)
dup_letters_in_hand.delete(chars)
else
return false
end
end

check = 0

Choose a reason for hiding this comment

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

This check seems redundant. The first loop will return false if a letter in the word is not in the hand. If that return doesn't happen, you can simply return true after that loop is finished.

input.each do |chars|
if letters_in_hand.include?(chars)
check = 0
else
check += 1
end
end
return check == 0
end

def score_word(word)
letter_points = {
"A" => 1, "B" => 3, "C" => 3, "D" => 2, "E" => 1, "F" => 4, "G" => 2, "H" => 4, "I" => 1, "J" => 8, "K" => 5, "L" => 1, "M" => 3, "N" => 1, "O" => 1, "P" => 3, "Q"=> 10, "R"=> 1, "S" => 1, "T" => 1, "U" => 1, "V" => 4, "W" => 4, "X" => 8, "Y" => 4, "Z" => 10
}
word_array = word.upcase.chars
word_points = word_array.map do |k, v|

Choose a reason for hiding this comment

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

Use meaningful names for k and v (i.e. letter and letter_value).

letter_points[k]
end
total_points = word_points.sum

Choose a reason for hiding this comment

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

Consider using the .sum enumerable to combine the map and sum operations your perform.

if word.length > 6 && word.length < 11
total_points += 8
end
return total_points
end

def highest_score_from(words)
highest_score_hash = {}
score = 0
winning_word = ""

words.each do |object|
word_score = score_word(object)
if word_score > score
score = word_score
winning_word = object
elsif word_score == score
length_of_obj = object.length
length_of_winning_word = winning_word.length
if length_of_winning_word == 10
winning_word = winning_word
elsif length_of_obj == 10
winning_word = object
else
winning_word = tiebreaker_length(winning_word, object)
end
end
highest_score_hash[:word] = winning_word
highest_score_hash[:score] = score
end
return highest_score_hash
end

def tiebreaker_length (old_word, new_word)

Choose a reason for hiding this comment

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

Great use of a helper method. You could consider putting more of the tiebreaker functionality into this method.

tiebreaker_len_arr = [old_word, new_word]
tiebreaker_len_arr.min { |old_word, new_word| old_word.length <=> new_word.length }
end
86 changes: 43 additions & 43 deletions test/adagrams_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,167 +13,167 @@
drawn_letters = draw_letters
expect(drawn_letters.size).must_equal 10
end

it 'returns an array, and each item is a single-letter string' do
drawn_letters = draw_letters
expect(drawn_letters.size).must_equal 10

expect(drawn_letters).must_be_instance_of Array
drawn_letters.each do |letter|
expect(letter).must_be_instance_of String
expect(letter.length).must_equal 1
end
end
end

describe 'uses_available_letters? method' do

it 'returns true if the submitted letters are valid against the drawn letters' do
drawn_letters = ['D', 'O', 'G', 'X', 'X', 'X', 'X', 'X', 'X', 'X']
test_word = 'DOG'

is_valid = uses_available_letters? test_word, drawn_letters

expect(is_valid).must_equal true
end

it 'returns false word contains letters not in the drawn letters' do
drawn_letters = ['D', 'O', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X']
test_word = 'DOG'

is_valid = uses_available_letters? test_word, drawn_letters

expect(is_valid).must_equal false
end

it 'returns false word contains repeated letters more than in the drawn letters' do
drawn_letters = ['A', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X']
test_word = 'AAA'

is_valid = uses_available_letters? test_word, drawn_letters

expect(is_valid).must_equal false
end

it 'does not change the letters in hand' do
drawn_letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
dl_copy = drawn_letters.dup

# Hint: if your implementation of uses_available_letters?
# needs to change the hand, you should make a copy first
uses_available_letters? 'ABCD', drawn_letters

expect(drawn_letters).must_equal dl_copy
end
end

describe 'score_word method' do
it 'returns an accurate numerical score according to the score chart' do
expect(score_word("A")).must_equal 1
expect(score_word("DOG")).must_equal 5
expect(score_word("WHIMSY")).must_equal 17
end

it 'returns a score regardless of input case' do
expect(score_word("a")).must_equal 1
expect(score_word("dog")).must_equal 5
expect(score_word("wHiMsY")).must_equal 17
end

it 'returns a score of 0 if given an empty input' do
expect(score_word("")).must_equal 0
end

it 'adds an extra 8 points if the word is 7 or more characters long' do
expect(score_word("XXXXXXX")).must_equal 64
expect(score_word("XXXXXXXX")).must_equal 72
expect(score_word("XXXXXXXXX")).must_equal 80
end
end

describe 'highest_score_from method' do
it 'returns a hash that contains the word and score of best word in an array' do
words = ['X', 'XX', 'XXX', 'XXXX']
best_word = highest_score_from words

expect(best_word[:word]).must_equal 'XXXX'
expect(best_word[:score]).must_equal 32
end

it 'accurately finds best scoring word even if not sorted' do
words = ['XXX', 'XXXX', 'XX', 'X']
best_word = highest_score_from words

expect(best_word[:word]).must_equal 'XXXX'
expect(best_word[:score]).must_equal 32
end

it 'in case of tied score, prefers the word with fewer letters' do
# the character 'M' is worth 3 points, 'W' is 4 points
words = ['MMMM', 'WWW']

# verify both have a score of 12
expect(score_word(words.first)).must_equal 12
expect(score_word(words.last)).must_equal 12

best_word = highest_score_from words

expect(best_word[:word]).must_equal 'WWW'
expect(best_word[:score]).must_equal 12
end

it 'in case of tied score, prefers the word with fewer letters regardless of order' do
# the character 'M' is worth 3 points, 'W' is 4 points
words = ['WWW', 'MMMM']

# verify both have a score of 12
expect(score_word(words.first)).must_equal 12
expect(score_word(words.last)).must_equal 12

best_word = highest_score_from words

expect(best_word[:word]).must_equal 'WWW'
expect(best_word[:score]).must_equal 12
end

it 'in case of tied score, prefers most the word with 10 letters' do
# the character 'A' is worth 1 point, 'B' is 3 points
words = ['AAAAAAAAAA', 'BBBBBB']

# verify both have a score of 10
expect(score_word(words.first)).must_equal 18
expect(score_word(words.last)).must_equal 18

best_word = highest_score_from words

expect(best_word[:word]).must_equal 'AAAAAAAAAA'
expect(best_word[:score]).must_equal 18
end

it 'in case of tied score, prefers most the word with 10 letters regardless of order' do
# the character 'A' is worth 1 point, 'B' is 3 points
words = ['BBBBBB', 'AAAAAAAAAA']

# verify both have a score of 10
expect(score_word(words.first)).must_equal 18
expect(score_word(words.last)).must_equal 18

best_word = highest_score_from words

expect(best_word[:word]).must_equal 'AAAAAAAAAA'
expect(best_word[:score]).must_equal 18
end

it 'in case of tied score and same length words, prefers the first word' do
# the character 'A' is worth 1 point, 'E' is 1 point
words = ['AAAAAAAAAA', 'EEEEEEEEEE']

# verify both have a score of 10
expect(score_word(words.first)).must_equal 18
expect(score_word(words.last)).must_equal 18

best_word = highest_score_from words

expect(best_word[:word]).must_equal words.first
expect(best_word[:score]).must_equal 18
end
Expand Down