Function and Recursions

    A function is a group of statements performing a specific task. When a program gets bigger in size and its complexity grows, it gets difficult for a programmer to keep track on which piece of code is doing what !
 
A function can be reused by the programmer in a given program any number of times.

Syntax :

def function1 () :
print ("hello")

    this function can be called any number of times, any where in the program

function call : whenever we want to call a function, we put the name of the function followed by parenthesis ; fun1( ) : this is called function call

function definition : the part containing the exact set of instructions which are executed during the function call

Types if functions in python :

1. Built in functions : Already present in python. print ( ), range ( ), etc are the examples.

2. user defined functions : defined by the user. fun1( ) is a user defined function.

Functions with arguments : a function can accept some values it can work with. We can put these values in the parenthesis. a function can also return values as show below :

def greet(name) :
gr = "Hello" +name
return gr
a=green("sir") 

Here, "sir" is passed to green in name and a will now contain "hello sir"

Default Parameter Value : We can have a value a default arguement in a function. 
If we specify name="stranger" in the line contain def, this value is used when no argument is passed.

def greet(name="stranger") :
#function body
greet( ) : name will be "stranger" in function body (default)
greet ("sir") : name will be "sir" in function body (passed)

Recursion :
Recursion is a function which call itself. It is used to directly use a mathematically formula as a function.

factorial(n) = n X factorial (n-1)
def factorial (x) :
if i==0 or i==1 :
return 1
else :
return n*factorial(n-1) 

Here, if is base condition which doesn't function any further and factorial(n-1) function calling itself

This works as follows 

Factorial (4) : Function called
4 X factorial(3)
4X [3 X factorial(2)]
4 X 3 X [2 X factorial (1)]
4 X 3 X 2 X [ 1 ] [function returned]

**The programmer need to be extremely careful while working with recurion to ensure that the function doesn't infinitely keep calling itself.

**Recursion is sometimes the most direct way to code an algorithm.

Programs:

1. #functions

def percent(marks):
    p = ((marks[0] + marks[1] + marks[2]+ marks[3])/400 )*100
    return p

marks1 = [45, 78, 86, 77]
percentage1 = percent(marks1)

marks2 = [75, 98, 88, 78]
percentage2 = percent(marks2)
print(percentage1, percentage2)

2. #function simple

def greet(name):
    print("Good Day, "+ name)

def mySum(num1, num2):
    return num1 + num2

greet("cstechiie")
s = mySum(6, 32)
print(s)

3. #Default Arguments 

def greet(name="Stranger"):
    print("Good Day, "+ name)
 
greet("cstechiie") 
greet()

4. #Factorial

# n! = 1 * 2 * 3 * 4...*n
# n! = [1 * 2 * 3 * 4... n-1] *n
# n! = n * (n-1)! 
# n = 0
# product = 1
# for i in range(n):
#     product = product * (i+1)
# print(product)

def factorial_iter(n):
    product = 1
    for i in range(n):
        product = product * (i+1)
    return product

def factorial_recursive(n):
    if n == 1 or n == 0:
        return 1
    return n * factorial_recursive(n-1)

# f = factorial_iter(5)
f = factorial_recursive(0)
print(f)