Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tiger - Lily & Stacy #59

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
81 changes: 77 additions & 4 deletions adagrams/game.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,84 @@

import random
def draw_letters():
pass
distribution_of_letters = {"A" : 9, "N" : 6, "B" : 2, "O" : 8, "C" : 2, "P" : 2, "D" : 4 ,"Q" : 1, "E" : 12, "R" : 6, "F" : 2, "S" : 4, "G" : 3, "T" : 6, "H" : 2, "U" : 4, "I" : 9, "V" : 2, "J" : 1 , "W" : 2, "K" : 1, "X" : 1, "L" : 4, "Y" : 2, "M" : 2, "Z" : 1}

Choose a reason for hiding this comment

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

Consider declaring this as a global "constant" (maybe POOL_OF_LETTERS) outside this function.

Doing so wouldn't really save on runtime (since we would then need to modify the counts and make a copy at the start of each call to this method), but it does declutter the method a bit by allowing us to move the large data structure to some innocuous corner of our file.

letters = []
while len(letters) < 10:
userletters = random.choice(list(distribution_of_letters.items()))
if userletters[1] > 0:
letters.append(userletters[0])
distribution_of_letters[userletters[0]]-=1
Comment on lines +10 to +13

Choose a reason for hiding this comment

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

Oh what an interesting way to handle checking the letter and the quantity!

return letters

def uses_available_letters(word, letter_bank):

Choose a reason for hiding this comment

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

👍

pass
counter = {}
for letter in letter_bank:
if letter in counter:
counter[letter] += 1
else:
counter[letter] = 1

for ch in word.upper():
if ch in counter and counter[ch] > 0:
counter[ch] -= 1
else:
return False
return True

def score_word(word):
pass
point_1_letters = ["A", "E", "I", "O", "U", "L", "N", "R", "S", "T"]
point_2_letters = ["D", "G"]
point_3_letters = ["B", "C", "M", "P"]
point_4_letters = ["F", "H", "V", "W", "Y"]
point_5_letters = ["K"]
point_8_letters = ["J", "X"]
point_10_letters = ["Q", "Z"]

# use map to store letter to score relationships
score_chart = {
1: point_1_letters,
2: point_2_letters,
3: point_3_letters,
4: point_4_letters,
5: point_5_letters,
8: point_8_letters,
10: point_10_letters
}

Choose a reason for hiding this comment

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

This takes a lot of lines. Let's combine this in one:

score_chart = {
    1: ["A", "E", "I", "O", "U", "L", "N", "R", "S", "T"]
    ...


total_score = 0

if len(word) != 0:
special_length = [7, 8, 9, 10]

# add additional 8 points for words with special length
if len(word) in special_length:
total_score += 8

Choose a reason for hiding this comment

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

Very creative! Consider refactoring this so we don't need a new data structure on line 51 and a for loop on line 54 (under the hood, if...in with a list is a loop).

We could combine the if statements together, like:

if len(word) > 6 and len(word) < 11:
    total_score += 8


# find the score for each letter in word, and add score to total_score
for point, letters in score_chart.items():
for letter in word.upper():
if letter in letters:
total_score += point

Choose a reason for hiding this comment

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

this works just fine! One thing to consider: looking up an item in a list is generally O(n), but the lookup time for a dictionary is O(1).

If we kept our dictionary like: letter_dict = {"A": 1, "B": 2....}, then our look up will be constant, and that will get rid of one of the the three for loops in this code block.

for letter in word.upper():
    if letter in letter_dict:
        # increase your total_score here

now our code only has one for loop in it!


return total_score


def get_highest_word_score(word_list):
pass
best_word = None

# iterate through the word_list, and update best_word when current word is the best word
for word in word_list:
score = score_word(word)

Choose a reason for hiding this comment

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

It's great that you have comments here to tell other coders what's going on, or to remind you later what this code does.

But with so many comments cutting up the code, it actually makes it harder to read. So here's what we can do:

def get_highest_word_score(word_list):
    '''
    Function iterates through word_list, and updates best_word 
    when current word is the best word.
    The rest of your comments here
    '''
    best_word = None
    # the rest of your code here

We can bring all our comments up to the top inside docstrings


# store the first word and score to the empty best_word
if not best_word:
best_word = (word, score)
Comment on lines +71 to +72

Choose a reason for hiding this comment

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

This works! We could also do this on line 67 initially:

best_word = (word_list[0], score_word(word_list[0]))

# update best_word with new value when current score is greater than previous best score
elif score > best_word[1]:
best_word = (word, score)
# update best_word when there's a tie and the previous word length is not 10 and either current word length is 10 or shorter than previous word length
elif score == best_word[1] and len(best_word[0]) != 10 and (len(word) == 10 or len(word) < len(best_word[0])):
best_word = (word, score)

return best_word

16 changes: 16 additions & 0 deletions tests/test_wave_03.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,38 @@
from adagrams.game import score_word

def test_score_word_accurate():
# Arrange
word = "A"
word = "DOG"
word = "WHIMSY"
# Act
# total_score = score_word(word)
# Assert
assert score_word("A") == 1
assert score_word("DOG") == 5
assert score_word("WHIMSY") == 17

def test_score_word_accurate_ignores_case():
# Arrange
word = "a"
word = "dog"
word = "wHiMsY"
# Assert
assert score_word("a") == 1
assert score_word("dog") == 5
assert score_word("wHiMsY") == 17

def test_score_zero_for_empty():
# Arrange
word = ""
# Assert
assert score_word("") == 0

def test_score_extra_points_for_seven_or_longer():
# Arrange
word = "XXXXXXX"
word = "XXXXXXXX"
word = "XXXXXXXXX"
# Assert
assert score_word("XXXXXXX") == 64
assert score_word("XXXXXXXX") == 72
Expand Down