# Learn Python from Khan Academy

```# Khan Academy
print (3+7)
print (type(3+7))  #<class 'int'>
print ("Hello")
print (type("Hello")) #<class 'str'>

# List
a = [7,13,15]
a = 5
b = a
print (b)

c = b[:]  #[5, 13, 15]
print (c)
d = b[0:2] #[5, 13]  [m:n] m=start from, n=up to but not included
print (d)

d.append(10) #[5, 13, 10]
print (d)

# Range
range(3) #[0, 1, 2]
range(1,6)  #[1, 2, 3, 4, 5]  up to but not including the upper
range(0,8,2) #[0, 2, 4, 6]

# ==========================================================
# For loop
sum = 0
for i in range(10):
sum = sum + i
print (sum)

# ==========================================================
# While loop
sum = 0
i = 0
while i < 10:
sum = sum + i
print (sum)
i = i + 1

# ==========================================================
# String
a = "This is a string"
len(a)
b = "This is another string"
a+b #Concatenate

b.split(' ') #['This', 'is', 'another', 'string']
b.find('no') #9
b.find('is') #2

b.replace('is','as') #'Thas as another string'  Did not replace b

match_string = "3+4*2"
print (match_string)
eval(match_string) #11
eval(match_string +'1') #87

expression_string = "a + b"
eval(expression_string)

# Sample of Factorial Program

# Window pop for an input
#number = input("Enter a non-negative integer to take the factorial of:")
#number = eval(input("Enter a non-negative integer to take the factorial of:")) #python 3
# python 3 = the result of input is string as is
# python 2 = the result will be evaluated automatically
number = 2
product = 1
for i in range(number):
product = product * (i+1)

print (product)

# ==========================================================
# Define a function
# Interactive
def factorial1(number):
product = 1
for i in range(number):
product = product * (i+1)
return product

# Use of function
user_input = 5
factorial_of_user_input = factorial1(user_input)
print (factorial_of_user_input)
print (factorial1(4))

# Now we are doing the "Recursive" Factorial function
# Is it faster?
def factorial2 (number):
if number <= 1: #base case
return 1
else:
return number * factorial2(nummber - 1)

# Comparing Iterative vs Recursive Functions?

# Fibonacci numbers
# 0,1,1,2,3,5,8,13,21,34,55
# Add previous two numbers to be new number
# Golden Ratio = two numbers next to each other
#               having the later divided by the former
#  21/13 ~ Golden ratio
#  55/34 ~ even closer to Golden ratio

#  When a > b,  (a+b)/a = a/b = GOlden ratio

# Assignment
#   fibonacci(1) = 1
#   fibonacci(3) = 2
#   fibonacci(0) = 0

# Iterative Fibonacci Function
def fibonacci_interative(n):
print ("Fibonacci: " + str(n))
terms = [0,1]
i = 2
while i <=n:
terms.append(terms[i-1]+terms[i-2])
i = i+1
return terms[n]

# Recursive Fibonacci Function
def fibonacci_recursive1(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return (fibonacci_recursive1(n-1)+fibonnaci_recursive1(n-2))

def fibonacci_recursive2(n):
if n<2:
return n
else:
return (fibonacci_recursive2(n-1)+fibonacci_recursive2(n-2))
#?? NameError: global name 'fibonacci_recursive' is not defined

n = 5
print ("Fibonacci of " + str(n) + " is " + str(fibonacci_recursive2(n)))

# Sort
a = [7,1,3,5,2,8]
a.sort()

# Insertion Sort
# Starting with the 2nd position and compare with what's before it
# 2nd position: [7,"3",1,2,4,6] > ["3",7,1,2,4,6]
# 3rd position: [3,7,"1",2,4,6] > [3,"1",7,2,4,6] > ["1",3,7,2,4,6]
# 4th position: [1,3,7,"2",4,6] > [1,3,"2",7,4,6] > [1,"2",3,7,4,6]
# 5th position: [1,2,3,7,"4",6] > [1,2,3,"4",7,6]
# 6th position: [1,2,3,4,7,"6"] > [1,2,3,4,"6",7]
# STOP

def sort_insertion(list):
for index in range(1,len(list)):
value = list[index]
i = index - 1
while i >= 0:
if value < list[i]:     # since the right number is less than the left
list[i+1] = list[i] # swap position - right number gets left number
list[i] = value     # left nymber gets right number
i = i - 1
else:
break

a = [7,1,3,5,9,2,3]
print (a)
sort_insertion(a)
print (a)

b = [56,11,32,511,19,21,23]
print (b)
sort_insertion(b)
print (b)

# Do a bit improvement
def sort_insertion2(list):
for index in range(1,len(list)):
value = list[index]
i = index - 1  # i is the previous value
while i >= 0 and value < list[i]: # since the right number is less than the left
list[i+1] = list[i] # swap position - right number gets left number
list[i] = value     # left nymber gets right number
i = i - 1

sort_insertion2(b)
print (b)
```