Prev - #25 Multiplication Table | Table of Contents | Next - #27 Rectangle Drawing
There is only one handshake that can happen between two people.
Between three people, there are three possible handshaking pairs. Between four
people, there are six handshakes; five people, ten handshakes, and so on. This
exercise explores the full range of possible handshaking combinations with
nested for
loops.
Exercise Description
Write a function named printHandshakes()
with a list parameter named people
which will be a list
of strings of people’s names. The function prints out 'X
shakes hands with Y', where X and Y are every possible pair of
handshakes between the people in the list. No duplicates are permitted: if
“Alice shakes hands with Bob” appears in the output, then “Bob shakes hands
with Alice” should not appear.
For example, printHandshakes(['Alice', 'Bob', 'Carol', 'David']) should print:
Alice shakes hands with Bob
Alice shakes hands with Carol
Alice shakes hands with David
Bob shakes hands with Carol
Bob shakes hands with David
Carol shakes hands with David
The printHandshakes()
function must also
return an integer of the number of handshakes.
These Python assert
statements stop
the program if their condition is False
. Copy them
to the bottom of your solution program. Your solution is correct if the output
displays all possible handshakes and the following assert
statements’ conditions are all True
:
assert printHandshakes(['Alice', 'Bob']) == 1
assert printHandshakes(['Alice', 'Bob', 'Carol']) == 3
assert printHandshakes(['Alice', 'Bob', 'Carol', 'David']) == 6
Try to write a solution based on the information in this description. If you still have trouble solving this exercise, read the Solution Design and Special Cases and Gotchas sections for additional hints.
Prerequisite concepts: for
loops, range() with two arguments, len()
,
augmented assignment operators
Solution Design
We need a pair of nested for
loops to
obtain the pairs of people in each handshake. The outer for
loop iterates over each index in the person list for the first handshaker, and
the inner for
loop iterates over each index in the
person list after the outer loop’s index.
The pattern behind the movements of i
and j
are easier to see when visually laid out, as
in Figure 26-1, which uses a 5-item people
list as
an example. The indexes i
and j
refer to the two people in the handshake:
Figure 26-1: The pattern of i and j’s movement.
As the algorithm runs, j
starts after i and moves to the right, and when it reaches the end, i moves right once and j
starts
after i
again. In the above example with 5 people
(indexes 0
to 4
) i starts at 0
and j starts at i + 1
, or 1. The j
variable increments
until it reaches 4
, at which point i increments to 1
and j resets back to i + 1
, which
is now 2
.
If you look at the overall range of i
and j
, you’ll see that i
starts at index 0
and ends at the second to last
index. Meanwhile, j
starts at the index after i and ends at the last index. This means our nested for loops over the people
list
parameter would look like this:
for i in range(0, len(people) - 1):
for j in range(i, len(people)):
This solution is identical to the nested for
loops in Exercise #42, “Bubble Sort.”
Special Cases and Gotchas
The most common mistake you want to avoid is having repeated
handshakes. This can happen if your nested for
loops
cover the full range of indexes in the people list like so:
for i in range(0, len(people)):
for j in range(0, len(people)):
In this case, i
and j would run with each pair twice: for example, the first
time with people[i]
as the first handshaker and people[j] as the second handshaker, and then with people[i] as the second handshaker and people[j] as the first handshaker.
Now try to write a solution based on the information in the previous sections. If you still have trouble solving this exercise, read the Solution Template section for additional hints.
Solution Template
Try to first write a solution from scratch. But if you have difficulty, you can use the following partial program as a starting place. Copy the following code from https://invpy.com/handshake-template.py and paste it into your code editor. Replace the underscores with code to make a working program:
def printHandshakes(people):
# The total number of handshakes starts at 0:
numberOfHandshakes = ____
# Loop over every index in the people list except the last:
for i in range(0, len(____) - 1):
# Loop over every index in the people list after index i:
for j in range(i + ____, len(____)):
# Print a handshake between the people at index i and j:
print(people[____], 'shakes hands with', people[____])
# Increment the total number of handshakes:
numberOfHandshakes += ____
# Return the total number of handshakes:
return numberOfHandshakes
The complete solution for this exercise is given in Appendix A and https://invpy.com/handshake.py. You can view each step of this program as it runs under a debugger at https://invpy.com/handshake-debug/.
Prev - #25 Multiplication Table | Table of Contents | Next - #27 Rectangle Drawing