## Session 19

### Quick Exercise

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?

• Can we eliminate the elif clause?
• Can we eliminate the uses of True and False?

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!

### A Look at Functions

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.

• Unix systems have one...
• On Mac OS X, and the Debian system that runs the department web server, the standard is /usr/share/dict/words.
• Today's code directory contains a copy of that file in dictionary.txt.

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).

• Only one line, but still valuable!

And write contains(word,char_list).

• How to solve? Break down further!
```    select desired characters from the word
return the word contains the desired characters in order
```
• "Select desired characters" is another high-level operation.
```    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').

### Returning from a Function

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'.

### Wrap Up

• Code -- today's code file, including a long word list

• Reading -- Review Chapter 6 one last time. You will see details you missed the first time, and those can make you a better programmer.

• Homework -- Homework 8 is available and due in about a week.

Eugene Wallingford ..... wallingf@cs.uni.edu ..... October 28, 2014