<jupyter_start><jupyter_text>Exploratory Computing with Python*Developed by <NAME>*  Notebook 3: Loops and `if/else` StatementsAs we will again be using `numpy` and `matplotlib`, we start by importing them<jupyter_code>import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline<jupyter_output><empty_output><jupyter_text>Basic `for` loopLoops are used to execute a command repeatedly. The syntax for a loop is as follows<jupyter_code>for i in range(5):
    print i,'Hello world'<jupyter_output>0 Hello world
1 Hello world
2 Hello world
3 Hello world
4 Hello world<jupyter_text>The first thing to understand about the syntax shown above is that `range(5)` produces a list of 5 values starting with the number 0. It is the equivalent of `arange` but returns a list rather than an array:<jupyter_code>print range(5)<jupyter_output>[0, 1, 2, 3, 4]<jupyter_text>Hence, the line `for i in range(5):` is equivalent to `for i in [0,1,2,3,4]:`A colon (`:`) needs to be placed at the end of the line starting with `for`. The loop starts after the colon. The next line needs to be indented. It doesn't matter how much you indent, as long as you are consistent. The notebook indents automatically for you, so stick with that. The entire block of indented code is executed before it goes to the next value in the list. To indicate the end of the loop, you simply stop indenting.<jupyter_code>for x in [0, 1, 2, 3, 4]:  # same as: for x in range(5):
    xsquare = x**2
    print 'x,xsquare', x, xsquare
print 'We are done with the loop'<jupyter_output>x,xsquare 0 0
x,xsquare 1 1
x,xsquare 2 4
x,xsquare 3 9
x,xsquare 4 16
We are done with the loop<jupyter_text>A loop can be used to fill an array. Let's compute $y=\cos(x)$ where $x$ is an array that varies from 0 to $2\pi$ with 100 points. We already know, of course, that this can be done with the statement `y=cos(x)`. Sometimes this is not possible, however, and we need to fill an array with a loop. First we have to create the array `y` (for example filled with zeros using the `zeros_like` function) and then fill it with the correct values by looping through all values of `x`. The counter in the loop (the variable `i` in the code below) is used as the index of the array that is filled.<jupyter_code>x = np.linspace(0, 2 * np.pi, 100)
y = np.zeros_like(x)  # similar to zeros(shape(x))
for i in range(len(x)):
    y[i] = np.cos(x[i])

plt.plot(x,y);<jupyter_output><empty_output><jupyter_text>Loops are very useful constructs in a programming script. Whenever you need to do a computation multiple times you should automatically think: *loop !*.   Exercise 1. First `for` loopConsider the following list of the ten largest countries by area:Russia, Canada, China, USA, Brazil, Australia, India, Argentina, Kazakhstan, Algeria.The corresponding areas (in $10^3$ km$^2$) are:17098, 9889, 9388, 9147, 8515, 7692, 3287, 2780, 2717, 2381.Loop through the list of country names and a list (or array) of the areas and for each country print to the screen:`CountryName has an area of XXX square kilometers`with the appropriate CountryName and number of square kilometers, of course. Make sure the printed units are square kilometers.<jupyter_code>x=['Russia', 'Canada', 'China', 'USA', 'Brazil','Australia', 'India', 'Argentina', 'Kazakhstan', 'Algeria']
y=['17098', '9889', '9388', '9147', '8515', '7692', '3287', '2780', '2717', '2381']

  

for i in range(len(x)):

    print x[i], 'has an area of', y[i],'*10^3 square kilometers.'<jupyter_output>Russia has an area of 17098 *10^3 square kilometers.
