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
97 changes: 97 additions & 0 deletions lib/adagrams.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
def draw_letters
letter_pool = { 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 }
letter_array = []
letter_pool.each do |letter, quantity|
quantity.times do
letter_array << letter.to_s.downcase
end
end
return letter_array.sample(10)
end

def uses_available_letters?(input, letters_in_hand)
size = 0
input_array = input.upcase.split(//)

Choose a reason for hiding this comment

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

Calling upcase on the user's input is a good idea, however you forgot to call upcase on the letters in letters_in_hand which means that if you are passed lowercase letters you won't have any matches.

You could add this to fix it:

letters_in_hand = letters_in_hand.map { |l| l.upcase }


letters_in_hand.each_with_index do |letter, index|
if input_array.include?(letter)

Choose a reason for hiding this comment

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

This is really close to right. Because of the way the above loop is implemented this winds up requiring the user to use all of a given letter. If you input_array.each and letters_in_hand.include? then this works perfectly.

size += 1
letters_in_hand.delete(index)

Choose a reason for hiding this comment

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

Because you delete letters from the hand as you go if a user submits a mostly correct word the letters it used are deleted. For example:

$ ruby wave-2-game.rb
Welcome to Adagrams!
Let's draw 10 letters from the letter pool...
You have drawn the letters:
t, g, e, a, a, s, e, e, a, e
Please input a word that only uses the letters from the letter bank
tget
You entered in a word that contains characters not in the letter bank
Please input a word that only uses the letters from the letter bank
tge
You entered in a word that contains characters not in the letter bank
Please input a word that only uses the letters from the letter bank

end
end

if size == input_array.length

Choose a reason for hiding this comment

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

This works but having to keep track of size is a little awkward.

return true
else
return false
end
end

def score_word(word)
points = 0
word.upcase.split(//).each do |letter|

Choose a reason for hiding this comment

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

There's a handy .chars method on String that does the same thing as .split(//) but a little clearer, if you want to do this again in the future. 😃

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

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

return points
end

def highest_score_from(words)
highest_score = Hash.new(0)

Choose a reason for hiding this comment

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

Misleading variable name: highest_score winds up holding all of the scores, not just the highest one(s).


words.each do |word|
highest_score[word] = score_word(word)
end

max_words = {
word: [],
score: [],
}

highest_score.each do |k, v|
if v == highest_score.values.max
max_words[:word] << k
max_words[:score] = v
end
end

best_word = {}

min_length = 10
if max_words[:word].length == 1
best_word[:word] = max_words[:word][0]
best_word[:score] = max_words[:score]
else
max_words[:word].each do |word|
if word.length == 10
best_word[:word] = word
best_word[:score] = max_words[:score]
return best_word
elsif word.length < min_length
min_length = word.length
best_word[:word] = word
best_word[:score] = max_words[:score]

Choose a reason for hiding this comment

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

This is a clever way to find the shortest word in max_words.

end
end
end
return best_word
end
90 changes: 44 additions & 46 deletions specs/adagrams_spec.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
require 'minitest/autorun'
require 'minitest/reporters'
require 'minitest/skip_dsl'
require "minitest/autorun"
require "minitest/reporters"
require "minitest/skip_dsl"

require_relative '../lib/adagrams'
require_relative "../lib/adagrams"

# Get that nice colorized output
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new

describe 'Adagrams' do
describe 'draw_letters method' do
it 'draws ten letters from the letter pool' do
describe "Adagrams" do
describe "draw_letters method" do
it "draws ten letters from the letter pool" do
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
it "returns an array, and each item is a single-letter string" do
drawn_letters = draw_letters
expect(drawn_letters.size).must_equal 10

Expand All @@ -26,137 +26,135 @@
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'
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'
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'
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

end

describe 'score_word method' do
it 'returns an accurate numerical score according to the score chart' do
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
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
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
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']
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[: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']
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[: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
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']
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[: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
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']
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[: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
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']
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[: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
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']
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[: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
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']
words = ["AAAAAAAAAA", "EEEEEEEEEE"]

# verify both have a score of 10
expect(score_word(words.first)).must_equal 18
Expand Down
1 change: 1 addition & 0 deletions wave-1-game.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require_relative 'lib/adagrams'
require 'pry'

def display_welcome_message
puts "Welcome to Adagrams!"
Expand Down