# 12.17. Exercises¶

1. Write a function named num_test that takes a number as input. If the number is greater than 10, the function should return “Greater than 10.” If the number is less than 10, the function should return “Less than 10.” If the number is equal to 10, the function should return “Equal to 10.”

2. Write a function that will return the number of digits in an integer.

3. Write a function that reverses its string argument.

4. Write a function that mirrors its string argument, generating a string containing the original string and the string backwards.

5. Write a function that removes all occurrences of a given letter from a string.

6. Although Python provides us with many list methods, it is good practice and very instructive to think about how they are implemented. Implement a Python function that works like the following:

1. count

2. in

3. reverse

4. index

5. insert

7. Write a function replace(s, old, new) that replaces all occurences of old with new in a string s:

test(replace('Mississippi', 'i', 'I'), 'MIssIssIppI')

s = 'I love spom!  Spom is my favorite food.  Spom, spom, spom, yum!'
test(replace(s, 'om', 'am'),
'I love spam!  Spam is my favorite food.  Spam, spam, spam, yum!')

test(replace(s, 'o', 'a'),
'I lave spam!  Spam is my favarite faad.  Spam, spam, spam, yum!')


Hint: use the split and join methods.

8. Write a Python function that will take a the list of 100 random integers between 0 and 1000 and return the maximum value. (Note: there is a builtin function named max but pretend you cannot use it.)

9. Write a function sum_of_squares(xs) that computes the sum of the squares of the numbers in the list xs. For example, sum_of_squares([2, 3, 4]) should return 4+9+16 which is 29:

10. Write a function to count how many odd numbers are in a list.

11. Sum up all the even numbers in a list.

12. Sum up all the negative numbers in a list.

13. Write a function findHypot. The function will be given the length of two sides of a right-angled triangle and it should return the length of the hypotenuse. (Hint: x ** 0.5 will return the square root, or use sqrt from the math module)

14. Write a function called is_even(n) that takes an integer as an argument and returns True if the argument is an even number and False if it is odd.

15. Now write the function is_odd(n) that returns True when n is odd and False otherwise.

16. Write a function is_rightangled which, given the length of three sides of a triangle, will determine whether the triangle is right-angled. Assume that the third argument to the function is always the longest side. It will return True if the triangle is right-angled, or False otherwise.

Hint: floating point arithmetic is not always exactly accurate, so it is not safe to test floating point numbers for equality. If a good programmer wants to know whether x is equal or close enough to y, they would probably code it up as

if  abs(x - y) < 0.001:      # if x is approximately equal to y
...


## 12.17.1. Contributed Exercises¶

Define a function called draw(turtle, shape, length). If shape is “square”, use turtle to draw a square with side equal to length. If shape is “triangle”, draw an equilateral triangle with side equal to length. Otherwise, draw nothing. The turtle should face in the same position after draw is done. The function may return whatever you like. Example usage: draw(myturtle, "triangle", 20).
Use the functions square_list and graph to draw the graph of a parabola: that is, [1,2,3,4] on the x axis, and [1,4,9,16] on the y axis.
Define a function graph(x_list,y_list) which takes two lists and uses Altair to make a point graph of the x_list versus the y_list.
Define a function graph(x_list,y_list) which takes two lists and uses Altair to make a point graph of the x_list versus the y_list.

Implement a function called pow_answer that has 2 parameters, base and exponent. The function computes the value of the base to the power of the exponent. It then returns a friendly answer For example, calling pow_answer(2, 3) returns: Value of 2 to the power of 3 is 8

Write a function named generate_odd_numbers that will generate a list containing every odd number between 0 and a number specified by the user, excluding the user-specified number. The function must return the generated list.

Write a function named average_odd_list that will return the average of the odd numbers between 0 and a number specified by the user, excluding the user-specified number. The function must return the average.

The average_odd_list function must make use of the generate_odd_numbers function from the wvu_functions_createlist question. You may copy-and-paste the source code for that function here.

Variance can be calculated as (∑(x−x̄)²)/n, where is the average of all x and n is the count of how many x there are.

Standard deviation is the square root of variance.

