lab7¶
count_chars
exercises the use of dictionaries. derivative
uses the concept of finite differences to approximate a differential operator. The newton
function implements a root finding algorithm (and makes use of the derivative
function). The is_palindrome
function exercises string processing. The is_palindrome
function can be implemented using recursion (if you like to learn about this) but there exist other solutions as well.
Relevant Socratica videos:
count_chars(s)
¶
Implement a function count_chars(s)
which takes a string s
and
returns a dictionary. The dictionary’s keys are the set of characters
that occur in string s
. The value for each key is the number of
times that this character occurs in the string s
.
Examples:
In [ ]: count_chars('x')
Out[ ]: {'x': 1}
In [ ]: count_chars('xxx')
Out[ ]: {'x': 3}
In [ ]: count_chars('xxxyz')
Out[ ]: {'x': 3, 'y': 1, 'z': 1}
In [ ]: count_chars('Hello World')
Out[ ]: {'H': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'W': 1, 'r': 1, 'd': 1}
derivative(f, x)
¶
This task has two parts.
Part 1
Write a function derivative(f, x)
which computes a numerical
approximation of the first derivative of the function f(x)
using
central differences. The value that the function returns is
with \(\epsilon=10^{-6}\).
Example:
In [ ]: def f(x):
...: return x * x
In [ ]: derivative(f, 0)
Out[ ]: 0.0
In [ ]: derivative(f, 1)
Out[ ]: 2.0000000000575113
In [ ]: derivative(f, 2)
Out[ ]: 4.000000000115023
Note that you may not get exactly the same numbers as shown above.
Part 2
Modify the derivative
function such that it takes an optional third
parameters eps
to represent the greek letter epsilon
(\(\epsilon\)) in the equation above. The parameter eps
should
default to 1e-6
).
Examples:
In [ ]: import math
In [ ]: derivative(math.exp, 0, eps=0.1)
Out[ ]: 1.000416718753101
In [ ]: derivative(math.exp, 0)
Out[ ]: 1.0000000000287557
In [ ]: derivative(math.exp, 0, eps=1e-6)
Out[ ]: 1.0000000000287557
is_palindrome(s)
¶
Implement a function is_palindrome(s)
which takes a string s
and
returns the value True
if s
is a palindrome, and returns
False
otherwise. (Note that the return value is not the string
“True”
but the special Python value True
— see the section True
and False
in the appendix below. The same applies to False
.)
A palindrome is a word that reads the same backwards as forwards, such as “madam”, “kayak”, “radar” and “rotator”.
Examples:
In [ ]: is_palindrome('rotator')
Out[ ]: True
In [ ]: is_palindrome('radiator')
Out[ ]: False
In [ ]: is_palindrome('ABBA')
Out[ ]: True
We treat small letters (e.g. a
) and capital letters (e.g. A
) as
different letters for this exercise: the string ABba
is thus not a
palindrome.
Hints for implementing a solution (Option 1):
if
s
is an empty string, then it is a palindrome.if
s
is a string with one character, then it is a palindrome.if the first letter of
s
is the same as the last letter ofs
, thens
is a palindrome if the remaining letters ofs
(i.e.s[1:-1]
) are a palindrome. This is algorithm is particularly easy to implement using recursion. (But you can also use a for loop.)Recursion: to learn about recursion, take some time to study the output of this recursive factorial computation in the appendix below. Or check out the first 2 minutes and 40 seconds in this Socratica video on recursion.
Hints for implementing a solution (Option 2):
A completely different strategy would be to create a second string that contains the letters of
s
in reverse orderand compare that second string against
s
.
Appendix¶
True and False¶
True and False are special boolean values (of Python type bool), and different from strings. Here is some demonstration of this:
In [ ]: a = True
In [ ]: b = "True"
In [ ]: type(a)
Out[ ]: bool
In [ ]: type(b)
Out[ ]: str
In the function is_palindrome()
above, you must return the bool
value True
or False
, but not the string “True” or the string
“False”.
Verbose recursive factorial implementation¶
We implement the factorial funcion $f(n) = n!$. We use recursion, i.e. the fact that $f(n) = n * f(n -1)$ and our knowledge that $f(1)=1$.
def f(n):
"""returns n*(n-1)*(n-2)*...*2*1"""
if n == 1:
return 1
else:
return n * f(n-1)
Here is a different implementation that prints more diagnostic output to the screen. Useful to understand how recursion works.
def f(n):
"""returns n*(n-1)*(n-2)*...*2*1
As fsilent(n), but includes many print statements to explain flow of
control"""
print(f"=> Starting f({n})")
if n == 1:
print("if n==1 TRUE => Base case (n==1). Will return 1 and " +
"leave function f(1)")
return 1
else:
print(f"if n==1 FALSE => (n={n}), need to compute n*f(n-1) =" +
f" {n}*f({n-1})")
print(f"Will call f({n-1}) now ...")
tmp1 = f(n-1)
result = tmp1*n
print(f"...returned from calling f({n-1}), back in f({n})")
print(f"Multiply n*f(n-1) = {n}*f({n-1}) = {n}*{tmp1} = {result}," +
f" leaving function f({n})")
return result
# You may want to try different calls here, say f(1), f(2), f(3)
print(f(3))
Please submit your file lab7.py
for this assignment.
Additional (voluntary) tasks are available in lab7-extra.
End of lab7.