Canada has an area of 9889 *10^3 square kilometers.
China has an area of 9388 *10^3 square kilometers.
USA has an area of 9147 *10^3 square kilometers.
Brazil has an area of 8515 *10^3 square kilometers.
Australia has an area of 7692 *10^3 square kilometers.
India has an area of 3287 *10^3 square kilometers.
Argentina has an area of 2780 *10^3 square kilometers.
Kazakhstan has an area of 2717 *10^3 square kilometers.
Algeria has an area of 2381 *10^3 square kilometers.<jupyter_text>`if`/`else` statementsAs we have seen, a basic `if` statement can be used to perform a task based on whether a condition is `True`. The `if` statement can be followed by an `else` statement, which is executed when the condition after `if` is `False`. For example<jupyter_code>a = 4
if a < 3:
    print 'a is smaller than 3'
else:
    print 'a is not smaller than 3'<jupyter_output>a is not smaller than 3<jupyter_text>You can even extend the `else` by adding one or more conditions with the `elif` command which is short for 'else if'<jupyter_code>a = 4
if a < 4:
    print 'a is smaller than 4'
elif a > 4:
    print 'a is larger than 4'
else:
    print 'a is equal to 4'<jupyter_output>a is equal to 4<jupyter_text>Rather than specifying the value of variable `a` at the top of the code cell, you can ask the user to enter a value and store that value in the variable `a` using the `input` function. Run the code cell below multiple times to see if it works when the entered value is larger than 4, smaller than 4, or equal to 4<jupyter_code>a = input('Enter a value ')
if a < 4:
    print 'the value is smaller than 4'
elif a > 4:
    print 'the value is larger than 4'
else:
    print 'the value is equal to 4'<jupyter_output>Enter a value 5
the value is larger than 4<jupyter_text>Exercise 2. Combination of `for` loop with `if` statementConsider the following squence of random numbers between 0 and 10 (Run the code cell below):<jupyter_code>n = np.random.randint(0, 10, 20)
print n<jupyter_output>[4 7 5 2 3 2 3 7 8 6 7 4 1 3 7 7 4 7 3 8]<jupyter_text>Create an new array with the same length as `numbers`. Loop through all values in `numbers` and store the positive value of `numbers`  in the new array when the value is even, and the negative value when it is odd.  You can determine whether a value is odd or even by using  the remainder operator `%`, which determines the remainder of a division. (Hint: try, for example, `3 % 2` and `4 % 2` to find out what the remainder operator does.)Plot the new array with blue dots.<jupyter_code>for i in range(len(n)): 
    if n[i]%2==0: 
        n[i]=n[i]
    else: 
        n[i]=-n[i]    

print n

plt.plot (n,'bo')<jupyter_output>[ 4 -7 -5  2 -3  2 -3 -7  8  6 -7  4 -1 -3 -7 -7  4 -7 -3  8]<jupyter_text>Exercise 3. Load and loop through dataThe monthly number of visitors for a themepark is given in the file `visitors.dat`. A month with less then 10,000 visitors is considered as a quiet month. If the number of visitors is between 10,000 and 20,000, it is a moderate month, and if the number of visitors is more than 20,000, it is a busy month.For each month, determine whether the theme park has a quiet, a moderate, or a busy month. Print for each month the name of the month, the number of visitors, and wheter it's a quiet, moderate or busy month. For example, something like: `January  had  4190 visitors and was a quiet month`, etc.<jupyter_code>z=np.loadtxt('visitors.dat')
u=('January','February','March','April','May','June','July','August','September','October','November','December')

for i in range(len(z)):
    if z[i]<10000:
        print u[i],'had', z[i], 'visitors and it was a quiet month.'
    elif z[i]>20000:
        print u[i],'had', z[i], 'visitors and it was a busy month.'
    else:
        print u[i],'had', z[i], 'visitors and it was a moderate month.'<jupyter_output>January had 4190.0 visitors and it was a quiet month.