Write a function named variance that will return the variance of a list. Write a second function named stdev that will return the standard deviation of a list.

Write a function findHypot. The function will be given the length of two sides of a right-angled triangle and it should return the length of the hypotenuse. (Hint: x ** 0.5 will return the square root, or use sqrt from the math module)

Write a Python function called largest that will take a the list of integers between 0 and 1000 and return the maximum value. (Note: there is a builtin function named max but pretend you cannot use it. In fact, don’t use the name max anywhere in you code.)

Write a function named num_test that takes a number as input. If the number is greater than 10, the function should return “Greater than 10.” If the number is less than 10, the function should return “Less than 10.” If the number is equal to 10, the function should return “Equal to 10.”

Write a function to implement the trapezoidal method,

$\int_a^b f(x)\, dx \approx \Delta x \left( \frac{f(a) + f(b)}{2} + \sum_{k=1}^{N-1} f(x_k)\right),$

where $$a$$ and $$b$$ are the lower and upper bounds of the integral, $$f(x)$$ is the integrand, $$N$$ is the number of points that the integrand is evaluated at, and $$\Delta x$$ is the interval between evaluation points.

Your function should be called int_trapz and should take as parameters the integrand, lower and upper bounds, and the number of evaluation points. It should return the estimated value of the integral.

Use your function to evaluate the integral

$\int_{-1}^3 x^3\, dx$

using 101 evaluation points and print out the result.

Hint: use your and pow3 functions from a previous problem.

Write a function call pow3 that takes a parameter x and returns float according to

$f(x) = x^3$

Using your function, print out values for $$x=-1.5, 0, 2.1$$.

Write a function call linspace that returns $$N$$ evenly spaced values between two points $$a$$ and $$b$$ inclusive. Your function should take parameters a, b, and N and return a list of length N.

Using your function, print out the sequence

[-5. , -4.5, -4. , -3.5, -3. , -2.5, -2. , -1.5, -1. , -0.5,  0. ,
0.5,  1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5,  5. ]


Functions are also objects. This means that we can pass function object as a parameter to another function. For example, we will create a function that applies another function to each element of a list. This function looks like:

def apply_to_each(func, lst_in):
lst_out = []
for elem in lst_in:
lst_out.append(func(elem))
return lst_out


We can then specify a list and a function to apply to it:

nums = [1, 2, 3]

def square(x):
return x**2


Finally, we can apply square to each element of nums.

print( apply_to_each(square, nums) )


Notice that there are no arguments or parentheses for square; we are pass it as an object. The output is then

[1, 4, 9]


Create a function call eval_delta that returns the values from a function evaluated at x - dx, x, x+dx. It should take the function name, x, and dx as parameters and return a tuple of the three values. The function definition is provided for you.

Use this to evaluate square at 0.5, 1, 1.5 and print out the results.

Write a function called transpose that takes any matrix and returns its transpose without changing the input. Use your function to assign the transpose of mat_a and mat_b to mat_at and mat_bt.

Hint: use your solution from a previous exercise to get started.

Write a function called l2_norm that takes a vector (list) of any length as input and returns the $$L^{2}\text{-norm}$$ without modifying the input. Use your function to compute and print out the $$L^{2}\text{-norm}$$ of the vectors defined below.

Hint: use your solution from a previous exercise to get started.

The energy levels of the hydrogen atom are given by the equation

$E_{n}=-\frac{2 e^{4}m_{e}}{\left(4\epsilon_{0}h\right)^{2}}\left(\frac{1}{n^{2}}\right)\quad n=1,2,3,\dots$

where $$m_{e}=9.109381\times10^{-31}\text{ kg}$$ is the electron mass, $$e=1.602176\times10^{-19}\text{ C}$$ is the elementary charge, $$\epsilon_{0}=8.854187817\times10^{-12}\text{ F/m}$$ is the permittivity of free space, $$h=6.626068\times10^{-34}\text{J}\cdot\text{s}$$ is Planck’s constant, and $$n$$ is the quantum number.

Write a function called h_atom_ene that takes the quantum number as a parameter and returns the energy in units of electron volts, where

$1\text{ eV} = 1.602176\times10^{-19}\text{ J}.$

