Skip to content
Open
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
153 changes: 149 additions & 4 deletions adagrams/game.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,156 @@
from operator import le

Choose a reason for hiding this comment

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

It looks like le, which is part of this import statement never got used. Most likely this is because of a "helpful" VSCode feature that will attempt to add import statements for you automatically, but often just cause problems. I would recommend just turning it off. Ansel provided these steps:

  1. Open the Settings screen, by either going to the Code > Preferences > Settings menu pick, or using the ⌘, keyboard shortcut.
  2. In the Search settings, look for: analysis.
  3. Look for a result titled Python > Analysis: Auto Import Completions.
  4. Uncheck the option to Offer auto-import completions.

import random
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
}
SCORE_CHART = {
'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
}
def create_bag_of_letters():
"""
Returns an array containing all the letters of the "LETTER_POOL" dictionary
according to the frequency associated with each letter.
Ex: Since the value of 'A' is 9, the first 9 elements of this list will be 'A'
appearing 9 times, and so on.
bag_of_letters = ['A', 'A', ..., 'B', ...]
"""

Choose a reason for hiding this comment

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

Ooh, nice docstring, and good use of adding a helper function!

bag_of_letters = []
for letter in LETTER_POOL:
number_of_letters = LETTER_POOL[letter]
for i in range(number_of_letters):
bag_of_letters.append(letter)
return bag_of_letters

def draw_letters():

Choose a reason for hiding this comment

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

This looks good, I just have a few style notes!

pass
hand_of_letters = [] # to be filled with 10 one-letter strings

Choose a reason for hiding this comment

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

Minor style preference: I'm not sure there's much value to this type of comment. It is more about "what" the code will do rather that "why" it will do it a certain way. I generally recommend removing "what" comments because the true marker of what the code does is the code itself. Additionally, these types of comments often fall out of sync with the code they're commenting.

It's generally OK to use them when scaffolding, but once your code is there, you can remove them.

bag_of_letters = create_bag_of_letters()

for i in range(10):
#size_of_letter_bag = len(bag_of_letters)

Choose a reason for hiding this comment

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

Minor style preference: Building on to that, I would normally remove commented code just to keep things clean.

letter_picked = random.choice(bag_of_letters)
hand_of_letters.append(letter_picked)
bag_of_letters.remove(letter_picked)

return hand_of_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.

This looks good, one minor style comment!

pass
copy_of_letter_bank = list(letter_bank)
upper_case_word = word.upper()
#We checked to make sure that removing wouldn't affect original letter_bank array here:
# copy_of_letter_bank.remove('B')
# print("letter bank:", letter_bank)
#print("copy of letter bank:" , copy_of_letter_bank)

Choose a reason for hiding this comment

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

Minor style preference: Much as I said in the last function, there's not as much benefit to keeping this type of "exploratory" code in, even while commented after y'all figure it out. That being said, writing a bit of code like this to figure things out is a really good tendency to have! Just, don't keep it in. :3

Choose a reason for hiding this comment

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

There are some other places with commented code, but from here on out, I'll skip pointing it out to not repeat myself.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for pointing this out! As you mentioned, this was mostly used as scaffolding for writing the code itself, but I will remove in final submissions moving forward! :)


for character in upper_case_word:
if character in copy_of_letter_bank:
copy_of_letter_bank.remove(character)
else:
return False

return True


def score_word(word):

Choose a reason for hiding this comment

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

This looks fine!

pass
final_score = 0
upper_case_word = word.upper()
for char in upper_case_word:
final_score += SCORE_CHART[char]
if len(word) > 6 and len(word) < 11:
final_score += 8
return final_score


def get_highest_word_score(word_list):

Choose a reason for hiding this comment

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

OK, I really like this implementation! I feel that some people would find the use of a dictionary here to keep track the important information for each word was overkill, but I think it serves a very good method for organizing the calculations and making it easier to work with for pretty minimal extra memory usage. (Not going to lie, by "some people" I mean me, because I was about to comment on it until I understood y'all's logic.)

Otherwise, I did have a small style comment...

pass
word_info = []
for word in word_list:
word_dict = {}
word_dict["word"] = word
word_dict["score"] = score_word(word)
word_dict["length"] = len(word)
word_info.append(word_dict)

max_words = []
max_score = 0

for word_dict in word_info:
if word_dict["score"] == max_score:
max_words.append(word_dict["word"])
elif word_dict["score"] > max_score:
max_score = word_dict["score"]
max_words.clear()
max_words.append(word_dict["word"])
# CASE 1

Choose a reason for hiding this comment

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

While I am not sure y'all need this comment or the one below in general, this comment is pretty terse. That is, "CASE 1" doesn't really tell me what case 1 actually means. So something like # CASE 1: No tied scores would be better. At the same time, that is right on the border of "what" and "why" as far as comments go and I say it's more on the "what" side, and thus wouldn't bother keeping it. (Usually the tone of my "why" comments are like "I had to code it this terrible way no one should have to code it because of this annoying reason".)

Plus, this is very minor, but make sure to keep your comments indented with what they're commenting just because with Python using indentation to mark blocks, the indentation of everything is a large part of understanding code written in it.

Copy link
Author

Choose a reason for hiding this comment

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

Thank you for all the great feedback! I learned a lot about commenting etiquette 💬 😸

if len(max_words) == 1:
return (max_words[0], score_word(max_words[0]))

# CASE 2

min_letter_count = 10
shortest_word = None

for word in max_words:
if len(word) == 10:
return (word, score_word(word))
elif len(word) < min_letter_count:
min_letter_count = len(word)
shortest_word = word
return (shortest_word, score_word(shortest_word))

# word_info:
# {“word”: word,
# “Score”: score_word(word),
# “Length”: len(word)
# }

#hand = ['S', 'B', 'E', 'T', 'R','E' , 'Z', 'A', 'L', 'M']
#uses_available_letters("TREE", hand)