This homework aims at giving you some experience with Python for-loops and while-loops as well as reading user input from the Bash command line.

1.  The while-loop implementation of a for-loop. Consider the following example code, which converts a list of temperature values from Celcius to Ferenheit, using a for-loop and then prints them on screen.

Cdegrees = [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
print ('    C     F')
for C in Cdegrees:
    F = (9.0/5)*C + 32
print ('%5d %5.1f' % (C, F))
    C     F
  -20  -4.0
  -15   5.0
  -10  14.0
   -5  23.0
    0  32.0
    5  41.0
   10  50.0
   15  59.0
   20  68.0
   25  77.0
   30  86.0
   35  95.0
   40 104.0

Write a while-loop implementation of the above code.

2.  Consider the following nested list,

the following nested list:
q = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h']]

Write a for-loop that extracts all the letters in the list and finally prints them all as a single string,


3.  Consider the following program,

from math import sqrt
for n in range(1, 60):
    r_org = 2.0
    r = r_org
    for i in range(n):
        r = sqrt(r)
    for i in range(n):
        r = r ** 2
    print ('With {} times sqrt and then {} times **2, the number {} becomes: {:.16f}'.format(n,n,r_org,r))

Explain what this code does. Then run the code, and explain why do you the behavior observed. In particular, why do you not recover the original value $2$ after many repetitions of the same forward and reverse task?

4.  Consider the following code,

eps = 1.0
while 1.0 != 1.0 + eps:
    print ('...............', eps)
    eps /= 2.0
print ('final eps:', eps)

Explain what the code is doing. Run the code and observe the output. How could 1.0 != 1.0 + eps be False?

5.  Consider the following list,

numbers = list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Now run the following code, given the above list. Explain the weird behavior that you observe.

for n in numbers:
    i = len(numbers)//2
    del numbers[i]
    print ('n={}, del {}'.format(n,i), numbers)

6.  Consider a problem similar to what we had in the midterm exam: Write a Python function that when executed, asks the user to enter an integer number, then the function gives out the number of prime numbers that are smaller than the input integer number. Here is the answer to this question using only the knowledge of recursive functions and if-blocks,

def is_prime(n):
    is_prime = True
    def is_divisible(n,divisor):
        if n<(divisor-1)*divisor: return False
        if n%divisor==0: return True
            divisor += 1
            return is_divisible(n,divisor)

    if is_divisible(n,divisor=2): is_prime=False
    return is_prime

def get_primes(n):
    count = 0
    if n == 1:
        return count
        if is_prime(n):
            count = 1
        n -= 1
        return count + get_primes(n)


(A) Now rewrite get_primes(n) and the other functions in the above code using for-loop this time. Name the new functions get_prime_for(n) and is_prime_for(n), with for in the names indicating that the functions now use for-loops.

(B) Now compare the performance of the two functions get_primes(n=500) and get_primes_for(n500) using Jupyter’s or IPython’s %timeit magic function. Which one is faster?