The Lorentzian function is often used to fit frequency spectra. It is given by

$L\left(p\right)=\frac{1}{1+\left(\frac{p^{0}-p}{w/2}\right)^{2}}$

where $$p$$ is the frequency, $$p^0$$ is the frequency of maximum intensity, and $$w$$ is the full width at half maximum.

Write a function called lorzentian that takes parameters freq ($$p$$), freq_max ($$p^0$$), and width ($$w$$) and returns the value of the Lorentzian function as a float.

Print the results of your function for

freq=0.5,  freq_max=0,   width=1
freq=-0.5, freq_max=0,   width=1
freq=0.5,  freq_max=0.5, width=1
freq=0.5,  freq_max=0,   width=2
freq=-0.5, freq_max=0.5, width=2


Write a function called matmul that takes any two matrices and returns their matrix multiplication without changing either one.

To test your code, use the two $$3\times3$$ matrices, mat1 and mat2, defined for you. If your code is correct, your function should return

[[0.86814005, 0.88635532],
[0.6728074 , 1.0937629 ]]


Hint: use your solution from a previous exercise to get started.

Write a function called count_list that reproduces the count method without using the count. That is it takes a list and an object as parameters and returns the number of times the object occurs in the list.

Write a function called in_list that reproduces the in operator without using the in operator. That is it takes a list and an object as parameters and returns True if the object is in the list and False otherwise.

The normalized Gaussian function has the form

$g\left(x\right)=\frac{1}{\sigma\sqrt{2\pi}}\exp\left(-\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^{2}\right)$

where $$\sigma$$ is the standard deviation and $$\mu$$ is the mean.

Write a function call gaussian that takes x, mean, and stdev as parameters and returns a float. mean and stdev should be optional parameters with default values of 1.0.

Print the results of your function for

x=0.5,  mean=0,   stdev=1
x=-0.5, mean=0,   stdev=1
x=0.5,  mean=0.5, stdev=1
x=0.5,  mean=0,   stdev=2
x=-0.5, mean=0.5, stdev=2


Write a function called add_2x than takes a list of numbers and adds 2 times the last number to the end. The function should not return anything. Instead, it should modify the list in-place.

E.g., for input list

lst = [4, 5, 6]


the list

[4, 5, 6, 12]


Consider the expression for radioactive decay

$\frac{dN}{dt} = -\lambda N$

where $$N$$ is the number of particles, $$t$$ is time and $$\lambda$$ is a decay constant. If we have a value for the number of particles at the current time, $$N(t)$$, we can calculate the number of particles at $$\Delta t$$ in the future from

$N(t+\Delta t) = N(t) + \frac{dN}{dt}\Delta t = N(t) -\lambda N(t) \Delta t$

Write a function call decay that takes a list of the number of particles a previous times, the decay constant, decay_const, the time step delta_t, and the number of time steps, nsteps. It should update the input list by using the last value in the list as the current number of particles and appending a new value for each time step.

E.g., the function call

decay( , 2, .01, 5)


we expect the output

[10, 9.8, 9.604, 9.41192, 9.2236816, 9.039207968]


For

decay( [100, 200, 300], 2, .01, 5)


we expect the output

[100, 200, 300, 294.0, 288.12, 282.3576, 276.710448, 271.17623904]


since 100 and 200 are not used.

Note: the approach we are using here is called the Euler method. There are much better methods for integrating ordinary differential equation initial values problems but they all use the same basic approach of iteratively updating from an initial value.

Write a function to compute the value of a mathematical function midway between two points. E.g., for

$f(x) = (x-1)^2$

and point $$a=1$$ and $$b=3$$, the result is

$f\left(\frac{a+b}{2}\right) = 1$

Your function should be called midpoint and take a function and two floats as input parameters.

A root of a mathematical function is input value (or values) for which the function evaluates to zero. For example,

$f(x) = x^2 -1$

has roots at $$x=1$$ and $$-1$$.

Often, we don’t know the exact values of the root but we might know that it lies is some range of $$x$$ values. In this case, we can find an approximation of the root using the bisection method.

1. Set err to the acceptable error.

2. Set maxstep to a large number, say 1000.

3. Guess a low and a high value for the root where $$f(\mathtt{low})<0$$ and $$f(\mathtt{high})>0$$. These must bracket a single root. For $$f(x) = x^2 -1$$, suitable brackets are 0 and 5 for the $$x=1$$ root and 0.5 and -4 for the $$x=-1$$ root. A bracket of -4 and 5 is not suitable because it brackets two roots and $$f(-4)>0$$ and $$f(5)>0$$. Brackets are just guesses and don’t need to be exact.

4. Check that $$f(\mathtt{low})<f(\mathtt{high})$$. If not, swap low and high.

5. For maxsteps iterations:

1. Set mid to (high+low)/2.

2. If $$|f(\mathtt{mid})|>err$$

1. If $$f(\mathtt{mid})>0$$, then replace high with mid.

2. else replace low with mid.

3. Set mid to (high+low)/2.

4. Continue iterating.

3. else return mid as the approximate root.

6. If you get to this step, your function did not find a good enough approximation of the root. It should return None, which is the same a not having a return statement at all in Python.

Implement the bisection method by completing the function below. Test it by finding both roots of $$f(x)$$ above.

Write a function called order to compute the value of a mathematical function at two points, low and high. If $$f(\mathtt{low}) < f(\mathtt{high})$$, then return the tuple (low, high). If $$f(\mathtt{low}) > f(\mathtt{high})$$, then swap low and high and return the tuple (low, high).

E.g., for the math function

$f(x) = -2x+3$
def line(x):
return -2*x+3


the function could be called as

order(line, 1, 10)


and would return (10, 1). If it was instead called as

order(line, 10, 1)


it would also return (10, 1) as $$f(10)< f(1)$$.

Write a function lettercount that accepts a list and a letter. The function should return a new list with all the words in the original list that have the letter in them with a dash and the number of times that letter is in the word. For example lettercount([‘cat’,’dog’,’parakeet’,’turtle’],’t’) should return [‘cat-1’,’parakeet-1’,’turtle-2’]. Use append to add to your list.

Create a function cleanup that accepts a string makes it all lower case and breaks the string into a list at the commas, it should then strip any leading/trailing white space out of each list element, and convert any string in the list with only numbers (and periods) into a float.

