
# coding: utf-8

# # Preliminaries
# 
# All assignments for this class will be fetched, worked-on, and submitted via a dynamic in-browser Python development and testing environment known as the [Jupyter Notebook](http://jupyter.org/).
# 
# This first machine problem is intended to familiarize you with the environment and assignment retrieval/submission system.
# 
# ## Fetching assignments
# 
# If you're reading this, then you're likely already familiar with the procedure for fetching an assignment. To recap:
# 
# - After logging in using your @hawk.iit.edu account, you'll either click "Start Server" or "My Server" to go to the Jupyter dashboard
# - From there, go to the "Assignments" tab, where you'll see any newly released assignments in the "Released assignments" area. You can fetch the files by clicking the "Fetch" button next to each assignment.
# - After an assignment has been fetched, you'll see it in the "Downloaded assignments" area, where you can expand the assignment to click on individual notebooks to open them up. You can also validate and submit your work here. Alternatively, you can also browse into an assignment folder from the "Files" tab and click on notebook files to open them up there.

# ## In-browser development
# 
# One of the main reasons we're using the Jupyer Notebook platform is because it provides every student with a consistent, in-browser development environment. Each cell that you see in this notebook, in fact, can be used to evaluate Python code. Before proceeding, you might want to check out the [official Notebook interface documentation](http://jupyter-notebook.readthedocs.org/en/latest/notebook.html#notebook-user-interface).
# 
# The most important thing for now --- we'll be going over more details during lecture --- is that you can select a code cell (marked with a `In [XX]` indicator to its left), hit `Enter` to edit it, and `shift-Enter` to evaluate its contents.
# 
# Try this with the cells below. Note that definitions "stick" across cells, allowing us to write lengthy programs across cells in a notebook. Feel free to play around a bit.

# In[1]:

def say_hello():
    print("hello world!")


# In[2]:

say_hello()


# ### Autograded cells
# 
# Many of the machine problems you'll be working on will have auto-graded pieces. Typically, these involve functions you need to complete, paired with test-cases written in advance. 
# 
# Below, for instance, is a stubbed out `factorial` function for you to complete. If you've forgotten, the factorial of a positive integer *n* is simply the product of all integers from *n* down through 1. E.g., the factorial of $5 = 5 \times 4 \times 3 \times 2 \times 1 = 120$.
# 
# Go ahead and complete the implementation of `factorial` now. (You should delete the comment and the `raise` statement.)

# In[5]:

def factorial(n):
    f=1
    while n>=1:
        f=f*n
        n=n-1
    return f

    


# When you're done with your solution, you can run the tests in the cell below (but don't modify its contents!) to see how you did. Any errors will be displayed as output; if there is no output, it means you passed all the autograder tests.

# In[8]:

import unittest
tc = unittest.TestCase()
tc.assertEqual(factorial(1), 1)
tc.assertEqual(factorial(5), 120)
tc.assertEqual(factorial(10), 3628800)


# ### Project Euler problems

# Because we've yet to discuss any data structures or algorithms, these next few general programming problems are taken from [Project Euler](https://projecteuler.net/) to provide some warm-up exercises for the Python language.

# #### Multiples of 3 and 5
# 
# If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
# 
# Find the sum of all the multiples of 3 or 5 below the provided argument `n`.

# In[1]:

def multiples_of_3_and_5(n):
    total=0
    for i in range(1,n):
        if(i%3==0 or i%5==0):
            total=total+i
    return total


# In[2]:

import unittest
tc = unittest.TestCase()
tc.assertEqual(multiples_of_3_and_5(10), 23)
tc.assertEqual(multiples_of_3_and_5(500), 57918)
tc.assertEqual(multiples_of_3_and_5(1000), 233168)


# #### Even Fibonacci numbers
# 
# Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
# 
#     1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
# 
# By considering the terms in the Fibonacci sequence whose values do not exceed the argument `n`, find the sum of the even-valued terms.

# In[65]:

def even_fibonacci(n):
    total=0
    a=0
    b=1
    while b<n:
        a, b=b, a+b 
        
        if(b%2==0 and b<n):
            total=total+b
    return total
    


# In[66]:

import unittest
tc = unittest.TestCase()
tc.assertEqual(even_fibonacci(100), 44)
tc.assertEqual(even_fibonacci(10000), 3382)
tc.assertEqual(even_fibonacci(4000000), 4613732)


# ## Submission
# 
# When you're ready to submit your work, make sure it's saved (you can click the disk icon in the menu bar), then go back to the "Assignments" tab and click "Submit" next to this assignment in the "Downloaded assignments" area. You can submit as many times as you like before the due date -- you'll see your submissions listed in the "Submitted assignments" area.
# 
# That's it for now!
