Created
September 8, 2018 10:13
-
-
Save nitobuendia/0ea5c5ce0160bf7746f9b999cbc51f54 to your computer and use it in GitHub Desktop.
Code in the Community application exercises.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Asks users for input to generate a list of random numbers and print data.""" | |
import random | |
def _generate_print_message(number_list): | |
"""Generates desired print message based on the sequence list of numbers. | |
Args: | |
number_list: List[int], List of numbers. | |
Returns: | |
str, Desired output message for printing. | |
""" | |
template = ('Sequence: {number_list}\n\n' | |
'List length: {list_length}\n' | |
'Largest integer: {largest_int}\n' | |
'Smallest integer: {smallest_int}\n' | |
'Sum: {sum_int}\n' | |
'Average: {avg_int}') | |
return template.format( | |
number_list=number_list, | |
list_length=len(number_list), | |
largest_int=max(number_list), | |
smallest_int=min(number_list), | |
sum_int=sum(number_list), | |
avg_int=round(sum(number_list) / len(number_list), 2)) | |
def _get_list_length(): | |
"""Asks users for a valid list length. | |
Returns: | |
int, The length of the list. | |
""" | |
valid_input = False | |
while not valid_input: | |
try: | |
input_list_length = input('Please enter the length of the list: ') | |
list_length = int(input_list_length) | |
if input_list_length != list_length: # Will catch 3.2 vs 3. | |
raise ValueError('List must be an integer.') | |
if not (0 < list_length <= 100): | |
raise ValueError('List length must be between than 0 and 100.') | |
except: | |
print('List length must be an integer between 0 and 100.') | |
else: | |
valid_input = True | |
return list_length | |
def _get_max_range(min_range): | |
"""Asks users for a valid max range for the list range. | |
Args: | |
min_range: int, The lower bound for the range. | |
Returns: | |
int, The max range of the list. | |
""" | |
valid_input = False | |
while not valid_input: | |
try: | |
max_range_input = input( | |
'Please enter the upper bound for the range of integer values: ') | |
max_range = int(max_range_input) | |
if max_range_input != max_range: # Will catch 3.2 vs 3. | |
raise ValueError('Upper bound must be an integer.') | |
if max_range_input < min_range: | |
raise ValueError('Upper bound must be greater or equal to lower bound.') | |
except: | |
print('The upper bound must be an integer larger or equal than the ' | |
'lower bound: {min_range}.'.format(min_range=min_range)) | |
else: | |
valid_input = True | |
return max_range | |
def _get_min_range(): | |
"""Asks users for a valid min range for the list range. | |
Returns: | |
int, The min range of the list. | |
""" | |
valid_input = False | |
while not valid_input: | |
try: | |
min_range_input = input( | |
'Please enter the lower bound for the range of integer values: ') | |
min_range = int(min_range_input) | |
if min_range_input != min_range: # Will catch 3.2 vs 3. | |
raise ValueError('List must be an integer.') | |
except: | |
print('The lower bound must be an integer.') | |
else: | |
valid_input = True | |
return min_range | |
def _generate_list_of_random_numbers(list_length, min_range, max_range): | |
"""Generates a list of random numbers. | |
Args: | |
list_length: int, How many numbers to generate. | |
min_range: Optional[int], Minimum possible number. | |
max_range: Optional[int], Maximum possible number. | |
Returns: | |
List[int], List of numbers | |
""" | |
return [random.randint(min_range, max_range) for i in range(list_length)] | |
def main(): | |
"""Main application for CITC application.""" | |
list_length = _get_list_length() | |
min_range = _get_min_range() | |
max_range = _get_max_range(min_range) | |
number_list = _generate_list_of_random_numbers( | |
list_length, min_range, max_range) | |
print_message = _generate_print_message(number_list) | |
print(print_message) | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Implements Shiritori game. | |
Shiritori game is one where the next word must start with the last letter of the | |
previous word. Words must not be repeated. In addition, the word must exist. | |
For validating, we use the list of words on this dictionary: goo.gl/gVEhEX | |
""" | |
import re | |
# Number of rounds before game congratulates you. | |
MAX_ROUNDS = 100 | |
class ShiritoriRuleError(Exception): | |
"""Defines an error caused by violating Shiritori rules.""" | |
pass | |
class NotLastLetterError(ShiritoriRuleError): | |
"""The word did not start with the last letter of the previous word.""" | |
pass | |
class RepeatedWordError(ShiritoriRuleError): | |
"""The word entered was used before.""" | |
pass | |
class NonExistingWordError(ShiritoriRuleError): | |
"""The word entered does not exist on the dictionary.""" | |
pass | |
def _clean_word(word): | |
"""Cleans a word from extra spaces and characters. | |
Args: | |
word: str, Word to clean up. | |
Return: | |
str, Cleaned up word. | |
""" | |
word = word.lower().strip() | |
word = re.sub(r'[^\w\s]', '', word) # Removes punctuation. | |
return word | |
def _load_dictionary(dictionary_file_path = 'word_list.txt'): | |
"""Loads a dictionary to validate words. | |
Words must be in a text file (csv, text) where one word must be placed | |
per line. A dictionary is returned because the look up time is faster than | |
in a list. | |
Args: | |
dictionary_file_path: Optional[str] Path to the dictionary file. | |
Default: word_list.txt | |
Returns: | |
Dict[str, boolean], Hash map where keys exist if the keyword exists. | |
""" | |
dict_file = open(dictionary_file_path, 'r') | |
dictionary = {} | |
for word in dict_file: | |
clean_word = _clean_word(word) | |
dictionary[clean_word] = True | |
dict_file.close() | |
return dictionary | |
def _ask_for_next_word(words_typed, dictionary): | |
"""Asks user for the next word and checks for all the Shiritori rules. | |
Args: | |
words_typed: List[str], List of all the words typed until now. | |
dictionary: Dict[str, bool], Dictionary of existing keywords. | |
Raises: | |
NotLastLetterError: New word does not start with last letter. | |
RepeatedWordError: Word entered has been entered before. | |
NonExistingWordError: Word is not loaded in the dictionary. | |
Returns: | |
List[str], List of all the words typed, including the new one. | |
""" | |
new_word = None | |
while not new_word: | |
new_word = raw_input('Please type a word: ') | |
new_word = _clean_word(new_word) | |
if words_typed: | |
last_word = words_typed[-1] | |
last_last_letter = last_word[-1] | |
new_first_letter = new_word[0] | |
if last_last_letter != new_first_letter: | |
raise NotLastLetterError( | |
'You didn\'t type a word starting with {}.'.format((last_last_letter))) | |
if new_word in words_typed: | |
repeated_round = words_typed.index(next_word) + 1 | |
raise RepeatedWordError( | |
'You typed a word that has been typed before in round {}.'.format( | |
repeated_round)) | |
if new_word not in dictionary: | |
raise NonExistingWordError('You typed a word which does not seem to exist.') | |
words_typed.append(new_word) | |
return words_typed | |
def main(): | |
"""Main application for Shiritori application.""" | |
dictionary = _load_dictionary() | |
words_typed = [] | |
while len(words_typed) < MAX_ROUNDS: | |
try: | |
words_typed = _ask_for_next_word(words_typed, dictionary) | |
except ShiritoriRuleError as error_message: | |
print(error_message) | |
exit() | |
print('CONGRATULATIONS! You beat the game with {} successful words.'.format( | |
MAX_ROUNDS)) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment