\(\renewcommand\AA{\unicode{x212B}}\)

Solutions To Exercises

Exercise 1

  • Write a program that prints out the square of the first 20 integers in a block such that the block is a rectangle of size 4x5. (Hint: One method uses the % (modulo) operator to test if a number is a multiple of another number. The answer is the remainder of the division of the lhs into whole parts, e.g. 4 % 1 = 0, 4 % 2 = 0, 4 % 3 = 1, 4 % 4 = 0)

# Write a program that prints out the square of the first
# 20 integers a block such that the block has a dimension of 4x5.

for i in range(1,21):
    print(str(i*i).center(3),end=' ') # center is a function for strings that centers the contents to the given width
    if i % 4 == 0:
        print()

# ------------ Produces -------------
# 1   4   9   16
# 25  36  49  64
# 81 100 121 144
#169 196 225 256
#289 324 361 400

Exercise 2

  • Write a program that prints out the first 25 Fibonacci numbers. (The Fibonacci sequence starts as with 0,1 and next number is the sum of the two previous numbers)

    • Extend the program to also print the ratio of successive numbers of the sequence.

# prev_2 - One before previous number
# prev_1 - Previous number
prev_2, prev_1 = 0, 1

# Already have first 2 terms above
print(prev_2)
print(prev_1)

# Now the next 23 terms (range(0,23) will run the loop 23 times)
for i in range(0,23):
    current = prev_2 + prev_1
    # Ratio to previous
    ratio = float(current)/prev_1
    print(str(current) + " ratio to previous= " +str(ratio))
    # Move the previous markers along one for the next time around
    prev_2 = prev_1
    prev_1 = current

Exercise 3

  • Starting with your solution to exercise 2, rewrite your code so that you have a function called fib that accepts a number. The function should compute a fibonacci sequence containing this many elements and return them as a list.

# Write a program that builds a list of the first 20 Fibonacci numbers, then
## Use the list to print out the value of the ratio of successive numbers of the sequence,
##   printing out the final value.
## Extend the program so that the Fibonacci list is calculated in a function that takes the
##   number of required values as a parameter and returns the list.

# Function to calculate the first n fibonacci numbers
# and return them as a list
def fib(nfibs):
    if nfibs == 0:
        return []
    elif nfibs == 1:
        return [0]
    else:
        pass
    # First two numbers
    fibs = [0,1]
    if nfibs == 2:
        return fibs
    for i in range(2, nfibs):
        fibs.append(fibs[i-2] + fibs[i-1])
    return fibs

#### fib ends here ####

# Print out successive ratio remembering that the first number is a zero
nfibs = 20
fib_nums = fib(nfibs)
for i in range(1,nfibs):
    try:
        numerator = fib_nums[i]
        denominator = fib_nums[i-1]
        ratio = float(numerator)/denominator
    except ZeroDivisionError:
        print('Warning: Invalid ratio: ' + str(numerator) + '/' + str(denominator))
    else:
        print('Ratio ' + str(numerator) + '/' + str(denominator) + ': ' + str(ratio))

##### Produces #####
#Warning: Invalid ratio: 1/0
#Ratio 1/1:  1.0
#Ratio 2/1:  2.0
#Ratio 3/2:  1.5
#Ratio 5/3:  1.66666666667
#Ratio 8/5:  1.6
#Ratio 13/8:  1.625
#Ratio 21/13:  1.61538461538
#Ratio 34/21:  1.61904761905
#Ratio 55/34:  1.61764705882
#Ratio 89/55:  1.61818181818
#Ratio 144/89:  1.61797752809
#Ratio 233/144:  1.61805555556
#Ratio 377/233:  1.61802575107
#Ratio 610/377:  1.61803713528
#Ratio 987/610:  1.61803278689
#Ratio 1597/987:  1.61803444782
#Ratio 2584/1597:  1.6180338134
#Ratio 4181/2584:  1.61803405573

Exercise 4

  • Write a program that creates a dictionary and initializes it with 5 names/ID pairs.

    • Create a function that prints out the dictionary as a 2 columns: the first being the key and the second the value

    • Update the dictionary with another 5 name/values and reprint the table, making sure you understand the ordering within the map

# Write a program that creates a dictionary and initializes it with 5 names/ID pairs.
## Create a function that prints out the dictionary in a nicely formatted table;
## Update the dictionary with another 5 name/values and reprint the table,
##   making sure you understand the ordering within the map.

def formatLine(cola, colb, width):
    return cola.center(width) + '|' + colb.center(width)

# A simple two cloumn print out
def outputStore(store):
    print('Phonebook contains {} entries:'.format(len(store)))

    # Do a quick sweep to find out the longest name
    col_width = 0
    for k in store:
        if len(k) > col_width:
            col_width = len(k)
    col_width += 5

    # Header
    print('-'*col_width*2)
    print(formatLine('Name', 'Ext.', col_width))
    print('-'*col_width*2)
    for k ,v in store.items():
        print(formatLine(k, str(v), col_width))

phone_book = {'Martyn Gigg' : 1234, 'Joe Bloggs' : 1233, 'Guido Van Rossum' : 4321, 'Bob' : 2314, 'Linus Torvalds' : 4132 }
outputStore(phone_book)

# Update Dictionary (replacing one person's phone number
new_entries = {'Bjarne Strousoup' : 9876, 'Bill Gates' : 9898, 'Steve Jobs' : 7898, \
              'Bob' : 9871, 'Dave' : 7098 }

phone_book.update(new_entries)
outputStore(phone_book)

#------------- Produces --------------------

#Phonebook contains 5 entries:
#------------------------------------------
#         Name        |         Ext.
#------------------------------------------
#         Bob         |         2314
#      Joe Bloggs     |         1233
#    Linus Torvalds   |         4132
#   Guido Van Rossum  |         4321
#     Martyn Gigg     |         1234
#Phonebook contains 9 entries:
#------------------------------------------
#         Name        |         Ext.
#------------------------------------------
#   Guido Van Rossum  |         4321
#     Martyn Gigg     |         1234
#      Steve Jobs     |         7898
#   Bjarne Strousoup  |         9876
#      Joe Bloggs     |         1233
#    Linus Torvalds   |         4132
#         Dave        |         7098
#      Bill Gates     |         9898
#         Bob         |         9871

Exercise 5

  1. Build a list containing the 5 filenames of the text files that are going to be used. (Hint: Can be done by hand or using the os.listdir(‘dirpath’) function in the os module)

  2. Add a bogus file name that doesn’t exist to the list (so that we have to do some error handling)

  3. Loop over the list and for each file (Remember here that we have a non existent file in the list and calling open on this will result in an IOError exception that needs to be dealt with)

    1. Open the file;

    2. Loop over each line;

    3. Split the line up into sections (Hint: The string has a .split() function that splits the string on whitespace and gives back a list with each section as an element of the list)

    4. Convert the second column value into an float

    5. Keep track of the values for each line and compute an average for the file.

  4. Finally, print out a list of file,average-value pairs

## Exercise 5
#   1.  Build a list containing the 5 filenames of the text files that are going to be used.
#       (Hint: Can be done by hand or using the os.listdir() function in the os module)
#   2. Add a bogus file name that doesn't exist to the list (so that we have to do some error handling)
#   3. Loop over the list and for each file (Remember here that we have a non existent file in the list and calling open
#      on this will result in an IOError exception that needs to be dealt with)
#         1. Open the file;
#         2. Loop over each line;
#         3. Split the line up into sections (Hint: The string has a .split() function that splits the string on
#            whitespace and gives back a list with each section as an element of the list)
#         4. Convert the second column value into an integer
#         5. Keep track of the values for each line and compute an average for the file.
#   4. Finally, print out a list of file,average-value pairs
import os

file_dir = "C:\\MantidInstall\\data\\"
file_names = os.listdir(file_dir)
file_names.append('nonexistant.txt')
average_store = {}
print('Computing average for log files in directory "' + file_dir + '"')
for name in file_names:
    # Skip all no text files
    if name.endswith('.txt') == False:
        continue
    try:
        file_handle = open(os.path.join(file_dir,name), 'r')
    except IOError:
        print('\tError: No such file: "' + name + '". Skipping file')
        continue
    print('\tReading file',name)
    # At this point we have an open file
    average = 0.0
    nvalues = 0
    line_counter = 1
    for line in file_handle:
        columns = line.split()
        if len(columns) == 2:
            average += float(columns[1])
            nvalues += 1
        else:
            print('\tWarning: Unexpected file format encountered in file {0}  on line {1}'.format(name,line_counter))
        line_counter += 1

    average /= nvalues
    average_store[name] = average
    file_handle.close()

# Print out file averages
column_width = 30
print('')
print('-'*column_width*2)
print('File'.center(column_width) + '|' + 'Average'.center(column_width))
print('-'*column_width*2)
for key, value in average_store.items():
    print(key.center(column_width) + '|' + str(value).center(column_width))