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

Spruce - Mary Tian #52

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fa003b2
completed draw_letters() function
rzuick Sep 22, 2021
58cde09
Merge branch 'master' of https://github.com/Mary-Tian/adagrams-py
rzuick Sep 22, 2021
58e4683
updated draw_letters() to use the LETTER_POOL dict included in tests
rzuick Sep 22, 2021
ede8403
updated uses_available_letters() and passed all tests in wave 02. can…
rzuick Sep 22, 2021
d22f5b3
crefactored uses_available_letters() to be more concise
rzuick Sep 22, 2021
41eac74
thoughts for tackling score_word(word)
rzuick Sep 22, 2021
578b283
condensed LETTER_POOL dict and deleted import string
rzuick Sep 22, 2021
8f264ab
Changed variable names in draw_letters for clarity.
Mary-Tian Sep 23, 2021
9489155
Completed Wave 3, all tests passing.
Mary-Tian Sep 24, 2021
9569f75
formatted file to align with pep8 standards
rzuick Sep 24, 2021
8e30f04
refactored uses_available_letters function for clarity. updated varia…
rzuick Sep 24, 2021
692d319
created docstrings for uses_available_letters function
rzuick Sep 24, 2021
7f1428d
Created dictionary for get_highest_word_score. Working on rest of code.
Mary-Tian Sep 24, 2021
b091b4a
finished get_highest_word_score function. game.py passing all waves.
rzuick Sep 25, 2021
c1f82c3
completing merge
rzuick Sep 25, 2021
19f5d56
removed commented code
rzuick Sep 25, 2021
1f82866
refactored score_word function with list comprehension
rzuick Sep 26, 2021
8b1289b
added docstrings for get_highest_word_score function. refactored this…
rzuick Sep 26, 2021
d8e63cf
updated comment about rando module imported
rzuick Sep 26, 2021
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
86 changes: 82 additions & 4 deletions adagrams/game.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,89 @@
import random
# module will let us randomly choose characters in specified sample range

def draw_letters():
pass
"""
Build a hand of 10 letters for the user. Returns an array of strings, one letter long.
The num of strings included in the array
cannot be more than the num alloted in the letter table
"""
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
}
Comment on lines +10 to +14
Copy link
Collaborator

Choose a reason for hiding this comment

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

Long chunks of data like letter_bank tend to clutter functions and require more scrolling to see the rest of the function body. Consider moving this dictionary outside of this function (or in a new file) as a constant variable to be referenced in draw_letters.

letter_to_draw = list(LETTER_POOL.keys())
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
letter_to_draw = list(LETTER_POOL.keys())
letter_to_draw = list(LETTER_POOL)

We can omit keys() as the default iterator for dictionaries are its own keys. This means the list function will iterate through LETTER_POOL and create a list of its keys.

letters_drawn = []
letter_count = {}
for letter in random.sample(letter_to_draw, 10):
if letter not in letters_drawn:
letters_drawn.append(letter)
letter_count[letter] = 1
elif letter_count[letter] < LETTER_POOL[letter]:
letters_drawn.append(letter)
letter_count[letter] += 1
Comment on lines +18 to +24
Copy link
Collaborator

Choose a reason for hiding this comment

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

Love the use of a frequency map to keep track of the letters being drawn!

Copy link
Collaborator

Choose a reason for hiding this comment

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

We could also use sample to build letters_drawn directly from LETTER_POOL.

    letters_drawn = random.sample(LETTER_POOL.keys(), counts=LETTER_POOL.values(), k=10)

Here's the sample documentation, if you'd like to learn more about the method.


return letters_drawn


def uses_available_letters(word, letter_bank):
pass
"""
If letters in user's word are not in letter_bank, or if user uses more letters
than in hand, the function returns False.
Function returns False if user enters empty word. Else, it returns True.
"""
for letter in word:
if letter not in letter_bank or word.count(letter) > letter_bank.count(letter):
is_valid = False
else:
is_valid = True

return is_valid
Comment on lines +35 to +41
Copy link
Collaborator

Choose a reason for hiding this comment

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

Great use of a guard clause here. We can make the code even neater by getting rid of the else clause (aka the dangly bit). To do so, we can take advantage of using the is_valid flag to describe the single scenario where is_valid would be false in the guard clause. Otherwise, the function will just return True. Like so:

    is_valid  = True 
    for letter in word:
        if letter not in letter_bank or word.count(letter) > letter_bank.count(letter):
            is_valid = False

    return is_valid
Suggested change
for letter in word:
if letter not in letter_bank or word.count(letter) > letter_bank.count(letter):
is_valid = False
else:
is_valid = True
return is_valid
is_valid = True
for letter in word:
if letter not in letter_bank or word.count(letter) > letter_bank.count(letter):
is_valid = False
return is_valid



def score_word(word):
pass
"""
Calculate user's score for their entered word.
Ignore lettercase, account for empty word, and give extra points for longer words.
"""
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
}
Comment on lines +49 to +53
Copy link
Collaborator

Choose a reason for hiding this comment

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

Similar to my feedback on LETTER_POOL, we can declutter this function by moving LETTER_POINTS outside of the function as a const variable.

bonus_range = [7, 8, 9, 10]
total = sum([LETTER_POINTS[letter] for letter in word.upper()])
Copy link
Collaborator

Choose a reason for hiding this comment

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

LOVELY use of list comprehension here!

if len(word) in bonus_range:
total += 8

return total
Copy link
Collaborator

Choose a reason for hiding this comment

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

This function is so neat, great work!



def get_highest_word_score(word_list):
pass
"""
Score the words in word_list. Returns tuple of word with highest score.
If tie score, word with 10 letters or word with least letters wins.
"""
words_scored_dict = {user_word: score_word(
user_word) for user_word in word_list}

highest_word_score = max(words_scored_dict.values())
smallest_word_len = min((len(key) for key in words_scored_dict.keys()))
largest_word_len = max((len(key) for key in words_scored_dict.keys()))
Comment on lines +71 to +72
Copy link
Collaborator

Choose a reason for hiding this comment

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

keys() can be removed as the default iterator for dicts are its own keys.

Suggested change
smallest_word_len = min((len(key) for key in words_scored_dict.keys()))
largest_word_len = max((len(key) for key in words_scored_dict.keys()))
smallest_word_len = min((len(key) for key in words_scored_dict.keys()))
largest_word_len = max((len(key) for key in words_scored_dict.keys()))

Copy link
Collaborator

Choose a reason for hiding this comment

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

Really cool use of dictionary and list comprehensions!!


for user_word, score in words_scored_dict.items():
if largest_word_len == 10:
if len(user_word) != 10:
continue
elif len(user_word) == 10:
winning_word = user_word
highest_word_score = score
break
Comment on lines +76 to +81
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can take out if len(user_word) != 10 as the loop will continue anyway.

Suggested change
if len(user_word) != 10:
continue
elif len(user_word) == 10:
winning_word = user_word
highest_word_score = score
break
if len(user_word) == 10:
winning_word = user_word
highest_word_score = score
break

elif score == highest_word_score and len(
user_word) == smallest_word_len:
winning_word = user_word
break
elif score == highest_word_score:
winning_word = user_word

return winning_word, highest_word_score
Copy link
Collaborator

Choose a reason for hiding this comment

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

Great work!