Writing Algorithms using Python Constructs

Arithmetic Operations

Divide and “take the floor” with the // operator

Taking the floor” of a number and truncating it are the same for positive numbers:

In: 5/2
Out: 2.5

In: 5//2
Out: 2

In: math.trunc(5/2)
Out: 2

The floor rounds it toward negative infinity and truncating rounds toward zero.

When the numbers are negative, taking the floor and truncating aren’t the same:

In: -5/2
Out: -2.5

In: -5//2
Out: -3

In: math.trunc(-5/2)
Out: -2

When you need to round toward positive infinity, you can “take the ceiling”:

In: 5/2
Out: 2.5

In: math.ceil(5/2)
Out: 3

In: math.ceil(-5/2)
Out: -2

Control Flow

Check conditions in order and select the first true one with if … elif … elif …

When the conditions are mutually exclusive and exhaustive, it’s easy to reason about:

In:
output = [] 
for x in range(1, 5):
    if x % 3 == 0:
        output.append("Fizz")
    elif x % 3 != 0:
        output.append("not Fizz")

Out: ['not Fizz', 'not Fizz', 'Fizz', 'not Fizz']

When the conditions aren’t mutually exclusive, the order of the conditions matters:

In:
output = [] 
for x in range(12, 16):
    if x % 3 == 0:
        output.append("Fizz")
    elif x % 5 == 0:
        output.append("Buzz")
    else:
        output.append(str(x))

Out: ['Fizz', '13', '14', 'Fizz']
In:
output = [] 
for x in range(12, 16):
    if x % 5 == 0:
        output.append("Buzz")
    elif x % 3 == 0:
        output.append("Fizz")
    else:
        output.append(str(x))

Out: ['Fizz', '13', '14', 'Buzz']

When the conditions are reordered, the output for x=15 changes from Fizz to Buzz.

Note the use of the else clause to make the if … elif … elif … construct exhaustive.

To make overlapping conditions easier to reason about, we can explicitly enumerate them using logical operators:

In:
output = [] 
for x in range(12, 16):
    if (x % 3 == 0) and (x % 5 == 0):
        output.append("FizzBuzz")
    elif (x % 3 == 0) and (x % 5 != 0):
        output.append("Fizz")
    elif (x % 5 == 0) and (x % 3 != 0):
        output.append("Buzz")
    else:
        output.append(str(x))

Out: ['Fizz', '13', '14', 'FizzBuzz']

If the overlapping conditions have a natural ordering, we can order them from most to least specific:

In:
x = 10

if x > 20:
    print("x is greater than 20")
elif x > 10:
    print("x is greater than 10")
elif x > 0: 
    print("x is positive")
else:
    print("x is non-positive")

Out: x is positive

Note that list.insert(i,x) inserts x before index i

In: cubes = [1, 8, 27, 65, 125]

In: cubes.append(6**3)
Out: [1, 8, 27, 65, 125, 216]

In: cubes.insert(len(cubes), 7**3)
Out: [1, 8, 27, 65, 125, 216, 343]

In: cubes.insert(0,0**3)
Out: [0, 1, 8, 27, 65, 125, 216, 343]

In: cubes.pop()
Out: [0, 1, 8, 27, 65, 125, 216]

In: cubes.pop(0)
Out: [1, 8, 27, 65, 125, 216]