Skip to content

Tigers - Mica C. and Lain #64

Open
allcomputersarebad wants to merge 22 commits intoAda-C18:masterfrom
mc-dev99:master
Open

Tigers - Mica C. and Lain #64
allcomputersarebad wants to merge 22 commits intoAda-C18:masterfrom
mc-dev99:master

Conversation

@allcomputersarebad
Copy link
Copy Markdown

@allcomputersarebad
Copy link
Copy Markdown
Author

note tests fail due to use of counts= named parameter of random.sample, which was added in python version 3.9

Copy link
Copy Markdown

@chimerror chimerror left a comment

Choose a reason for hiding this comment

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

Good work!

I really appreciate y'all's succinctly written code while still being very readable, as well as a correct implementation of the requirements. I do make a few comments about what I think are performance issues, but in one case there's an argument in favor of y'all's implementation, and in the other a simple fix. I think I also make some positive comments with slight quibbles about readability.

Comment thread adagrams/game.py
}


def draw_letters():
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This looks fine, good use of library functions and built-in operators! No comments.

Comment thread adagrams/game.py
return sample(pool, k=10)


def uses_available_letters(word, letter_bank):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is a fine implementation very succinct and pythonic, though there's a slight time performance hit from using count...

Comment thread adagrams/game.py
upper_word = word.upper()
return all(
upper_word.count(letter) <= letter_bank.count(letter)
for letter in set(upper_word)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

From my investigations, count takes O(n) time as the implementation goes through each element of the list and just counts up. The for generator runs over set(upper_word), which at worst has n elements (n being the number of letters in word) if every letter in word is different. Thus O(n^2) in the end for time complexity.

A common way to implement this function is to create frequency dictionaries of either or both word and letter_bank (each likely taking a separate O(n) for loop) and then compare the counts, which could also be done in an O(n) loop. Since none of these loops are nested, the entire implementation takes O(n).

However, by creating the dictionaries, we are also using O(n) space, while the big benefit of generators is that they don't need to allocate space, making y'all's implementation O(1). Which could very well be worth the worse time complexity! Trade-offs abound.

Comment thread adagrams/game.py
)


def score_word(word):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is also a very fine succinct and pythonic implementation, but I think then we get a space performance issue this time...

Comment thread adagrams/game.py

def score_word(word):
pass
total_score = sum([LETTER_POINTS.get(letter, 0) for letter in word.upper()])
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

In this case rather than a generator, y'all used a comprehension (due to the square brackets), which does end up allocating O(n) memory (apparently even if you never assign it, sadly). However, I just tested and y'all could just switch to a generator here and get O(1) space complexity!

Great since this is so succinct and clean and I do really value that!

Comment thread adagrams/game.py
def score_word(word):
pass
total_score = sum([LETTER_POINTS.get(letter, 0) for letter in word.upper()])
total_score += len(word) > 6 and 8
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good use of the short-circuiting behavior of and as well as the integer representation of False as 0. I could quibble about readability, but these behaviors are common enough knowledge it's not that big a deal to me.

Comment thread adagrams/game.py
return total_score


def break_tie(words):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Woo, helper functions!

Comment thread adagrams/game.py


def break_tie(words):
return min(words, key=lambda w: 0 if len(w) == 10 else len(w))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

And this is so good and succinct to account for all tiebreakers and verifying that min (and its siblings) pick the first encountered matching value it does indeed meet all the tie breaking rules.

Nice work!

Comment thread adagrams/game.py
return min(words, key=lambda w: 0 if len(w) == 10 else len(w))


def get_highest_word_score(word_list):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nice and succinct as all the rest of the code has been while still being correct. No comments.

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.

3 participants