#!/usr/bin/env python
# coding: utf-8
# # Lecture 4
#
# In this lecture, we will to continue to learn NumPy `array`, and we will use flow control loops to manunipulate arrays.
# ## Review of NumPy array
# `ndarray` is an arbitrary dimension set of variables of the *same type* (cf. `list` can be concatenate different types). In default, one entry of an array is a 64-bit float (a real number represented by 64 binary digit).
# * Functions: `shape`, `reshape`, `arange`.
# In[ ]:
# always run this cell block first
import numpy as np
# In[ ]:
arr = np.array(range(10))
print(arr)
# In[ ]:
arr[-1] # [] is used for array indexing, () is used as input of functions
# ## For loops
#
# Syntax:
# > for INDEX IN A SET:
# > STUFF THAT WILL BE REPEATED IN EVERY ITERATION
# ## While loops
#
# Very clever way to repeat actions.
#
# Syntax:
# > while CONDITION FOR DOING THE NEXT ITERATION OF THE LOOP:
#
# > STUFF THAT WILL BE REPEATED IN EVERY ITERATION
# In[1]:
# generate lst which is a list of integers from 0 to 9 using while
# code here
n = 0 # counter
lst = [] # initialize the list
while n < 10:
lst.append(n) # the code to be executed if n < 10
n = n + 1 # increase the counter by 1
# ## Example: Checking for primeness
# We want to write a function called `isprime` that checks if a number is prime. Returns `True` if number is prime, `False` otherwise.
# In[ ]:
def isprime(n):
# insert code here
# we check all the divisor d < n whether n % d is 0
# recall n % d is the modulo operation,
# which return the remainder of the division using divisor d
# ## Computing the sum of 1 to 100
# In[2]:
# while loop version: generating an array
arr = np.empty([100], dtype = 'int')
k = 1
while k <= 100:
arr[k-1] = k
k += 1
# In[ ]:
# for loop version
# ### Remark: Break and continue keywords
#
# These are keywords:
# * When the `break` was called, it stopped the loop without doing the print statement underneath.
# * `continue` skips the rest of the current looping of the loop but continues to loop as usual afterwards
#
#
# ### Good exercises (try by yourself):
#
# * Using while loops, implement the integer division function `//` as `division(a,b)`. Make sure you are doing the negative number examples correctly.
# * Write a loop to print the first 100 prime numbers.
# * Make a list of all the prime numbers up to 1000 (using append to add elements)
# * Write a function that will return the maximum element of a list
# * Write a function that will return the sum of the elements of a list
# * Write a function that takes two lists, and checks to see if they have at least one common element
# * Estimate pi by adding the first 1000 terms in the formula:
# $$\frac{\pi}{4} = 1 - \frac13 + \frac15 - \frac17+ \cdots,$$
# which comes from the Taylor expansion of $\arctan(x)$.
# Write a code snippet to compare the answer to the built-in `math.pi`.
# # Vectorization:
#
# Instead of iterating along the indices, we can use built-in routine to make our execution more efficient.
# In[ ]:
arr = np.array(range(16))
# In[ ]:
arr = arr.reshape(4,4) + 1
# In[ ]:
arr.reshape(2,2,-1) # if you put -1, it figures out what the shape should be
# In[ ]:
arr
# In[ ]:
np.reshape(arr, (2,2,-1)) # -1 means unspecified
# In[ ]:
np.sum(arr)
# In[ ]:
np.mean(arr)
# In[ ]:
np.apply_along_axis()
# In[ ]:
np.apply_along_axis(np.sum, 0, arr)
# In[ ]:
np.apply_along_axis(np.sum, 1, arr)
# In[ ]:
np.sum(arr, axis=1)