diff --git a/lib/adagrams.rb b/lib/adagrams.rb index e69de29..aa5cb3f 100644 --- a/lib/adagrams.rb +++ b/lib/adagrams.rb @@ -0,0 +1,139 @@ +require 'csv' + +def return_letter_pool_hash + + letter_pool_hash = { + "A" => {number_of_tiles: 9, number_of_points: 1}, + "B" => {number_of_tiles: 2, number_of_points: 3}, + "C" => {number_of_tiles: 2, number_of_points: 3}, + "D" => {number_of_tiles: 4, number_of_points: 2}, + "E" => {number_of_tiles: 12, number_of_points: 1}, + "F" => {number_of_tiles: 2, number_of_points: 4}, + "G" => {number_of_tiles: 3, number_of_points: 2}, + "H" => {number_of_tiles: 2, number_of_points: 4}, + "I" => {number_of_tiles: 9, number_of_points: 1}, + "J" => {number_of_tiles: 1, number_of_points: 8}, + "K" => {number_of_tiles: 1, number_of_points: 5}, + "L" => {number_of_tiles: 4, number_of_points: 1}, + "M" => {number_of_tiles: 2, number_of_points: 3}, + "N" => {number_of_tiles: 6, number_of_points: 1}, + "O" => {number_of_tiles: 8, number_of_points: 1}, + "P" => {number_of_tiles: 2, number_of_points: 3}, + "Q" => {number_of_tiles: 1, number_of_points: 10}, + "R" => {number_of_tiles: 6, number_of_points: 1}, + "S" => {number_of_tiles: 4, number_of_points: 1}, + "T" => {number_of_tiles: 6, number_of_points: 1}, + "U" => {number_of_tiles: 4, number_of_points: 1}, + "V" => {number_of_tiles: 2, number_of_points: 4}, + "W" => {number_of_tiles: 2, number_of_points: 4}, + "X" => {number_of_tiles: 1, number_of_points: 8}, + "Y" => {number_of_tiles: 2, number_of_points: 4}, + "Z" => {number_of_tiles: 1, number_of_points: 10} +} + +return letter_pool_hash + +end + +def draw_letters + + letter_pool_hash = return_letter_pool_hash + + letter_pool_array = letter_pool_hash.map do |letter, letter_info| + (letter * letter_info[:number_of_tiles]).split("") + end + + letter_pool_array = letter_pool_array.flatten + + drawn_letters = letter_pool_array.sample(10) + return drawn_letters + +end + +def uses_available_letters? (input, letters_in_hand) + + copy_of_hand = letters_in_hand.clone + letters_of_input = input.upcase.split("") + + letters_of_input.each do |letter_from_input| + if copy_of_hand.include? letter_from_input + + index_of_input_letter = copy_of_hand.index(letter_from_input) + copy_of_hand.delete_at(index_of_input_letter) + + else + + copy_of_hand = letters_in_hand.clone + return false + + end + end + + return true + +end + +def score_word(word) + + letter_pool_hash = return_letter_pool_hash + + word_array = word.upcase.split("") + + word_points = word_array.map do |letter| + letter_pool_hash[letter][:number_of_points] + end + + if word_array.length >= 7 + word_points << 8 + end + + return word_points.sum + +end + +def highest_score_from(words) + scores_hash = {} + + words.each do |word| + scores_hash[word] = score_word(word) + end + + highest_score = scores_hash.values.max + highest_scores_hash = scores_hash.select do |word, score| + score == highest_score + end + + if highest_scores_hash.length == 1 + return {word: highest_scores_hash.keys[0], score: highest_scores_hash.values[0]} + else + + highest_scores_hash.each do |word, score| + if word.length == 10 + return {word: word, score: score} + end + end + + min_length = highest_scores_hash.map { |word, score| word.length }.min + highest_scores_hash.each do |word, score| + if word.length == min_length + return {word: word, score: score} + end + end + + end +end + +def is_in_english_dict?(input) + + dict_array = [] + CSV.foreach("assets/dictionary-english.csv") do |row| + dict_array << row + end + + dict_array = dict_array.flatten + + answer = dict_array.include?(input.downcase) ? true : false + + return answer + +end diff --git a/test/adagrams_test.rb b/test/adagrams_test.rb index 90ec44d..ae7bf95 100644 --- a/test/adagrams_test.rb +++ b/test/adagrams_test.rb @@ -13,11 +13,11 @@ 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 @@ -25,157 +25,195 @@ 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 end + + describe 'is_in_english_dict? method' do + it 'returns true if input is contained in the english dictionary' do + # Arrange + input = "adverbs" + # Act + answer = is_in_english_dict?(input) + # Assert + expect(answer).must_equal true + + end + it 'returns false if input is not contained in the english dictionary' do + # Arrange + input = "laallaloo" + # Act + answer = is_in_english_dict?(input) + # Assert + expect(answer).must_equal false + end + + it 'returns correct answer regardless of input case' do + # Arrange + input = "AdVeRbS" + # Act + answer = is_in_english_dict?(input) + # Assert + expect(answer).must_equal true + end + + it 'returns false if given an empty input' do + # Arrange + input = "" + # Act + answer = is_in_english_dict?(input) + # Assert + expect(answer).must_equal false + end + end end