Write a function sortandseperate that takes a list with mixed type and divides it into sub lists by type. A list with sorted strings and a list with sorted numbers, and a list of lists (don’t need to sort…). For example [‘rat’,8,’dog’,10,11,,3,[‘cat’]] would become [[‘dog’,’rat’],[3,8,10,11],[,[‘cat’]].

The taylor series expansion for $$e^x$$ is

$1 + \frac{x^1}{1!} + \frac{x^2}{2!} + \frac{x^3}{3!} + ...$

Start by grabbing your factorial code from Classwork 3, and turning it into a function called factorial which returns the value of the factorial. Then create a function taylorterm that accepts an integer $$a$$ and the value of $$x$$ and returns the result of an individual taylor fraction. In other words

$\frac{x^a}{factorial(a)}$

Use a for loop and concatenation to make a list with each term of the taylor series. This should be a function called taylorlist that should take the value of x and max value of a as inputs. So $$x=3$$ and $$a=2$$ would get

$[1 , taylorterm(3,1) , taylorterm(3,2)] = [1 , 3 , 4.5]$

Lastly create a function taylorex that returns the taylor series result this should accept an $$x$$ and an $$a$$ and sum the result from the taylorlist. So $$x=3$$ and $$a=2$$ would get 8.5.

Write a function separate_types that takes a list with mixed type and divides it into sub lists by type. A list with sorted strings and a list with sorted numbers, and a list of lists (don’t need to sort…). For example [‘rat’,8,’dog’,10,11,,3,[‘cat’]] would become [[‘dog’,’rat’],[3,8,10,11],[,[‘cat’]].

Create a function called key_val that accepts a dictionary and a list of keys and returns the corresponding list of values. For example key_val({‘one’:1,’two’:2,’three’:3,’four’:4},[‘one’,’three’,’two’]) should return [1,3,2].

Write a function speak(animal,number) which takes in the name of an animal (either cow, dog, or pig) and a number between 1 and 5, and prints their signature utterance (moo, woof, or oink) as many times as number says. It should print an error message if you choose another animal, or if the number is outside the range above.

Define a function first_letters(sentence) which takes in a string, and counts the number of words that begin with each letter of the alphabet. The function should return a dictionary. Example: first_letters(“She sold six buns today”) should return {‘s’: 3, ‘b’: 1, ‘t’: 1}.

Define a function square_list(list) which takes in a list of numbers, and returns a list of the squares of those numbers. Example: square_list([1,5,3]) should return [1,25,9].

Ask the user “How many circles?”, then use the turtle library to draw that many circles.

Ask the user “How many circles?”, then use the turtle library and a function you create called circles(x) to draw that many circles on a regular polygon. To get full credit, the circles MUST be placed on the corners of a regular polygon. For example, if the number of circles is 4, the 4 circles most be in the corners of a square. If the number is 3, the 3 circles must be place in the corners of a triangle.

Write a function that removes all occurrences of a given letter from a string. Test your code with the following text: “Peter Piper picked a peck of pickled peppers. A peck of pickled peppers Peter Piper picked. If Peter Piper picked a peck of pickled peppers, where’s the peck of pickled peppers Peter Piper picked?” by removing all “p” and “P”.

Write a function square_list which takes in a list of numbers, and returns a list of the squares of those numbers. Example: square_list([1,5,3]) should return [1,25,9].

Write a function named odds_below that will generate a list containing every odd number between 0 and a number specified by the user, excluding the user-specified number. For example, calling odds_below(9) should return [1, 3, 5, 7].

Write a function named merge_strings that takes two parameters, both strings, and merges them into one, alternating the characters. For example, if merge_strings is called with the actual parameters "abc" and "123", merge_strings should return "a1b2c3". If the function merge_strings is called with strings that aren’t the same length, then it should print the error message "Strings must be the same length" and return the empty string.

Define a function square_list(list) which takes in a list of numbers, and returns a list of the squares of those numbers. Example: square_list([1,5,3]) should return [1,25,9].

Define a function is_leap_year(year) which takes a year and returns a Boolean indicating whether that year was a leap year. Example: is_leap_year(2020) should return True.

Complete this definition of function is_leap_year(year) which takes a year and returns a Boolean indicating whether that year was a leap year. Example: is_leap_year(2020) should return True.

Replicate the built-in count method for lists in Python. Your function should return the number of times the first argument appears in the second argument. Assume the second argument will always be a list.

Define a function named in_list that checks if a given object is in a list. The function needs to accept a list and an object as parameters. Return True if the object is in the list and False if it is not in the list.

Define a function named matrix_multiply that takes any two matrices and returns their matrix multiplication.

To test your code, use the two $$3\times3$$ matrices, mat1 and mat2, defined for you. If your code is correct, your function should return [[29.88, 29.506], [0.6728074 , 1.0937629 ]]

Note: your funciton should be able to multiply more than just $$3\times3$$ matrices.

Replicate the built-in count method for lists in Python. Your function should return the number of times the first argument (an item) appears in the second argument (a list). Assume the second argument will always be a list.

Define a function named in_list that checks if a given object is in a list. The function needs to accept a list and an object as parameters. Return True if the object is in the list and False if it is not in the list. You may not use the in operator or .count method. You must use a for loop, which uses the in keyword–that’s perfectly fine.

Define a function named matrix_multiply that takes any two matrices and returns their matrix multiplication.

To test your code, use the two matrices, mat1 and mat2, defined for you. If your code is correct, your function should return [[35.36, 29.506], [102.75, 79.725]]

Note: your function should be able to multiply matrices of any (compatible) sizes.

Define a function is_pangram(sentence) which takes a string and returns a Boolean indicating whether that sentence is a pangram. Example: is_pangram("The quick brown fox jumps over the lazy dog.") should return True.

Define a function are_anagrams(word1, word2) which takes two strings and returns a Boolean indicating whether the strings are anagrams of each other. Example: are_anagrams("Live", "Evil") should return True. Note that we are ignoring case!

Write a function wordsize that accepts a list and a number. The function should return a new list with all the words in the original list that have length no greater than the number given. For example wordsize(['this','is','a','test','you'],3) should return ['is', 'a', 'you']. Use append to add to your list.

This ActiveCode box is for you to write your program. There is no starter code, but you have all the guidelines and instructions you need in the assignment PDF, which is available on Moodle. You are allowed to use your Runestone textbook freely, but you are not allowed to use any other sources (nor are you allowed to get help from other people). Your program is due by Dec. 3 at 5:00 PM, but you can take as much time as you want until then (it does not need to be done in one sitting).

Write a function called vowel_finder that takes a string as its parameter and returns a list of the words in that string that begin with a vowel.

Hint: the string 'We all know that as the human body can be nourished on any food, so the human mind can be fed by any knowledge' would return ['all', 'as', 'on', 'any', 'any'].

Create a function called get_prime that takes an integer N and returns the Nth prime number. Hint: the 10th prime number is 29.

1. Write a function row(char, num) that takes a single character and a positive integer as parameters, and returns a string containing the character as many times as number says. For example, calling row('*', 3) should return the string "***". If the function is called with a string of length greater than 1, or if the number is less than 1, then the function should print an appropriate error message to the terminal and return None.

2. Write a function print_wedge(char,ht) that takes a single character and a positive integer as parameters, and prints a wedge or triangle of height ht using the row(char, num) function. For example, calling print_wedge('$', 4) will print the following: $
\$



If the function is called with a string of length greater than 1, or if the height is less than 1, then the function should print an appropriate error message.

3. Write a main() function where you ask the user for a character and the height of a wedge and you draw the desired wedge using print_wedge(char,ht).

Write a function named merge_strings that takes two parameters, both strings, and merges them into one, alternating the characters. For example, if merge_strings is called with the actual parameters "abc" and "123", merge_strings should return "a1b2c3". If the function merge_strings is called with strings that aren’t the same length, then it should print the error message "Strings must be the same length" and return the empty string. Type annotations are not required.

Write a function named list_times_10 that takes one parameter, a list of integers. The function creates and returns a new list that is the same as the parameter list except that each value is multiplied by 10. The parameter list must not be mutated. Use type annotations for the parameter and return.

(5 points) Define a Python function named trimmedMean that takes a list of floating-point numbers as its input (i.e. numList) and then calculates and returns the trimmed mean of that list.

The trimmed mean excludes the outliers from the list, i.e. it does not include the smallest and largest numbers from the list when computing the mean (average). In that way, a trimmed mean is more representative of a dataset, with less interference from the outliers. Your function need not behave well with lists of fewer than 3 elements, or if the list has duplicate elements. Your function definition should not include any print statements.

I have provided a main program that may help you test your function–do not make any changes to my code. (However, this is not an automatic test: you are responsible for determining whether your code is correct.) You may define and use additional functions if you wish; but that is not required. Click the Show Code button to begin.

Write a function row(char, num) that takes a single character and a positive integer as parameters, and returns a string containing the character as many times as num says. For example, calling row('*', 3) should return the string "***". If the function is called with a string of length greater than 1, or if the number is less than 1, then the function should print an appropriate error message to the terminal and return None.

Write a function lettercount that accepts a list and a letter. The function should return a new list with all the words in the original list that have the letter in them with a dash and the number of times that letter is in the word. For example lettercount([‘cat’,’dog’,’parakeet’,’turtle’],’t’) should return [‘cat-1’,’parakeet-1’,’turtle-2’]. Use append to add to your list.

Let’s just see if the getEditorText() method works.

Write a function that will return the number of digits in an integer.

Sum up all the even numbers in a list.

Write a Python function named perim_rectangle that accepts two parameters, the length and width of a rectangle. It should calculate and return the perimeter of a rectangle with that length and width.

Recall from math that P = (2 x length) + (2 x width)

Write a function called add_2x than takes a list of numbers and adds 2 times the last number to the end. The function should not return anything. Instead, it should modify the list in-place.

E.g., for input list

lst = [4, 5, 6]


the list

[4, 5, 6, 12]


Define a Python function

basketball(foulShots, fieldGoals, threePointers)

that computes and returns a team’s basketball score, given the number of each kind of shot. Your function should not contain any print statements.

I have included some test cases you can use. Recall that foul shots are worth 1 point each, field goals are worth 2 points each, and three pointers are, of course, worth 3 points each.

Write a Python function named countVowels that accepts a string as its parameter and then returns (as a single integer) the total number of vowels contained in that string.

For our purposes, assume the vowels are a, e, i, o, and u. Treat capital letters the same as lowercase letters (in other words, for example, A and a are the same letter). Test your function by invoking it with several different strings.

Write a Python function named assignGrades that takes as its single parameter a list of numeric scores, and returns a list of letter grades corresponding to those scores.

For example, a call to assignGrades([78, 91, 85]) should return the list ['C', 'A', 'B']. Your function should not contain any print statements.

For our purposes, we use the traditional grading scheme. That is, a score of 90 or better results in an ‘A’, 80 or better results in a ‘B’, etc. Any score below 60 is an ‘F’.

Outside of your function, write whatever code you feel you need to write to sufficiently test your function.

Write a function speak(animal, number) that takes the name of an animal (either cow, dog, or pig) and a number between 1 and 5 (inclusive) as parameters, and returns their signature utterance (moo, woof, or oink) as many times as number says, separated by spaces. If the function is called with any other animal, or if the number is outside the given range, then the function should print an appropriate error message to the terminal and return None.

Examples:
1. speak('dog', 1) should return the string "woof".

2. speak('cow', 3) should return the string "moo moo moo".

3. speak('cow', 10) should print an error message and return None.

4. speak('fish', 2) should print an error message and return None.

Make sure your code is well-organized, uses appropriate variable names, and includes a descriptive docstring (see section 12.2).

Write a function lettercount that accepts a list and a letter. The function should return a new list with all the words in the original list that have the letter in them with a dash and the number of times that letter is in the word.

Examples:
1. lettercount(['cat','dog','parakeet','turtle'],'t') should return the list ['cat-1','parakeet-1','turtle-2'].

2. lettercount(['grass','bubble','cards','a','stub'],'b') should return the list ['bubble-3', 'stub-1'].

3. lettercount(['boone'],'q') should return an empty list.

Use append to add to your list. Make sure your code is well-organized, uses appropriate variable names, and includes a descriptive docstring (see section 12.2).

Write a function look_and_say_seq(seed, num_of_terms) that takes a string seed and an integer num_of_terms as parameters and returns the look and say sequence (as a list) with the specified number of terms starting with the seed as the first term. You should use the say_what_you_see function from the previous problem.

Examples:

look_and_say_seq('555', 4) should return ['555', '35', '1315', '11131115'].

look_and_say_seq('1', 5) should return ['1', '11', '21', '1211', '111221'].

In almost all look and say sequences the strings grow in length as the sequence progresses. For example, consider the following look and say sequence:

‘2’, ‘12’, ‘1112’, ‘3112’, ‘132112’, ‘1113122112’, …

The lengths of the strings in that sequence are the following:

1, 2, 4, 4, 6, 10, …

The goal of this problem is to investigate the rate at which the lengths are increasing. To do so, we consider the increase in length from one term to the next. More precisely, we look at the ratios of successive lengths. For example, the ratio of successive lengths for the sequence above are

2/1, 4/2, 4/4, 6/4, 10/6, …

With this in mind, complete the following:

1. Use your look_and_say_seq function to generate a look and say sequence with the given seed and number of terms.

2. Create a list called length_ratios that holds the ratio of successive lengths of the look and say sequence.

3. Use the altair module to create a scatter plot showing how the values of length_ratios change as the sequence progresses.

4. Modify the given seed to see how the rate at which the lengths grow varies based on the start of the look and say sequence.

Write a function row(char, num) that takes a single character and a positive integer as parameters, and returns a string containing the character as many times as num says. For example, calling row('*', 3) should return the string "***". If the function is called with a string of length greater than 1, or if the number is less than 1, then the function should print an appropriate error message to the terminal and return None.