Prev - #25 Multiplication Table | Table of Contents | Next - #27 Rectangle Drawing

Exercise #26: Handshakes

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