February had 3200.0 visitors and it was a quiet month.
March had 6000.0 visitors and it was a quiet month.
April had 12000.0 visitors and it was a moderate month.
May had 17000.0 visitors and it was a moderate month.
June had 20500.0 visitors and it was a busy month.
July had 21000.0 visitors and it was a busy month.
August had 35000.0 visitors and it was a busy month.
September had 15000.0 visitors and it was a moderate month.
October had 5000.0 visitors and it was a quiet month.
November had 2300.0 visitors and it was a quiet month.
December had 3000.0 visitors and it was a quiet month.<jupyter_text>Looping and summationOne application of a loop is to compute the sum of all the values in an array. Consider, for example, the array `data` with 8 values. We will compute the sum of all values in `data`. We first define a variable `datasum` and assign it the value 0. Next, we loop through all the values in `data` and add the value to `datasum`:<jupyter_code>data = np.array([1,3,2,5,7,3,4,2])
print data
datasum = 0
for i in range(len(data)):
    datasum =datasum + data[i]
    print 'i,datasum: ',i,datasum
print 'total sum of data: ',datasum<jupyter_output>[1 3 2 5 7 3 4 2]
i,datasum:  0 1
i,datasum:  1 4
i,datasum:  2 6
i,datasum:  3 11
i,datasum:  4 18
i,datasum:  5 21
i,datasum:  6 25
i,datasum:  7 27
total sum of data:  27<jupyter_text>Note that the statement `datasum = datasum + data[i]` means that `data[i]` is added to the current value of `datasum` and that the result is assigned to `datasum`. There is actually a shorter syntax for the same statement: `datasum += data[i]`The `+=` command means: add whatever is on the right side of the `+=` sign to whatever is on the left side. You can use whichever syntax you are most comfortable with (although `+=` is considered to be better and in some cases more efficient).  Exercise 4.  Running totalCreate a list with the names of the months in a year, and a separate list or array with the number of days in each month (for a regular year). Create a loop that prints to the screen `at the end of MONTH XX days have passed this year`where you fill in the name of the month and `XX` is the corresponding number of days that have passed at the end of that month in that year. Make sure `XX` is computed by your code.<jupyter_code>month = ['January','February','March','April','May','June','July','August','September','October','November','December']
dat=[31,28,31,30,31,30,31,31,30,31,30,31]

print dat
datsum = 0
for i in range(len(dat)):
    datsum =datsum + dat[i]
    print 'At the end of',month[i],datsum,'have passed this year'<jupyter_output>[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
At the end of January 31 have passed this year
At the end of February 59 have passed this year
At the end of March 90 have passed this year
At the end of April 120 have passed this year
At the end of May 151 have passed this year
At the end of June 181 have passed this year
At the end of July 212 have passed this year
At the end of August 243 have passed this year
At the end of September 273 have passed this year
At the end of October 304 have passed this year
At the end of November 334 have passed this year
At the end of December 365 have passed this year<jupyter_text>Finding the maximum value the hard wayNext, let's find the maximum in the array `data` and the index of the maximum value. For illustration purposes, we will do this the hard way by using a loop and an if statement. First we create a variable `maxvalue` that contains the maximum value and set it initially to a very small number, and a variable `maxindex` that is the index of the maximum value and is initially set to `None`. Then we loop through all values in `data` and update the `maxvalue` and `maxindex` everytime we find a larger value than the current `maxvalue`<jupyter_code>maxvalue = -1e8
maxindex = None
for i in range(len(data)):
    if data[i] > maxvalue:
        maxvalue = data[i]
        maxindex = i
print 'the maximum value is ',maxvalue
print 'the index of the maximum value is ',maxindex<jupyter_output>the maximum value is  7
the index of the maximum value is  4<jupyter_text>For this example, it is easy to check whether these numbers are correct by looking at the `data` array. But there are, of course, functions available (in the numpy package) to find the maximum value and the index of the maximum value: `amax` returns the maximum value of an array, and `argmax` returns the index of the maximum of the array. There are similar functions if you are interested in the mimimum value.<jupyter_code>print 'the maximum value is ',np.amax(data)
print 'the index of the maximum value is ',np.argmax(data)<jupyter_output>the maximum value is  7
the index of the maximum value is  4<jupyter_text>Exercise 5, Minimum and maximum wave heightThe file `waves2014.dat` contains the significant wave heights (defined as the average height of the highest one-third of the waves) in cm at a buoy in the North Sea recorded in 2014. Load the data and plot it. Add a title and labels to the axes. Use numbers along the axis.<jupyter_code>w= np.loadtxt('waves2014.dat')
plt.plot (w)
plt.ylabel ('average height of waves in cm')
plt.xlabel('time')
plt.title ( 'Average height of the highest one-third of the waves at a buoy in the North Sea in 2014')<jupyter_output><empty_output><jupyter_text>When you look at the timeseries, you can see the highest and lowest recorded significant wave height.Write a `for` loop to find the highest and lowest significant wave height in the data set and print the values to the screen. Next, use the `np.max` and `np.min` functions to determine the same.<jupyter_code>maxvalue = -1e8

for i in range(len(w)):
   if w[i] > maxvalue:
        maxvalue = w[i]
        maxindex = i
print 'The maximum value is ',maxvalue


minvalue = 1e8

for i in range(len(w)):
    if w[i] < minvalue:
        minvalue = w[i]
        minindex = i
print 'The minimum value is ',minvalue



print 'The maximum value is ',np.amax(w)


print 'The minimum value is ',np.amin(w)<jupyter_output>The maximum value is  261.0
The minimum value is  9.0
The maximum value is  261.0
The minimum value is  9.0<jupyter_text>Nested loopsIt is also possible to have loops inside loops. These are called nested loops. For example, consider the array `data` with 3 rows and 4 columns shown below. We want to compute the sum of the values in each row and we are going to do this using a double loop. First, we make an array of zeros called `rowtotal` of length 3 (one value for each row of the array `data`). Next, we loop through each row. For each row inside the loop, we start another loop that goes through all the columns and adds the value to the array rowtotal for that row.<jupyter_code>data = np.array([[1,2,3,5],
              [4,8,6,4],
              [3,5,4,6]])
print data
rowtotal = np.zeros(3)
print rowtotal
for irow in range(3):
    for jcol in range(4):
        rowtotal[irow] += data[irow,jcol]
        # longer alternative:
        #rowtotal[irow] = rowtotal[irow] + data[irow,jcol]
print rowtotal<jupyter_output>[[1 2 3 5]
 [4 8 6 4]
 [3 5 4 6]]
[ 0.  0.  0.]
[ 11.  22.  18.]<jupyter_text>After running the code above, first make sure that the answer is correct. Next, note that it is important to set the values of `rowtotal` to 0 before starting the loops, as we added to these values to compute the sum of each row. In the code, we use two loops, so we indented twice.   Breaks and whileA common task is to find the position of a value in a sorted table (e.g., a list or array). For example, determine between which two numbers the number 6 falls in the sequence `[1,4,5,8,9]`. I know, it is between `5` and `8`, but what if the list is long? Then you really want a routine to do that.To find the position in the list, we need to loop through the list and break out of the loop once we have found the position.For this, Python has the command `break`.<jupyter_code>x = [1,4,5,8,9]
a = 6
for i in range(len(x)):
    if a < x[i]:
        break
print 'a is between ',x[i-1],' and ',x[i]<jupyter_output>a is between  5  and  8<jupyter_text>There is another way of coding this using a `while` loop. Let's first look at the while loop for the same code as above<jupyter_code>x = [1,4,5,8,9]
a = 6
i = 0
while a >= x[i]:
    i = i + 1
print 'a is between ',x[i-1],' and ',x[i]<jupyter_output>a is between  5  and  8<jupyter_text>In the `while` loop, the comparison is done at the beginning of the loop, while the counter (in this case `i`) is updated inside the loop. Either a loop with a break or a while loop with a counter works fine, but `while` loops may be tricky in some cases, as they can result in infinite loops when you have an error in your code. Once you are in an infinite loop (one that never stops), click on the [Kernel] menu item at the top of the window and select [Restart]. This will end your Python session and start a new one. When you print something to the screen in your while loop, it may not be possible to break out of the loop and you may need to end your IPython session (and potentially lose some of your work).   StringsStrings are a very versatile data type, and we can easily spend an entire Notebook on strings. We will only make limited use of strings, so we keep treatment here to a bare minimum. We already used strings to specify names along axes of a graph, or in the legend of a graph. Strings are like tuples in that every character in a string has an index. Each character or range of characters can be accessed, just like for tuples, but they cannot be changed. A string also has a length.<jupyter_code>text1 = 'Goodmorning everybody'
print len(text1)
print text1[0]
print text1[0:12]<jupyter_output>21
G
Goodmorning<jupyter_text>When you add two strings, they are put back to back, just like tuples. When you want to combine text with a variable, you first need to change the variable to a string and then add the two strings<jupyter_code>newtext = text1 + ' in the class'  # Adding two srings
print newtext
a = 7
mes = 'The magic number is ' + str(a)  # Combining strings and numbers
print mes<jupyter_output>Goodmorning everybody in the class
The magic number is 7<jupyter_text>Comparisons work on strings just like they work on numbers. The comparison starts with the first character in a string and only goes to the next character when the first characters of both strings are equal. The letter 'a' is smaller than 'b', 'b' is smaller than 'c', etc. But be careful, in the order of things, the upper case characters are smaller than all lower case characters! So 'A' is smaller than 'a', but also than 'm' or any other lower case character. Make sure you understand the following statements<jupyter_code>print 'delft' < 'eindhoven'  # True as 'd' is smaller than 'e'
print 'dalft' < 'delft'      # True as 'a' is smaller than 'e'
print 'delft' == 'Delft'     # False as lower and upper case are not equal
print 'Delft' < 'delft'      # True as 'D' is smaller than 'd'
print 'delft' > 'Eindhoven'  # Also True, as 'd' is larger than 'E' or any other upper case character<jupyter_output>True
True
False
True
True<jupyter_text>Strings can be converted to upper or lower case<jupyter_code>TU = 'TU Delft'
print TU
print TU.lower()
print TU.upper()<jupyter_output>TU Delft
tu delft
TU DELFT<jupyter_text>A string conisting of multiple words can be converted into a list that of words using `split`<jupyter_code>sentence = 'This is a sentence of a number of words'
print 'This is the sentence:'
print sentence
wordlist = sentence.split()
print 'This is the split sentence:'
print wordlist
print 'All words may be printed seperately:'
for word in wordlist:
    print word<jupyter_output>This is the sentence:
This is a sentence of a number of words
This is the split sentence:
['This', 'is', 'a', 'sentence', 'of', 'a', 'number', 'of', 'words']
All words may be printed seperately:
This
is
a
sentence
of
a
number
of
words<jupyter_text>Exercise 6, Count letters using a nested loopConsider the following text about <NAME> (the first paragraph of his Wikipedia page):<jupyter_code>text = '<NAME> was born in Arnhem Gelderland (The Netherlands), the son of <NAME> (1822–1893), a well-off nurseryman, and <NAME> (1826–1861). In 1862, after his mothers death, his father married <NAME>. Despite being raised as a Protestant, he was a freethinker in religious matters. From 1866 to 1869 he attended the "Hogere Burger School" in Arnhem, a new type of public high school recently established by <NAME> His results in school were exemplary; not only did he excel in the exact sciences but also in English, French, and German. In 1870 he passed the exams in classical languages which were then required for admission to University'
print text<jupyter_output><NAME> was born in Arnhem Gelderland (The Netherlands), the son of <NAME> (1822–1893), a well-off nurseryman, and <NAME> (1826–1861). In 1862, after his mothers death, his father married <NAME>. Despite being raised as a Protestant, he was a freethinker in religious matters. From 1866 to 1869 he attended the "Hogere Burger School" in Arnhem, a new type of public high school recently established by <NAME> His results in school were exemplary; not only did he excel in the exact sciences but also in English, French, and German. In 1870 he passed the exams in classical languages which were then required for admission to University<jupyter_text>Count how many times each letter of the alphabet appears in the text about Lorentz. Store the number of times each letter appears in an array of length 26 (the number of letters in the alphabet) using a nested loop. For each letter, print to the screen `LETTER is present XX times`, where you print each `LETTER` of the alphabet and the corresponding number of times `XX` it appears in the text.<jupyter_code>text1= text.lower()

lettrs=['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
sum =0    

rowtotal = np.zeros(26)

for irow in range(len(lettrs)):
    for i in range(len(text1)):
        if lettrs[irow] == text1[i]:
            rowtotal[irow]=rowtotal[irow]+sum+1
            
    sum=0
print rowtotal

for i in range(len(lettrs)):
    print 'the letter',lettrs[i],'is present', rowtotal[i],'time'<jupyter_output>[ 38.   9.  14.  21.  78.  11.  13.  36.  37.   1.   6.  26.  11.  42.  28.
   8.   1.  45.  36.  36.  13.   2.   7.   4.   7.   2.]
the letter a is present 38.0 time
the letter b is present 9.0 time
the letter c is present 14.0 time
the letter d is present 21.0 time
the letter e is present 78.0 time
the letter f is present 11.0 time
the letter g is present 13.0 time
the letter h is present 36.0 time
the letter i is present 37.0 time
the letter j is present 1.0 time
the letter k is present 6.0 time
the letter l is present 26.0 time
the letter m is present 11.0 time
the letter n is present 42.0 time
the letter o is present 28.0 time
the letter p is present 8.0 time
the letter q is present 1.0 time
the letter r is present 45.0 time
the letter s is present 36.0 time
the letter t is present 36.0 time
the letter u is present 13.0 time
the letter v is present 2.0 time
the letter w is present 7.0 time
the letter x is present 4.0 time
the letter y is present 7.0 time
the letter z is present 2.[...]<jupyter_text>Exercise 7. Count how many time you can make a wordUsing the text about Lorentz of the previous Exercise, count how many times you can make the word `bouwplaats` with the letters in te text using a nested loop. You can use the result of the previous exercise. You can use each letter only once. So if there are 10 letters 'b' in the text, you can make at most 10 times the words `bouwplaats`.<jupyter_code>text1= 'bouwplaats'
rowss = np.zeros(len (text1))
for irow in range(len(lettrs)):
    for i in range(len(text1)):
        if lettrs[irow] == text1[i]:
            rowss[i]=rowtotal[irow]
            
rowss[6] = rowss[6]/2.
rowss[7] = rowss[7]/2.

print rowss

print 'I cam make at most',np.amin(rowss),'times the word bouwplaats.'<jupyter_output>[  9.  28.  13.   7.   8.  26.  19.  19.  36.  36.]
I cam make at most 7.0 times the word bouwplaats.
{'fraction_non_alphanumeric': 0.08286731062531774, 'fraction_numerical': 0.03609557702084393, 'mean_word_length': 4.093871385412171, 'pattern_counts': {'":': 0, '<': 112, '<?xml version=': 0, '>': 110, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '29', 'dir': 'jupyter-structured-clean-dedup', 'id': '407918', 'license': 'MIT', 'n_tokens_mistral': 7842, 'n_tokens_neox': 7139, 'n_words': 3748, 'path': 'Computerprogrameren TUDelft/Notebook 03 Loops and if elfe statments/3.ipynb', 'repo_name': 'Pietervanhalem/Pieters-Personal-Repository', 'size': '23750'}