Skip to content

Instantly share code, notes, and snippets.

@nitobuendia
Created September 8, 2018 10:13
Show Gist options
  • Save nitobuendia/0ea5c5ce0160bf7746f9b999cbc51f54 to your computer and use it in GitHub Desktop.
Save nitobuendia/0ea5c5ce0160bf7746f9b999cbc51f54 to your computer and use it in GitHub Desktop.
Code in the Community application exercises.
"""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()
"""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