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

C19 - Amber Shay #112

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open

C19 - Amber Shay #112

wants to merge 13 commits into from

Conversation

Maashad
Copy link

@Maashad Maashad commented Mar 24, 2023

No description provided.

Copy link

@spitsfire spitsfire left a comment

Choose a reason for hiding this comment

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

Nicely done, Amber! Below is some feedback and suggestions. The one pattern I saw was having several nested loops in your functions. This takes practice to catch, but if you do see you've got more than 2 nested loops, consider refactoring!

Also, great job using docstrings to summarize your function's utility!

letters = []

while len(letters) < 10:
letter_key = random.choice(list(letter_pool_copy.keys()))

Choose a reason for hiding this comment

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

Nice idea! One thing to consider: should each letter have the same probability of being chosen, though? For example, should "Z" have a probability of 1 in 26 or 1 in 98 (the total amount of tiles that can be drawn)?

How could we represent that in a data structure? Maybe a list of all tiles and their duplicates (ie, ['A','A','A','B','B'] and so on) to randomly choose from.

A more advanced solution might be using the random.choice method, but with more than one param. Here's an example of how you can "weigh" your string or list: https://www.geeksforgeeks.org/how-to-get-weighted-random-choice-in-python/

letter_bank_case = [element.upper() for element in letter_bank_copy]

for letter in word.upper():
letter.upper()

Choose a reason for hiding this comment

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

We don't need this a second time. The letter value will be uppercase already because of word.upper()

Suggested change
letter.upper()

Comment on lines +65 to +66
letter_bank_copy = letter_bank.copy()
letter_bank_case = [element.upper() for element in letter_bank_copy]

Choose a reason for hiding this comment

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

Consider combining these into one! Line 65 is not making a true copy of letter_bank. copy makes a "shallow" copy that still points to the original reference IDs of the items inside the list. Let's refactor line 66 a bit:

    letter_bank_copy = [element.upper() for element in letter_bank.deepcopy()]

This would now make a "deep" copy of each value in the list, and then convert each value to its uppercase in memory,.

Comment on lines +82 to +83
for letter in word:
letter = letter.upper()

Choose a reason for hiding this comment

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

Let's combine these lines:

for letter in word.upper():

letters.append(letter_key)

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.

This works fine! We've only just talked about Big O and time/space complexity, but one thing to notice here is we have a 3 nested for loops, even if we haven't explicitly stated for___ in ___ three times.

The remove method loops through letter_bank_case and if letter in letter_bank_case loops under the hood. Nothing wrong with 2 nested for loops. At times they are the easier solution. But! we have 3 here, and a dictionary of letters counted from the letter_bank_case would help us here.

How might we create a "frequency map" (a dictionary of items counted) with a constant lookup (O(1)) of letters found in letter_bank_case, then use it to check if all those letters are in the word?

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.

Here again we've got 3 nested loops. Let's refactor the letter_value dictionary so that each letter is its own key. Is there some overhead setting that up? Yes. But it would also let us look up a letter's score in "constant" time (letter in score_dict) rather than iterating through an entire list, which is "linear" time (O(n)) (letter in ['A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T']).

Again, we only just discussed time complexity and Big O, but that's a brief explanation as to why a dictionary is a beneficial data structure we can use to hold data that needs to be frequently looked up.

for word in word_list:
score = score_word(word)
print(f'word: {word}, score: {score}')

Choose a reason for hiding this comment

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

Don't forget to remove any print statements that are for debugging purposes when you submit a final project!

Suggested change
print(f'word: {word}, score: {score}')

winning_word = ""

for word in word_list:

Choose a reason for hiding this comment

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

👍 Your conditional statements are well organized and easy to read! Good job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants