# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + [markdown] deletable=true editable=true
# # Debug and judge

# + [markdown] deletable=true editable=true
# Let's try to do a few easy things so that you can practice what you have learned.
#
# First, let's look at another python function: **reduce( )**. Let's say you want to to calculate the product of a list of numbers. Normally, you can do a for-loop that goes through each item and outputs the result.
#
# Below, I have written some code that implements this simple idea. It has, however, a number of bugs and wrong code in it that you should correct. If you have corrected the code, you should see the follwing output:
#
#
# ```
# [1,2,3,4,5,6,7,8,9,10]
# Product of list is:  3628800
# ```
#
# **Hint:** There are four mistakes in the code. 

# + deletable=true editable=true
# our data as created by a list from 1 to 10
data = range(1,10)
print(data)

# initialize variable
product = 0

# do for-loop
for d in data
    product = product * d

# print out result
print('Product of list is: ',product)

# + [markdown] deletable=true editable=true
# Now, let's use the **reduce( )** function for this in connection with a **lambda** function that we define on the elements. **reduce( )** uses two inputs: first, a function and, second, the data that the function is applied to. The end-result will be one single, reduced element that is the result of the function on the data. 
#
# The **reduce( )** function is part of a package, which we need to import first. I have written the import statement below. It is, however, not correct. Correct this:

# + deletable=true editable=true
from functool import reduce

# + [markdown] deletable=true editable=true
# Once you have this corrected, let me give you an example of the use of **reduce( )**

# + deletable=true editable=true
print(reduce(lambda x,y: x+y, [1,2,3,4]))

# + [markdown] deletable=true editable=true
# So the lambda function has two inputs x and y that come from the repeated application of reduce on the array. The "previous" result is x and the "current" input y is added to x in each step. So this is equivalent to a for-loop that goes through the list and adds all elements. 

# + [markdown] deletable=true editable=true
# Back to our example! We now need to define a lambda function that takes each element of our data array and produces a multiplication. Correct the following example:

# + deletable=true editable=true
print('Product of list is: ',reduce(lambda x: x*x,data))


# + [markdown] deletable=true editable=true
# We would like to know whether it is actually better to run reduce than to run the for-loop. So let's time the two things. For this, we will use the IPython utility function **timeit** that I showed you a few times already. We will also define a new array of data, which is a little larger.

# + deletable=true editable=true
def myp(x,y):
    return x*y

newdata = range(1,200)
# %timeit reduce(myp,newdata)# insert the code here that times the reduce function!
print(reduce(myp,newdata))


# + [markdown] deletable=true editable=true
# Alright, now let's time the for-loop. For this, we put this in a function that we call once in order to get the array multiplied. 

# + deletable=true editable=true
def myproduct(da):
    product = 1
    for d in da:
        product = product * d
    return product

newdata = range(1,200)
# %timeit myproduct(newdata)
print(myproduct(newdata))


# + [markdown] deletable=true editable=true
# Can you interpret the result? Which method is faster??

# + [markdown] deletable=true editable=true
# # More timing - loops
#
# In python, general lists can iterated over in several different ways. Just to see how things go, expand the following code to time the three functions I have defined below that show three different types of iteration.
#
# ```
# def pythonFor(a):
# 	for index, item in enumerate(a): tmp1,tmp2 = index, item
# 	
# def cFor(a):
# 	for i in range(len(a)): tmp1,tmp2 = i, a[i]
# 	
# def numpyFor(a):
# 	for i in np.arange(len(a)): tmp1,tmp2 = i, a[i]
# ```
# -

def pythonFor(a):
    for index, item in enumerate(a): tmp1,tmp2 = index, item
def cFor(a):
    for i in range(len(a)): tmp1,tmp2 = i, a[i]
def numpyFor(a):
    for i in np.arange(len(a)): tmp1,tmp2 = i, a[i]



StarcoderdataJupyterScriptsDedupFiltered