Here are our solutions for the day 25 exercises in the 30 Days of Python series. Make sure you try the exercises yourself before checking out the solutions!
1) Write a function that prompts the user for their name and then greets them. If after processing the string you're left with an empty string, the function should replace the empty string with "World" in the output.
Let's start by defining our function.
def greeter():
pass
The first thing we need to put in the function body is our input
call to grab the user's name. I'm going to process the string all on the same line.
def greeter():
name = input("Please enter your name: ").strip().title()
The only thing left to do is print the greeting. We can use or
directly in our f-string to change the output depending on whether or not name
ended up as an empty string.
def greeter():
name = input("Please enter your name: ").strip().title()
print(f"Hello, {name or 'World'}!")
Be careful not to use the same type as quotes inside the curly braces as you used for the outer string. If you do, you'll terminate your string early and it will lead to an error.
2) Write a function to determine whether or not a string contains exclusively ASCII letters.
Once again, let's start by defining the skeleton of our function.
def is_ascii_letters(test_string):
pass
For this exercise, I think our best approach is going to be importing the string
module and making use of the string constants defined inside. There is one called ascii_letters
which includes all uppercase and lowercase ASCII letters, which is exactly what we want.
We can then loop over the test_string
and check if a given character is in ascii_letters
. If we find a character which isn't in this string constant, we can return False
right away.
from string import ascii_letters
def is_ascii_letters(test_string):
for character in test_string:
if character not in ascii_letters:
return False
else:
return True
Note that we're using an else
clause with the for
loop here, not with the conditional statement inside the loop. We talked about this back in day 8.
This is a perfectly fine solution, but we don't need to implement such a verbose loop structure like this. Instead, we can use the all
function in combination with a generator expression.
from string import ascii_letters
def is_ascii_letters(test_string):
return all(character in ascii_letters for character in test_string)
This is functionally identical, but written with some of the more advanced tools we've learnt in the last week of the course.
3) Use the sample
function in the random
module to create three lists, each containing fifteen numbers from 1
to 100
(inclusive). Sort each of these lists into descending order (largest first), and then truncate each list so that only 5 items remain in each.
Let's start by importing sample
and generating our initial lists of numbers. The sample
function expected a population and as well as a value representing how many numbers it should select from the population. The population needs to be a sequence, so we can provide a range
.
import random
numbers = [random.sample(range(1, 101), 15) for _ in range(3)]
This is a fairly dense line of code, but I think it's still readable enough. If you like, you could extract the population to a variable so we don't have ranges all over the place in our comprehension.
import random
population = range(1, 101)
numbers = [random.sample(population, 15) for _ in range(3)]
Our next step is to sort the lists we get back from sample
. We can use the sorted
function as part of the comprehension to do this all in one step.
Since we want the numbers in descending order, we need to provide a value for the reverse
parameter, passing in True
.
import random
population = range(1, 101)
numbers = [sorted(random.sample(population, 15), reverse=True) for _ in range(3)]
However, I think this is getting a bit too much for a comprehension, and we're about to iterate over this collection with a for
loop anyway.
Instead I would use the sort
method like this:
import random
population = range(1, 101)
numbers = [random.sample(population, 15) for _ in range(3)]
for number_set in numbers:
number_set.sort(reverse=True)
Once again we need to remember to pass in a value for reverse
so that the list is sorted in descending order.
Now we can use del
and the slice syntax to truncate the lists as part of the same loop.
import random
population = range(1, 101)
numbers = [random.sample(population, 15) for _ in range(3)]
for number_set in numbers:
number_set.sort(reverse=True)
del number_set[5:]
If we now print numbers
, we should have three lists that have the highest five numbers in each.