$$\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

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