When we compute interest that is compounded daily, or population growth based on average daily changes, we need to know if a year is a leap year or not. In our calendar, a leap year is divisible by 4. However, years divisible by 100 are not leap years, with one exception: years divisible by 400 are leap years.
Write a Python function named is_leap_year() that takes a year as an argument and returns true or false as its value.
Does this work?
def is_leap_year(year):
if year % 4 == 0:
return True
if year % 100 == 0:
return False
if year % 400 == 0:
return True
return False
Why not? We have to handle the special cases first, because otherwise the normal cases return the wrong answer. Here is one solution, plus a loop for demonstrating the function. In what other ways could we have written the function?
I have tired of writing and reading the a % b == 0 construction...
Write a Python function named divisible_by() that takes a number and a divisor as arguments and returns true if the number is evenly divisible by the divisor, and false otherwise.
That's straightforward:
def divisible_by(number, divisor):
return number % divisor == 0
Why bother? Because now we can write is_leap_year() in a way that resembles the English definition:
def is_leap_year(year):
return divisible_by(year, 400) or \
divisible_by(year, 4) and not divisible_by(year, 100)
Recall the description of a function as conceptually, a single operation. Functions let us turn ideas in the problem space into named operations in our programs. The result can be code that is easier to read!
The problem of Section 6.3.4, given on Page 267:
Find a word that contains the vowels a, e, i, o, and u in that order.
To solve this word puzzle, we need a list of words.
Now we are ready to solve the problem, but how?
big task
algorithm
for every word in the dictionary
if the word contains 'aeiou' in order
print the word
issues
- lines read from file contain \n
- some words are capitalized
- any word with fewer than five characters
can't be a solution
improved algorithm
for every word in the dictionary
scrub the word
if it has fewer than five characters
ignore the word
if the word contains 'aeiou' in order
print the word
ideally, our program will look like this!
the code for
scrub the word
and
if the word contains 'aeiou' in order
will be complex enough to obscure the algorithm
so write functions for them!
- scrub(word) → same word, no caps, no whitespace
- contains(word, char_list) → true or false
First pass:
word_source = open ('dictionary.txt', 'r')
for word in word_source:
word = scrub(word)
if len(word) < 5:
continue
if contains(word, 'aeiou'):
print(word)
Now write scrub(word).
And write contains(word,char_list).
select desired characters from the word
return the word contains the desired characters in order
so write a functions for it
- find_all_in(desired_chars, word) → list of chars
in word that match any char in desired_chars
This gives us word_puzzle.py. Our dictionary has several more matches ('abstemious', 'arsenious', 'caesious'), plus a few words that contain more vowels, as long as 'aeiou' appear in order ('facetiousness', 'nonabstemious').
No return? A procedure. Python does return a 'special' value. But we don't care. We use procedures for their effect.
Many returns? The first one executed causes the function to stop and return. Make sure if has an else, for a default case, or a 'backstop'.