0% found this document useful (0 votes)
22 views

ACSD06

Uploaded by

varunmunaga15
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views

ACSD06

Uploaded by

varunmunaga15
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 60

COURSE CONTENT

PROGRAMMING FOR PROBLEM SOLVING LABORATORY


II Semester: AE / ME / CE / ECE / EEE / CSE / CSE (AI & ML) / CSE (DS) / CSE (CS) / IT
Course Code Category Hours / Week Credits Maximum Marks
L T P C CIA SEE Total
ACSD06 Foundation
0 1 2 2 40 60 100
Contact Classes: Nil Tutorial Classes: 15 Practical Classes: 30 Total Classes: 45
Prerequisites: There are no prerequisites to take this course.

I. COURSE OVERVIEW:
The course is designed with the fundamental programming skills and problem-solving strategies necessary to
tackle a wide range of computational challenges. Through hands-on programming exercises and projects,
students will learn how to write code, analyze problems and develop solutions using various programming
languages and tools. The course will cover fundamental programming concepts and gradually progress to more
advanced topics.

II. COURSE OBJECTIVES


The students will try to learn:
I. The fundamental programming constructs and use of collection data types in Python.
II. The ability to develop programs using object-oriented features.
III. Basic data structures and algorithms for efficient problem-solving.
IV. Principles of graph theory and be able to apply their knowledge to a wide range of practical problems
across various disciplines.

III. COURSE OUTCOMES:


At the end of the course students should be able to:
CO1 Adapt programming concepts, syntax, and data structures through hands on coding exercises.
CO2 Develop the ability to solve a variety of programming problems and algorithms using python.
CO3 Implement complex and custom data structures to solve real-world problems.
CO4 Demonstrate proficiency in implementing graph algorithms to solve variety of problems and scenarios.
CO5 Develop critical thinking skills to solve the various real-world applications using graph theory.
CO6 Learn the importance of numerical methods and apply them to tackle a wide range of computational
problems.
IV. COURSE CONTENT:

EXERCISES FOR PROGRAMMING FOR PROBLEM SOLVING


LABORATORY

Note: Students are encouraged to bring their own laptops for laboratory
practice sessions.

1. Getting Started Exercises


1.1 Two Sum
Given an array of integers nums and an integer target, return indices of the two numbers such that they
add up to target. You may assume that each input would have exactly one solution, and you may not use
the same element twice. You can return the answer in any order.
Input: nums = [2, 7, 11, 15], target = 9
Output: [0, 1]
Explanation: Because nums[0] + nums[1] == 9, so return [0, 1].
Input: nums = [3, 2, 4], target = 6
Output: [1, 2]
Input: nums = [3, 3], target = 6
Output: [0, 1]

Hints:
def twoSum(self, nums: List[int], target: int) -> List[int]:
a=[]
# Write code here

return a

1.2 Contains Duplicate


Given an integer array nums, return true if any value appears at least twice in the array, and return false if
every element is distinct.
Input: nums = [1, 2, 3, 1]
Output: true
Input: nums = [1, 2, 3, 4]
Output: false
Input: nums = [1, 1, 1, 3, 3, 4, 3, 2, 4, 2]
Output: true

Hints:
def containsDuplicate(self, nums):
a = set() # set can have only distinct elements
# Write code here

return False

1.3 Roman to Integer


Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

For example, 2 is written as II in Roman numeral, just two ones added together. 12 is written as XII, which
is simply X + II. The number 27 is written as XXVII, which is XX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is
not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making
four. The same principle applies to the number nine, which is written as IX. There are six instances where
subtraction is used:
I can be placed before V (5) and X (10) to make 4 and 9.
X can be placed before L (50) and C (100) to make 40 and 90.
C can be placed before D (500) and M (1000) to make 400 and 900.

Given a roman numeral, convert it to an integer.

Input: s = "III"
Output: 3
Input: s = "LVIII"
Output: 58

Hints:
def romanToInt(self, s: str) -> int:
# Write code here

return number

1.4 Plus One


th
You are given a large integer represented as an integer array digits, where each digits[i] is the i digit of
the integer. The digits are ordered from most significant to least significant in left-to-right order. The
large integer does not contain any leading 0's. Increment the large integer by one and return the resulting
array of digits.
Input: digits = [1, 2, 3]
Output: [1, 2, 4]
Explanation: The array represents the integer 123.
Incrementing by one gives 123 + 1 = 124.
Thus, the result should be [1, 2, 4].
Hints:
def plusOne(self, digits: List[int]) -> List[int]:
n = len(digits)
# Write code here

return digits

1.5 Majority Element


Given an array nums of size n, return the majority element. The majority element is the element that
appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.
Input: nums = [3, 2, 3]
Output: 3
Input: nums = [2, 2, 1, 1, 1, 2, 2]
Output: 2

Hints:
def majorityElement(self, nums):
# write code here

1.6 Richest Customer Wealth


th
You are given an m x n integer grid accounts where accounts[i][j] is the amount of money the i customer
th
has in the j bank. Return the wealth that the richest customer has. A customer's wealth is the amount of
money they have in all their bank accounts. The richest customer is the customer that has the maximum
wealth.
Input: accounts = [[1, 2, 3], [3,2,1]]
Output: 6
Explanation:
1st customer has wealth = 1 + 2 + 3 = 6
2nd customer has wealth = 3 + 2 + 1 = 6
Both customers are considered the richest with a wealth of 6 each, so return 6.
Input: accounts = [[1, 5], [7,3],[3,5]]
Output: 10
Explanation:
1st customer has wealth = 6
2nd customer has wealth = 10
3rd customer has wealth = 8
The 2nd customer is the richest with a wealth of 10.
Input: accounts = [[2,8,7],[7,1,3],[1,9,5]]
Output: 17

Hints:
def maximumWealth(self, accounts: List[List[int]]) -> int:
# write code here

1.7 Fizz Buzz


Given an integer n, return a string array answer (1-indexed) where:
answer[i] == "FizzBuzz" if i is divisible by 3 and 5.
answer[i] == "Fizz" if i is divisible by 3.
answer[i] == "Buzz" if i is divisible by 5.
answer[i] == i (as a string) if none of the above conditions are true.
Input: n = 3
Output: ["1","2","Fizz"]
Input: n = 5
Output: ["1","2","Fizz","4","Buzz"]
Input: n = 15
Output: ["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz"]

Hints:
def fizzBuzz(self, n: int) -> List[str]:
# write code here

1.8 Number of Steps to Reduce a Number to Zero


Given an integer num, return the number of steps to reduce it to zero. In one step, if the current number
is even, you have to divide it by 2, otherwise, you have to subtract 1 from it.
Input: num = 14
Output: 6
Explanation:
 14 is even; divide by 2 and obtain 7.
 7 is odd; subtract 1 and obtain 6.
 6 is even; divide by 2 and obtain 3.
 3 is odd; subtract 1 and obtain 2.
 2 is even; divide by 2 and obtain 1.
 1 is odd; subtract 1 and obtain 0.
Input: num = 8
Output: 4
Explanation:
 8 is even; divide by 2 and obtain 4.
 4 is even; divide by 2 and obtain 2.
 2 is even; divide by 2 and obtain 1.
 1 is odd; subtract 1 and obtain 0.
Input: num = 123
Output: 12

Hints:
def numberOfSteps(self, n: int) -> int:
# write code here

1.9 Running Sum of 1D Array


Given an array nums. We define a running sum of an array as runningSum[i] = sum (nums[0]…nums[i]).
Return the running sum of nums.
Input: nums = [1, 2, 3, 4]
Output: [1, 3, 6, 10]
Explanation: Running sum is obtained as follows: [1, 1+2, 1+2+3, 1+2+3+4].
Input: nums = [1, 1, 1, 1, 1]
Output: [1, 2, 3, 4, 5]
Explanation: Running sum is obtained as follows: [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1].
Input: nums = [3, 1, 2, 10, 1]
Output: [3, 4, 6, 16, 17]

Hints:
def runningSum(self, nums: List[int]) -> List[int]:
# write code here

return answer

1.10 Remove Element


Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The order
of the elements may be changed. Then return the number of elements in nums which are not equal to val.
Consider the number of elements in nums which are not equal to val be k, to get accepted, you need to
do the following things:
 Change the array nums such that the first k elements of nums contain the elements which are not
equal to val. The remaining elements of nums are not important as well as the size of nums.
 Return k.
Input: nums = [3, 2, 2, 3], val = 3
Output: 2, nums = [2, 2, _, _]
Explanation: Your function should return k = 2, with the first two elements of nums being 2.
It does not matter what you leave beyond the returned k (hence they are underscores).
Input: nums = [0,1,2,2,3,0,4,2], val = 2
Output: 5, nums = [0,1,4,0,3,_,_,_]
Explanation: Your function should return k = 5, with the first five elements of nums containing 0, 0, 1, 3,
and 4.
Note that the five elements can be returned in any order.
It does not matter what you leave beyond the returned k (hence they are underscores).

Hints:
def removeElement(self, nums: List[int], val: int) -> int:
# write code here

return len(nums)

2. Matrix Operations
2.1 Add Two Matrices
Given two matrices X and Y, the task is to compute the sum of two matrices and then print it in Python.
Input:
X= [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]

Y = [[9, 8, 7],
[6, 5, 4],
[3, 2, 1]]

Output:
Result = [[10, 10, 10],
[10, 10, 10],
[10, 10, 10]]

Hints:
# Program to add two matrices using nested loop
X = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]

Y = [[9,8,7],
[6,5,4],
[3,2,1]]

result = [[0,0,0],
[0,0,0],
[0,0,0]]

# iterate through rows


for i in range(len(X)):
# write code here

for r in result:
print(r)

TRY
1. Take input as X = [[10, 20, 30],[41, 52, 63], [47, 58, 69]] Y = [[19,18,17],[66,35,49], [13,21,11]] and verify
the results.

2.2 Multiply Two Matrices


Given two matrices X and Y, the task is to compute the multiplication of two matrices and then print it.
Input:
X= [[1, 7, 3],
[3, 5, 6],
[6, 8, 9]]

Y = [[1, 1, 1, 2],
[6, 7, 3, 0],
[4, 5, 9, 1]]

Output:
Result = [[55, 65, 49, 5],
[57, 68, 72, 12],
[90, 107, 111, 21]]

Hints:
# Program to multiply two matrices using list comprehension

# take a 3x3 matrix


A = [[12, 7, 3],
[4, 5, 6],
[7, 8, 9]]

# take a 3x4 matrix


B = [[5, 8, 1, 2],
[6, 7, 3, 0],
[4, 5, 9, 1]]

# result will be 3x4


# write code here

for r in result:
print(r)

TRY
1. Take input as X = [[11, 0, 30],[-41, -2, 63], [41, -5, -9]] Y = [[19,-48,17],[-6,35,19], [13,1,-9]] and verify the
results.

2.3 Transpose of a Matrix


A matrix can be implemented using a nested list. Each element is treated as a row of the matrix. Find the
transpose of a matrix in multiple ways.

Input: [[1, 2], [3, 4], [5, 6]]


Output: [[1, 3, 5], [2, 4, 6]]
Explanation: Suppose we are given a matrix
[[1, 2],
[3, 4],
[5, 6]]
Then the transpose of the given matrix will be,
[[1, 3, 5],
[2, 4, 6]]
Hints:
# Program to multiply two matrices using list comprehension

# take a 3x3 matrix


A = [[12, 7, 3],
[4, 5, 6],
[7, 8, 9]]

# result will be 3x4


# write code here

for r in result:
print(r)

TRY
1. Take input as X = [[11, 0, 30],[-41, -2, 63], [41, -5, -9]] and verify the results.

2.4 Matrix Product


Matrix product problem we can solve using list comprehension as a potential shorthand to the
conventional loops. Iterate and find the product of the nested list and at the end return the cumulative
product using function.

Input: The original list: [[1, 4, 5], [7, 3], [4], [46, 7, 3]]
Output: The total element product in lists is: 1622880

Hints:
# Matrix Product using list comprehension + loop

def prod(val):
# write code here

# initializing list
test_list = [[1, 4, 5], [7, 3], [4], [46, 7, 3]]

TRY
1. Take input list: [[1, 4, 5], [7, 3], [4], [46, 7, 3]] and verify the result.

3. Stack
3.1 Stack implementation using List
A stack is a linear data structure that stores items in a Last-In/First-Out (LIFO) or First-In/Last-Out (FILO)
manner. In stack, a new element is added at one end and an element is removed from that end only. The
insert and delete operations are often called push and pop.

The functions associated with stack are:


 empty() – Returns whether the stack is empty
 size() – Returns the size of the stack
 top() / peek() – Returns a reference to the topmost element of the stack
 push(a) – Inserts the element ‘a’ at the top of the stack
 pop() – Deletes the topmost element of the stack
Hints:
# Stack implementation using list
top=0
mymax=5
def createStack():
stack=[]
return stack
def isEmpty(stack):
# write code here

def Push(stack,item):
# write code here

def Pop(stack):
# write code here

# create a stack object
stack = createStack()
while True:
print("1.Push")
print("2.Pop")
print("3.Display")
print("4.Quit")
# write code here

TRY

1. Take input operations as [PUSH(A),PUSH(B),PUSH(C),POP,POP,POP,POP,PUSH(D)] and verify the result.


2. Take input operations as [POP, POP, PUSH (A), PUSH (B), POP, and PUSH(C)] and verify the result.

3.2 Balanced Parenthesis Checking


Given an expression string, write a python program to find whether a given string has balanced
parentheses or not.
Input: {[]{()}}
Output: Balanced
Input: [{}{}(]
Output: Unbalanced
Using stack One approach to check balanced parentheses is to use stack. Each time, when an open
parentheses is encountered push it in the stack, and when closed parenthesis is encountered, match it
with the top of stack and pop it. If stack is empty at the end, return Balanced otherwise, Unbalanced.
Hints:
# Check for balanced parentheses in an expression
open_list = ["[","{","("]
close_list = ["]","}",")"]

# Function to check parentheses


def check(myStr):
# write code here

TRY

1. Take input as {[]{()}[][]} and verify the result.


2. Take input as {[]{()}[]{}} and verify the result.

3.3 Evaluation of Postfix Expression


Given a postfix expression, the task is to evaluate the postfix expression. Postfix expression: The
expression of the form “a b operator” (ab+) i.e., when a pair of operands is followed by an operator.
Input: str = “2 3 1 * + 9 -“
Output: -4
Explanation: If the expression is converted into an infix expression, it will be 2 + (3 * 1) – 9 = 5 – 9 = -4.
Input: str = “100 200 + 2 / 5 * 7 +”
Output: 757
Procedure for evaluation postfix expression using stack:

 Create a stack to store operands (or values).


 Scan the given expression from left to right and do the following for every scanned element.
o If the element is a number, push it into the stack.
o If the element is an operator, pop operands for the operator from the stack. Evaluate the
operator and push the result back to the stack.
 When the expression is ended, the number in the stack is the final answer.

Hints:
# Evaluate value of a postfix expression

# Class to convert the expression


class Evaluate:

# Constructor to initialize the class variables


def __init__(self, capacity):
self.top = -1
self.capacity = capacity

# This array is used a stack


self.array = []

# Check if the stack is empty


def isEmpty(self):
# write code here

def peek(self):
# write code here

def pop(self):
# write code here

def push(self, op):
# write code here

def evaluatePostfix(self, exp):
# write code here

# Driver code
exp = "231*+9-"
obj = Evaluate(len(exp))

# Function call
print("postfix evaluation: %d" % (obj.evaluatePostfix(exp)))

TRY
1. Take input str = “A B + C* D / E +” and verify the result.
2. Take input str = “XYZ- + W+ R / S -” and verify the result.

4. Queue
4.1 Linear Queue using List
Linear queue is a linear data structure that stores items in First in First out (FIFO) manner. With a queue
the least recently added item is removed first. A good example of queue is any queue of consumers for a
resource where the consumer that came first is served first.

Hints:
# Static implementation of linear queue
front=0
rear=0
mymax=5
def createQueue():
queue=[] #empty list
return queue

def isEmpty(queue):
# write code here

def enqueue(queue,item): # insert an element into the queue
# write code here

def dequeue(queue): #remove an element from the queue
# write code here

# Driver code
queue = createQueue()
while True:
print("1.Enqueue")
print("2.Dequeue")
print("3.Display")
print("4.Quit")
# write code here

TRY

1. Take input operations as [ENQUEUE(A),DEQUEUE(),ENQUEUE(B),DEQUEUE(),ENQUEUE(C),DEQUEUE(),]


and verify the result.
2. Take input operations as [ENQUEUE(A), ENQUEUE(B),DEQUEUE(),ENQUEUE(C), DEQUEUE(),ENQUEUE(D),
DEQUEUE(), ENQUEUE(C),DEQUEUE(),] and verify the result.

4.2 Stack using Queues


Implement a last-in-first-out (LIFO) stack using only two queues. The implemented stack should support
all the functions of a normal stack (push, top, pop, and empty).
 void push(int x) Pushes element x to the top of the stack.
 int pop() Removes the element on the top of the stack and returns it.
 int top() Returns the element on the top of the stack.
 boolean empty() Returns true if the stack is empty, false otherwise.
Input:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
Output:
[null, null, null, 2, 2, false]

Hints:
class MyStack:

def __init__(self):
# write code here

def push(self, x: int) -> None:
# write code here

def pop(self) -> int:
# write code here

def top(self) -> int:
# write code here

def empty(self) -> bool:
# write code here

# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()

4.3 Implement Queue using Stacks


Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support
all the functions of a normal queue (push, peek, pop, and empty).
 void push(int x) Pushes element x to the back of the queue.
 int pop() Removes the element from the front of the queue and returns it.
 int peek() Returns the element at the front of the queue.
 boolean empty() Returns true if the queue is empty, false otherwise.
Input:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
Output:
[null, null, null, 1, 1, false]

Hints:
class MyQueue:

def __init__(self):
# write code here

def push(self, x: int) -> None:
# write code here

def pop(self) -> int:
# write code here

def peek(self) -> int:
# write code here

def empty(self) -> bool:
# write code here

# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

4.4 Circular Queue


A Circular Queue is an extended version of a normal queue where the last element of the queue is
connected to the first element of the queue forming a circle. The operations are performed based on FIFO
(First In First Out) principle. It is also called ‘Ring Buffer’.
Operations on Circular Queue:
 Front: Get the front item from the queue.
 Rear: Get the last item from the queue.
 enQueue(value) This function is used to insert an element into the circular queue. In a circular queue,
the new element is always inserted at the rear position.
 Check whether the queue is full – [i.e., the rear end is in just before the front end in a
circular manner].
 If it is full then display Queue is full.
 If the queue is not full then, insert an element at the end of the queue.
 deQueue() This function is used to delete an element from the circular queue. In a circular queue, the
element is always deleted from the front position.
 Check whether the queue is Empty.
 If it is empty then display Queue is empty.
 If the queue is not empty, then get the last element and remove it from the
queue.
Implement Circular Queue using Array:
1. Initialize an array queue of size n, where n is the maximum number of elements that the queue can
hold.
2. Initialize two variables front and rear to -1.
3. Enqueue: To enqueue an element x into the queue, do the following:
 Increment rear by 1.
 If rear is equal to n, set rear to 0.
 If front is -1, set front to 0.
 Set queue[rear] to x.
4. Dequeue: To dequeue an element from the queue, do the following:
 Check if the queue is empty by checking if front is -1.
 If it is, return an error message indicating that the queue is empty.
 Set x to queue [front].
 If front is equal to rear, set front and rear to -1.
 Otherwise, increment front by 1 and if front is equal to n, set front to 0.
 Return x.
Hints:
class CircularQueue():

# constructor
def __init__(self, size): # initializing the class
self.size = size

# initializing queue with none


self.queue = [None for i in range(size)]
self.front = self.rear = -1

def enqueue(self, data):


# Write code here

def dequeue(self):
# Write code here

def display(self):
# Write code here

# Driver Code
ob = CircularQueue(5)
ob.enqueue(14)
ob.enqueue(22)
ob.enqueue(13)
ob.enqueue(-6)
ob.display()
print ("Deleted value = ", ob.dequeue())
print ("Deleted value = ", ob.dequeue())
ob.display()
ob.enqueue(9)
ob.enqueue(20)
ob.enqueue(5)
ob.display()
TRY

1. Take input operations as [ENQUEUE(A,B,C,D,E,F),DEQUEUE(),DEQUEUE(),DEQUEUE(),ENQUEUE(G,H,I] and


verify the result.
2. Take input operations as [DEQUEUE(),ENQUEUE(A,B,C,D,E,F),DEQUEUE(),ENQUEUE(G,H,I] and verify the
result.

5. Graph Representation
5.1 Build a graph
You are given an integer n. Determine if there is an unconnected graph with n vertices that contains at
least two connected components and contains the number of edges that is equal to the number of
vertices. Each vertex must follow one of these conditions:
 Its degree is less than or equal to 1.
 It's a cut-vertex.
Note:
 The graph must be simple.
 Loops and multiple edges are not allowed.
Input: First line: n
Output: Print Yes if it is an unconnected graph. Otherwise, print No.
Sample Input Sample Output
3 No

Constraints: 1 ≤ n ≤ 100
Explanation: There is only one graph with the number of edges equal to the number of vertices (triangle)
which is connected.

5.2 Number of Sink Nodes in a Graph


Given a Directed Acyclic Graph of n nodes (numbered from 1 to n) and m edges. The task is to find the
number of sink nodes. A sink node is a node such that no edge emerges out of it.

Input: n = 4, m = 2, edges[] = {{2, 3}, {4, 3}}

Only node 1 and node 3 are sink nodes.


Input: n = 4, m = 2, edges[] = {{3, 2}, {3, 4}}

Output: 3

The idea is to iterate through all the edges. And for each edge, mark the source node from which the
edge emerged out. Now, for each node check if it is marked or not. And count the unmarked nodes.

Algorithm:

1. Make any array A[] of size equal to the number of nodes and initialize to 1.

2. Traverse all the edges one by one, say, u -> v.

(i) Mark A[u] as 1.

3. Now traverse whole array A[] and count number of unmarked nodes.

Hints:
# Program to count number if sink nodes

# Return the number of Sink Nodes.


def countSink(n, m, edgeFrom, edgeTo):
# Write code here

return count

# Driver Code
n = 4
m = 2
edgeFrom = [2, 4]
edgeTo = [3, 3]

print(countSink(n, m, edgeFrom, edgeTo))

5.3 Connected Components in a Graph


Given n, i.e. total number of nodes in an undirected graph numbered from 1 to n and an integer e, i.e.
total number of edges in the graph. Calculate the total number of connected components in the graph. A
connected component is a set of vertices in a graph that are linked to each other by paths.

Input: First line of input line contains two integers’ n and e. Next e line will contain two integers u and v
meaning that node u and node v are connected to each other in undirected fashion.

Output: For each input graph print an integer x denoting total number of connected components.

Sample Input Sample Output


8 5 3
1 2
2 3
2 4
3 5
6 7
Constraints: All the input values are well within the integer range.
5.4 Transpose Graph
Transpose of a directed graph G is another directed graph on the same set of vertices with all of the
edges reversed compared to the orientation of the corresponding edges in G. That is, if G contains an
edge (u, v) then the converse/transpose/reverse of G contains an edge (v, u) and vice versa. Given a graph
(represented as adjacency list), we need to find another graph which is the transpose of the given graph.

Input: figure (i) is the input graph.

Output: figure (ii) is the transpose graph of the given graph.


0--> 2
1--> 0 4
2--> 3
3--> 0 4
4--> 0

Explanation: We traverse the adjacency list and as we find a vertex v in the adjacency list of vertex u
which indicates an edge from u to v in main graph, we just add an edge from v to u in the transpose
graph i.e. add u in the adjacency list of vertex v of the new graph. Thus traversing lists of all vertices of
main graph we can get the transpose graph.

Hints:
# find transpose of a graph.
# function to add an edge from vertex source to vertex dest
def addEdge(adj, src, dest):
adj[src].append(dest)

# function to print adjacency list of a graph


def displayGraph(adj, v):

print()

# function to get Transpose of a graph taking adjacency list of given graph and that
of Transpose graph
def transposeGraph(adj, transpose, v):
# traverse the adjacency list of given graph and for each edge (u, v) add
# an edge (v, u) in the transpose graph's adjacency list

# Driver Code
v = 5
adj = [[] for i in range(v)]
addEdge(adj, 0, 1)
addEdge(adj, 0, 4)
addEdge(adj, 0, 3)
addEdge(adj, 2, 0)
addEdge(adj, 3, 2)
addEdge(adj, 4, 1)
addEdge(adj, 4, 3)

# Finding transpose of graph represented by adjacency list adj[]


transpose = [[]for i in range(v)]
transposeGraph(adj, transpose, v)

# Displaying adjacency list of transpose graph i.e. b


displayGraph(transpose, v)

TRY

1. Take input operations as addEdge( A, B), addEdge( A, D), addEdge( A, C), addEdge( C, A),addEdge(A, D),
addEdge( C, B), addEdge( B, C) and verify the result.

5.5 Counting Triplets


You are given an undirected, complete graph G that contains N vertices. Each edge is colored in either
white or black. You are required to determine the number of triplets (i, j, k) (1 ≤ i < j < k ≤ N) of vertices
such that the edges (i, j), (j, k), (i, k) are of the same color.

There are M white edges and (N (N-1)/2) – M black edges.

Input:
5 5
First line: Two integers – N and M (3 ≤ N ≤ 10 , 1 ≤ M ≤ 3 * 10 )
th
(i+1) line: Two integers – ui and vi (1 ≤ ui, vi ≤ N) denoting that the edge (ui, vi) is white in color.

Note: The conditions (ui, vi) ≠ (uj, vj) and (ui, vi) ≠ (vj, uj) are satisfied for all 1 ≤ i < j ≤ M.

.Output: Print an integer that denotes the number of triples that satisfy the mentioned condition.

Sample Input Sample Output


5 3 4
1 5
2 5
3 5

Explanation: The triplets are: {(1, 2, 3), (1, 2, 4), (2, 3, 4), (1, 3, 4)}

The graph consisting of only white edges:


The graph consisting of only black edges:

6. Graph Routing Algorithms


6.1 Seven Bridges of Konigsberg
There was 7 bridges connecting 4 lands around the city of Königsberg in Prussia. Was there any way to
start from any of the land and go through each of the bridges once and only once? Euler first introduced
graph theory to solve this problem. He considered each of the lands as a node of a graph and each bridge
in between as an edge in between. Now he calculated if there is any Eulerian Path in that graph. If there is
an Eulerian path then there is a solution otherwise not.

There are n nodes and m bridges in between these nodes. Print the possible path through each node
using each edges (if possible), traveling through each edges only once.

Input: [[0, 1, 0, 0, 1],


[1, 0, 1, 1, 0],
[0, 1, 0, 1, 0],
[0, 1, 1, 0, 0],
[1, 0, 0, 0, 0]]

Output: 5 -> 1 -> 2 -> 4 -> 3 -> 2

Input: [[0, 1, 0, 1, 1],


[1, 0, 1, 0, 1],
[0, 1, 0, 1, 1],
[1, 1, 1, 0, 0],
[1, 0, 1, 0, 0]]

Output: "No Solution"

Hints:
# A Python program to print Eulerian trail in a
# given Eulerian or Semi-Eulerian Graph
from collections import defaultdict

class Graph:
# Constructor and destructor
def __init__(self, V):
self.V = V
self.adj = defaultdict(list)

# functions to add and remove edge


def addEdge(self, u, v):
def rmvEdge(self, u, v):

# Methods to print Eulerian tour
def printEulerTour(self):
# Find a vertex with odd degree

# Print tour starting from oddv
self.printEulerUtil(u)
print()
def printEulerUtil(self, u):
# Recur for all the vertices adjacent to this vertex
for v in self.adj[u]:
# If edge u-v is not removed and it's a valid next edge
# The function to check if edge u-v can be considered as next edge in Euler Tout
def isValidNextEdge(self, u, v):
# The edge u-v is valid in one of the following two cases:

# 1) If v is the only adjacent vertex of u


# 2) If there are multiple adjacents, then u-v is not a bridge


# Do following steps to check if u-v is a bridge
# 2.a) count of vertices reachable from u

# 2.b) Remove edge (u, v) and after removing


# the edge, count vertices reachable from u

# 2.c) Add the edge back to the graph


self.addEdge(u, v)

# 2.d) If count1 is greater, then edge (u, v) is a bridge


return False if count1 > count2 else True

# A DFS based function to count reachable vertices from v

def DFSCount(self, v, visited):


# Mark the current node as visited

# Recur for all the vertices adjacent to this vertex

# utility function to form edge between two vertices source and dest
def makeEdge(src, dest):
graph.addEdge(src, dest)

# Driver code
# Let us first create and test graphs shown in above figure
g1 = Graph(4)
g1.addEdge(0, 1)
g1.addEdge(0, 2)
g1.addEdge(1, 2)
g1.addEdge(2, 3)
g1.printEulerTour()

g3 = Graph(4)
g3.addEdge(0, 1)
g3.addEdge(1, 0)
g3.addEdge(0, 2)
g3.addEdge(2, 0)
g3.addEdge(2, 3)
g3.addEdge(3, 1)
g3.printEulerTour()

TRY

1. Take input: [[1, 0, 1, 0, 1], [1, 0, 1, 0, 0], [1, 1, 0, 1, 0], [0, 0, 1, 0, 0], [1, 0, 1, 0, 0]] and verify the result.
2. Take input: [[0, 0, 1, 0, 1], [0, 0, 1, 0, 0], [1, 0, 0, 1, 0], [1, 0, 1, 0, 0], [1, 1, 1, 0, 0]] and verify the result.

6.2 Hamiltonian Cycle


The Hamiltonian cycle of undirected graph G = <V, E> is the cycle containing each vertex in V. If graph
contains a Hamiltonian cycle, it is called Hamiltonian graph otherwise it is non-Hamiltonian.
Hamiltonian Path in an undirected graph is a path that visits each vertex exactly once. A Hamiltonian cycle
(or Hamiltonian circuit) is a Hamiltonian path such that there is an edge (in the graph) from the last vertex
to the first vertex of the Hamiltonian path. Consider a graph G, and determine whether a given graph
contains Hamiltonian cycle or not. If it contains, then prints the path. Following are the input and output
of the required function.
Input: A 2D array graph [V][V] where V is the number of vertices in graph and graph [V][V] is adjacency
matrix representation of the graph. A value graph[i][j] is 1 if there is a direct edge from i to j, otherwise
graph[i][j] is 0.

th
Output: An array path [V] that should contain the Hamiltonian Path. Path [i] should represent the i
vertex in the Hamiltonian Path. The code should also return false if there is no Hamiltonian Cycle in the
graph.

For example, a Hamiltonian Cycle in the following graph is {0, 1, 2, 4, 3, 0}.


(0)--(1)--(2)

| /\ |

| / \ |

| / \ |

(3)-------(4)

And the following graph doesn’t contain any Hamiltonian Cycle.

(0)--(1)--(2)

| /\ |

| / \ |

| / \ |

(3) (4)

Backtracking Algorithm: Create an empty path array and add vertex 0 to it. Add other vertices, starting
from the vertex 1. Before adding a vertex, check for whether it is adjacent to the previously added vertex
and not already added. If we find such a vertex, we add the vertex as part of the solution. If we do not find
a vertex then we return false.

Hints:
# Python program for solution of Hamiltonian cycle problem

class Graph():
def __init__(self, vertices):
self.graph = [[0 for column in range(vertices)]
for row in range(vertices)]
self.V = vertices

def isSafe(self, v, pos, path):


# Check if current vertex and last vertex in path are adjacent

# A recursive utility function to solve Hamiltonian cycle problem


def hamCycleUtil(self, path, pos):

def hamCycle(self):

def printSolution(self, path):


print ("Solution Exists: Following","is one Hamiltonian Cycle")
for vertex in path:
print (vertex, end = " ")
print (path[0], "\n")

# Driver Code

''' Let us create the following graph


(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3)-------(4) '''
g1 = Graph(5)
g1.graph = [ [0, 1, 0, 1, 0], [1, 0, 1, 1, 1],
[0, 1, 0, 0, 1,],[1, 1, 0, 0, 1],
[0, 1, 1, 1, 0], ]

# Print the solution


g1.hamCycle();

''' Let us create the following graph


(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3) (4) '''
g2 = Graph(5)
g2.graph = [ [0, 1, 0, 1, 0], [1, 0, 1, 1, 1],
[0, 1, 0, 0, 1,], [1, 1, 0, 0, 0],
[0, 1, 1, 0, 0], ]

# Print the solution


g2.hamCycle();

TRY
1. Take a graph = [ [1, 1, 0, 1, 0], [1, 1, 1, 1, 1], [0, 1, 0, 1, 1,], [1, 1, 0, 1, 0], [0, 1, 1, 1, 0],] and verify the
results.

6.3 Number of Hamiltonian Cycle


Given an undirected complete graph of N vertices where N > 2. The task is to find the number of different
Hamiltonian cycle of the graph.

Complete Graph: A graph is said to be complete if each possible vertices is connected through an Edge.
Hamiltonian Cycle: It is a closed walk such that each vertex is visited at most once except the initial
vertex. and it is not necessary to visit all the edges.

Formula: (N – 1)! / 2

Input: N = 6
Output: Hamiltonian cycles = 60
Input: N = 4
Output: Hamiltonian cycles = 3

Explanation: Let us take the example of N = 4 complete undirected graph, The 3 different Hamiltonian
cycle is as shown below:

Hints:
# Number of Hamiltonian cycles
import math as mt

# Function that calculates number of Hamiltonian cycle


def Cycles(N):

# Driver code
N = 5
Number = Cycles(N)
print("Hamiltonian cycles = ", Number)

TRY
1. Take an input N=7 and verify the results.
2. Take an input N=10 and verify the results.

7. Shortest Path Algorithms


7.1 Travelling Salesman Problem

Given a set of cities and the distance between every pair of cities, the problem is to find the shortest
possible route that visits every city exactly once and returns to the starting point. The problem statement
gives a list of cities along with the distances between each city.

Objective: To start from the origin city, visit other cities only once, and return to the original city again.
Our target is to find the shortest possible path to complete the round-trip route.
Here a graph is given where 1, 2, 3, and 4 represent the cities, and the weight associated with every edge
represents the distance between those cities. The goal is to find the shortest possible path for the tour
that starts from the origin city, traverses the graph while only visiting the other cities or nodes once, and
returns to the origin city.
For the above graph, the optimal route is to follow the minimum cost path: 1 – 2 – 4 – 3 - 1. And this
shortest route would cost 10 + 25 + 30 + 15 =80

Algorithm for Traveling Salesman Problem: We will use the dynamic programming approach to solve
the Travelling Salesman Problem (TSP).

 A graph G=(V, E), which is a set of vertices and edges.


 V is the set of vertices.
 E is the set of edges.
 Vertices are connected through edges.
 Dist(i,j) denotes the non-negative distance between two vertices, i and j.

Let’s assume S is the subset of cities and belongs to {1, 2, 3, …, n} where 1, 2, 3…n are the cities and i, j are
two cities in that subset. Now cost(i, S, j) is defined in such a way as the length of the shortest path visiting
node in S, which is exactly once having the starting and ending point as i and j respectively.

For example, cost (1, {2, 3, 4}, 1) denotes the length of the shortest path where:
 Starting city is 1
 Cities 2, 3, and 4 are visited only once
 The ending point is 1

The dynamic programming algorithm would be:


 Set cost(i,, i) = 0, which means we start and end at i, and the cost is 0.
 When |S| > 1, we define cost(i, S, 1) = ∝ where i !=1 . Because initially, we do not know the exact
cost to reach city i to city 1 through other cities.
 Now, we need to start at 1 and complete the tour. We need to select the next city in such a way-
 cost(i, S, j) = min cost (i, S−{i}, j) + dist(i, j) where i ∈ S and i ≠ j
For the given figure above, the adjacency matrix would be the following:
dist(i, j) 1 2 3 4
1 0 10 15 20
2 10 0 35 25
3 15 35 0 30
4 20 25 30 0

Now S = {1, 2, 3, 4}. There are four elements. Hence the number of subsets will be 2^4 or 16. Those
subsets are-
1) |S| = Null:
{Φ}

2) |S| = 1:
{{1}, {2}, {3}, {4}}

3) |S| = 2:
{{1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}}

4) |S| = 3:
{{1, 2, 3}, {1, 2, 4}, {2, 3, 4}, {1, 3, 4}}

5) |S| = 4:
{{1, 2, 3, 4}}

As we are starting at 1, we could discard the subsets containing city 1. The algorithm calculation steps:
1) |S| = Φ:
cost (2, Φ, 1) = dist(2, 1) = 10
cost (3, Φ, 1) = dist(3, 1) = 15
cost (4, Φ, 1) = dist(4, 1) = 20

2) |S| = 1:
cost (2, {3}, 1) = dist(2, 3) + cost (3, Φ, 1) = 35+15 = 50
cost (2, {4}, 1) = dist(2, 4) + cost (4, Φ, 1) = 25+20 = 45
cost (3, {2}, 1) = dist(3, 2) + cost (2, Φ, 1) = 35+10 = 45
cost (3, {4}, 1) = dist(3, 4) + cost (4, Φ, 1) = 30+20 = 50
cost (4, {2}, 1) = dist(4, 2) + cost (2, Φ, 1) = 25+10 = 35
cost (4, {3}, 1) = dist(4, 3) + cost (3, Φ, 1) = 30+15 = 45

3) |S| = 2:
cost (2, {3, 4}, 1) = min [ dist[2,3] + Cost(3,{4},1) = 35+50 = 85,
dist[2,4]+Cost(4,{3},1) = 25+45 = 70 ] = 70
cost (3, {2, 4}, 1) = min [ dist[3,2] + Cost(2,{4},1) = 35+45 = 80,
dist[3,4]+Cost(4,{2},1) = 30+35 = 65 ] = 65
cost (4, {2, 3}, 1) = min [ dist[4,2] + Cost(2,{3},1) = 25+50 = 75
dist[4,3] + Cost(3,{2},1) = 30+45 = 75 ] = 75
4) |S| = 3:
cost (1, {2, 3, 4}, 1) = min [ dist[1,2]+Cost(2,{3,4},1) = 10+70 = 80
dist[1,3]+Cost(3,{2,4},1) = 15+65 = 80
dist[1,4]+Cost(4,{2,3},1) = 20+75 = 95 ] = 80

So the optimal solution would be 1-2-4-3-1

Hints:
from sys import maxsize
from itertools, import permutations
V = 4
def tsp(graph, s):

# Driver code
graph = [[0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]]
s = 0
print(tsp(graph, s))

TRY
1. Take a below table values and verify the results.

dist(i, j) 1 2 3 4
1 0 40 25 40
2 20 0 35 25
3 25 35 0 60
4 40 25 30 0

7.2 Shortest Paths from Source to all Vertices (Dijkstra's Algorithm)


Given a graph and a source vertex in the graph, find the shortest paths from the source to all vertices in
the given graph.
Input: src = 0, the graph is shown below.

Output: 0 4 12 19 21 11 9 8 14

Explanation: The distance from 0 to 1 = 4.


The minimum distance from 0 to 2 = 12. 0->1->2
The minimum distance from 0 to 3 = 19. 0->1->2->3
The minimum distance from 0 to 4 = 21. 0->7->6->5->4
The minimum distance from 0 to 5 = 11. 0->7->6->5
The minimum distance from 0 to 6 = 9. 0->7->6
The minimum distance from 0 to 7 = 8. 0->7
The minimum distance from 0 to 8 = 14. 0->1->2->8

Hints:
# Dijkstra's single source shortest path algorithm. The program is for adjacency
matrix representation of the graph

# Library for INT_MAX


import sys

class Graph():
def __init__(self, vertices):
self.V = vertices
self.graph = [[0 for column in range(vertices)]
for row in range(vertices)]

def printSolution(self, dist):


print("Vertex \tDistance from Source")
for node in range(self.V):
print(node, "\t", dist[node])

# A utility function to find the vertex with minimum distance value,


# from the set of vertices not yet included in shortest path tree
def minDistance(self, dist, sptSet):

# Function that implements Dijkstra's single source shortest path


# algorithm for a graph represented using adjacency matrix representation
def dijkstra(self, src):

# Driver's code
g = Graph(9)
g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0],
[4, 0, 8, 0, 0, 0, 0, 11, 0],
[0, 8, 0, 7, 0, 4, 0, 0, 2],
[0, 0, 7, 0, 9, 14, 0, 0, 0],
[0, 0, 0, 9, 0, 10, 0, 0, 0],
[0, 0, 4, 14, 10, 0, 2, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 1, 6],
[8, 11, 0, 0, 0, 0, 1, 0, 7],
[0, 0, 2, 0, 0, 0, 6, 7, 0]
]

g.dijkstra(0)

TRY
1. Take a below graph and verify the results.

7.3 Shortest Cycle in an Undirected Unweighted Graph


Given an undirected unweighted graph. The task is to find the length of the shortest cycle in the given
graph. If no cycle exists print -1.

Input: Consider the graph given below

Output: 4
Cycle 6 -> 1 -> 5 -> 0 -> 6

Input: Consider the graph given below


Output: 3
Cycle 6 -> 1 -> 2 -> 6

Hints:
from sys import maxsize as INT_MAX
from collections import deque

N = 100200

gr = [0] * N
for i in range(N):
gr[i] = []

# Function to add edge


def add_edge(x: int, y: int) -> None:
global gr
gr[x].append(y)
gr[y].append(x)

# Function to find the length of the shortest cycle in the graph


def shortest_cycle(n: int) -> int:

# To store length of the shortest cycle


ans = INT_MAX

# For all vertices


# write code here

# If graph contains no cycle


if ans == INT_MAX:
return -1

# If graph contains cycle


else:
return ans

# Driver Code
# Number of vertices
n = 7
# Add edges
add_edge(0, 6)
add_edge(0, 5)
add_edge(5, 1)
add_edge(1, 6)
add_edge(2, 6)
add_edge(2, 3)
add_edge(3, 4)
add_edge(4, 1)

# Function call
print(shortest_cycle(n))

TRY
1. Take a below graph and verify the results.

7.4 Count Unique and all Possible Paths in a M x N Matrix


Count unique paths: The problem is to count all unique possible paths from the top left to the bottom
right of a M X N matrix with the constraints that from each cell you can either move only to the right or
down.

Input: M = 2, N = 2

Output: 2

Explanation: There are two paths


(0, 0) -> (0, 1) -> (1, 1)
(0, 0) -> (1, 0) -> (1, 1)

Input: M = 2, N = 3

Output: 3

Explanation: There are three paths


(0, 0) -> (0, 1) -> (0, 2) -> (1, 2)
(0, 0) -> (0, 1) -> (1, 1) -> (1, 2)
(0, 0) -> (1, 0) -> (1, 1) -> (1, 2)

Count all possible paths: We can recursively move to right and down from the start until we reach the
destination and then add up all valid paths to get the answer.
Procedure:
 Create a recursive function with parameters as row and column index
 Call this recursive function for N-1 and M-1
 In the recursive function
 If N == 1 or M == 1 then return 1
 else call the recursive function with (N-1, M) and (N, M-1) and return the sum of this
 Print the answer

Hints:
# Python program to count all possible paths from top left to bottom right

# Function to return count of possible paths to reach cell at row number m and column
number n from the topmost leftmost cell (cell at 1, 1)

def numberOfPaths(m, n):


# Driver program to test above function


m = 3
n = 3
print(numberOfPaths(m, n))

TRY
1. Take input : M = 3, N = 2 and verify the results.
2. Take input : M = 2, N = 1 and verify the results.

8. Graph Coloring
8.1 Graph Coloring using Greedy Algorithm
Greedy algorithm is used to assign colors to the vertices of a graph. It doesn’t guarantee to use minimum
colors, but it guarantees an upper bound on the number of colors. The basic algorithm never uses more
than d+1 colors where d is the maximum degree of a vertex in the given graph.

Basic Greedy Coloring Algorithm:


1. Color first vertex with first color.
2. Do following for remaining V-1 vertices.
a) Consider the currently picked vertex and color it with the lowest numbered color that has not been
used on any previously colored vertices adjacent to it. If all previously used colors appear on vertices
adjacent to v, assign a new color to it.

Hints:
# Implement greedy algorithm for graph coloring

def addEdge(adj, v, w):


adj[v].append(w)
# Note: the graph is undirected
adj[w].append(v)
return adj

# Assigns colors (starting from 0) to all


# vertices and prints the assignment of colors
def greedyColoring(adj, V):

# Driver Code
g1 = [[] for i in range(5)]
g1 = addEdge(g1, 0, 1)
g1 = addEdge(g1, 0, 2)
g1 = addEdge(g1, 1, 2)
g1 = addEdge(g1, 1, 3)
g1 = addEdge(g1, 2, 3)
g1 = addEdge(g1, 3, 4)
print("Coloring of graph 1 ")
greedyColoring(g1, 5)

g2 = [[] for i in range(5)]


g2 = addEdge(g2, 0, 1)
g2 = addEdge(g2, 0, 2)
g2 = addEdge(g2, 1, 2)
g2 = addEdge(g2, 1, 4)
g2 = addEdge(g2, 2, 4)
g2 = addEdge(g2, 4, 3)
print("\nColoring of graph 2")
greedyColoring(g2, 5)

Output:
Coloring of graph 1
Vertex 0 ---> Color 0
Vertex 1 ---> Color 1
Vertex 2 ---> Color 2
Vertex 3 ---> Color 0
Vertex 4 ---> Color 1

Coloring of graph 2
Vertex 0 ---> Color 0
Vertex 1 ---> Color 1
Vertex 2 ---> Color 2
Vertex 3 ---> Color 0
Vertex 4 ---> Color 3

8.2 Coloring a Cycle Graph


Given the number of vertices in a Cyclic Graph. The task is to determine the Number of colors required to
color the graph so that no two adjacent vertices have the same color.

Approach:
 If the no. of vertices is Even then it is Even Cycle and to color such graph we require 2 colors.
 If the no. of vertices is Odd then it is Odd Cycle and to color such graph we require 3 colors.
Input: Vertices = 3
Output: No. of colors require is: 3

Input: vertices = 4
Output: No. of colors require is: 2

Example 1: Even Cycle: Number of vertices = 4

Color required = 2

Example 2: Odd Cycle: Number of vertices = 5

Color required = 3
Hints:
# Find the number of colors required to color a cycle graph

# Function to find Color required.


def Color(vertices):

# Driver Code
vertices = 3
print ("No. of colors require is:", Color(vertices))

8.3 m Coloring Problem


Given an undirected graph and a number m, determine if the graph can be colored with at most m colors
such that no two adjacent vertices of the graph are colored with the same color.

Note: Here coloring of a graph means the assignment of colors to all vertices
Following is an example of a graph that can be colored with 3 different colors:

Input: graph = {0, 1, 1, 1},


{1, 0, 1, 0},
{1, 1, 0, 1},
{1, 0, 1, 0}
Output: Solution Exists: Following are the assigned colors: 1 2 3 2
Explanation: By coloring the vertices with following colors, adjacent vertices does not have same colors

Input: graph = {1, 1, 1, 1},


{1, 1, 1, 1},
{1, 1, 1, 1},
{1, 1, 1, 1}
Output: Solution does not exist
Explanation: No solution exits

Generate all possible configurations of colors. Since each node can be colored using any of the m
available colors, the total number of color configurations possible is mV. After generating a configuration
of color, check if the adjacent vertices have the same color or not. If the conditions are met, print the
combination and break the loop

Follow the given steps to solve the problem:

 Create a recursive function that takes the current index, number of vertices and output color array
 If the current index is equal to number of vertices. Check if the output color configuration is safe, i.e
check if the adjacent vertices do not have same color. If the conditions are met, print the
configuration and break
 Assign a color to a vertex (1 to m)
 For every assigned color recursively call the function with next index and number of vertices
 If any recursive function returns true break the loop and returns true.

Hints:
# Number of vertices in the graph
# define 4 4

# check if the colored graph is safe or not

def isSafe(graph, color):


# check for every edge
for i in range(4):
for j in range(i + 1, 4):
if (graph[i][j] and color[j] == color[i]):
return False
return True

def graphColoring(graph, m, i, color):


# write your code here

# /* A utility function to print solution */

def printSolution(color):
print("Solution Exists:" " Following are the assigned colors ")
for i in range(4):
print(color[i], end=" ")

# Driver code
# /* Create following graph and test whether it is 3 colorable
# (3)---(2)
# | / |
# | / |
# | / |
# (0)---(1)
# */
graph = [
[0, 1, 1, 1],
[1, 0, 1, 0],
[1, 1, 0, 1],
[1, 0, 1, 0],
]
m = 3 # Number of colors

# Initialize all color values as 0.


# This initialization is needed
# correct functioning of isSafe()
color = [0 for i in range(4)]

# Function call
if (not graphColoring(graph, m, 0, color)):
print("Solution does not exist")

8.4 Edge Coloring of a Graph


Edge coloring of a graph is an assignment of “colors” to the edges of the graph so that no two adjacent
edges have the same color with an optimal number of colors. Two edges are said to be adjacent if they
are connected to the same vertex. There is no known polynomial time algorithm for edge-coloring every
graph with an optimal number of colors.

Input: u1 = 1, v1 = 4
u2 = 1, v2 = 2
u3 = 2, v3 = 3
u4 = 3, v4 = 4

Output: Edge 1 is of color 1


Edge 2 is of color 2
Edge 3 is of color 1
Edge 4 is of color 2

The above input shows the pair of vertices (ui, vi) who have an edge between them. The output shows the
color assigned to the respective edges.

Edge colorings are one of several different types of graph coloring problems. The above figure of a Graph
shows an edge coloring of a graph by the colors green and black, in which no adjacent edge have the
same color.
Algorithm:
1. Use BFS traversal to start traversing the graph.
2. Pick any vertex and give different colors to all of the edges connected to it, and mark those edges as
colored.
3. Traverse one of it’s edges.
4. Repeat step to with a new vertex until all edges are colored.

Hints:
# Edge Coloring

from queue import Queue

# function to determine the edge colors


def colorEdges(ptr, gra, edgeColors, isVisited):
# Write your code here

# Driver Function
empty=set()
# declaring vector of vector of pairs, to define Graph
gra=[]
edgeColors=[]
isVisited=[False]*100000

ver = 4
edge = 4
gra=[[] for _ in range(ver)]
edgeColors=[-1]*edge
gra[0].append((1, 0))
gra[1].append((0, 0))
gra[1].append((2, 1))
gra[2].append((1, 1))
gra[2].append((3, 2))
gra[3].append((2, 2))
gra[0].append((3, 3))
gra[3].append((0, 3))
colorEdges(0, gra, edgeColors, isVisited)

# printing all the edge colors


for i in range(edge):
print("Edge {} is of color {}".format(i + 1,edgeColors[i] + 1))

TRY
1. Write a program to implement graph coloring and edge coloring by consider the below graph and
verify the results.
9. Graph Traversal
9.1 Breadth First Search
The Breadth First Search (BFS) algorithm is used to search a graph data structure for a node that meets
a set of criteria. It starts at the root of the graph and visits all nodes at the current depth level before
moving on to the nodes at the next depth level.
For a given graph G, print BFS traversal from a given source vertex.

Hints:
# BFS traversal from a given source vertex.

from collections import defaultdict

# This class represents a directed graph using adjacency list representation


class Graph:

# Constructor
def __init__(self):
# Default dictionary to store graph
self.graph = defaultdict(list)

# Function to add an edge to graph


def addEdge(self, u, v):
self.graph[u].append(v)

# Function to print a BFS of graph


def BFS(self, s):
# Write your code here

# Create a graph given in the above diagram


g = Graph()
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)

print("Following is Breadth First Traversal" " (starting from vertex 2)")


g.BFS(2)
Output: Following is Breadth First Traversal (starting from vertex 2)
2031

9.2 Depth First Search


Depth First Traversal (or DFS) for a graph is similar to Depth First Traversal of a tree. The only catch here
is, that, unlike trees, graphs may contain cycles (a node may be visited twice). To avoid processing a node
more than once, use a boolean visited array. A graph can have more than one DFS traversal.

For a given graph G, print DFS traversal from a given source vertex.

Input: n = 4, e = 6
0 -> 1, 0 -> 2, 1 -> 2, 2 -> 0, 2 -> 3, 3 -> 3

Output: DFS from vertex 1: 1 2 0 3

Explanation:
DFS Diagram:

Input: n = 4, e = 6
2 -> 0, 0 -> 2, 1 -> 2, 0 -> 1, 3 -> 3, 1 -> 3

Output: DFS from vertex 2: 2 0 1 3

Explanation:
DFS Diagram:
Hints:
# DFS traversal from a given graph
from collections import defaultdict

# This class represents a directed graph using adjacency list representation


class Graph:
# Constructor
def __init__(self):
# Default dictionary to store graph
self.graph = defaultdict(list)

# Function to add an edge to graph


def addEdge(self, u, v):
self.graph[u].append(v)

# A function used by DFS


def DFSUtil(self, v, visited):

# The function to do DFS traversal. It uses recursive DFSUtil()

def DFS(self, v):


# Write your code here

# Driver's code
g = Graph()
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)
print("Following is Depth First Traversal (starting from vertex 2)")
# Function call
g.DFS(2)

TRY
1. Write a program to implement breadth first search and depth first search by consider the below graph
and verify the results.
10. Minimum Spanning Tree (MST)
10.1 Kruskal’s Algorithm
In Kruskal’s algorithm, sort all edges of the given graph in increasing order. Then it keeps on adding new
edges and nodes in the MST if the newly added edge does not form a cycle. It picks the minimum
weighted edge at first and the maximum weighted edge at last.

MST using Kruskal’s algorithm:


1. Sort all the edges in non-decreasing order of their weight.
2. Pick the smallest edge. Check if it forms a cycle with the spanning tree formed so far. If the cycle is not
formed, include this edge. Else, discard it.
3. Repeat step#2 until there are (V-1) edges in the spanning tree.

Kruskal’s algorithm to find the minimum cost spanning tree uses the greedy approach. The Greedy Choice
is to pick the smallest weight edge that does not cause a cycle in the MST constructed so far.

Input: For the given graph G find the minimum cost spanning tree.

The graph contains 9 vertices and 14 edges. So, the minimum spanning tree formed will be having (9 – 1)
= 8 edges.
After sorting:

Weight Source Destination


1 7 6
2 8 2
2 6 5
4 0 1
4 2 5
6 8 6
7 2 3
7 7 8
8 0 7
8 1 2
9 3 4
10 5 4
11 1 7
14 3 5
Now pick all edges one by one from the sorted list of edges.

Output:

Hints:
# Kruskal's algorithm to find minimum Spanning Tree of a given connected,
# undirected and weighted graph

# Class to represent a graph


class Graph:
def __init__(self, vertices):
self.V = vertices
self.graph = []

# Function to add an edge to graph


def addEdge(self, u, v, w):
self.graph.append([u, v, w])

def find(self, parent, i):


def union(self, parent, rank, x, y):


def KruskalMST(self):
# write your code here

# Driver code
g = Graph(4)
g.addEdge(0, 1, 10)
g.addEdge(0, 2, 6)
g.addEdge(0, 3, 5)
g.addEdge(1, 3, 15)
g.addEdge(2, 3, 4)

# Function call
g.KruskalMST()
Output: Following are the edges in the constructed MST
2 -- 3 == 4

0 -- 3 == 5

0 -- 1 == 10

Minimum Cost Spanning Tree: 19

10.2 Prim’s Algorithm


The Prim’s algorithm starts with an empty spanning tree. The idea is to maintain two sets of vertices. The
first set contains the vertices already included in the MST, and the other set contains the vertices not yet
included. At every step, it considers all the edges that connect the two sets and picks the minimum weight
edge from these edges. After picking the edge, it moves the other endpoint of the edge to the set
containing MST.

Prim’s Algorithm:
The working of Prim’s algorithm can be described by using the following steps:
1. Determine an arbitrary vertex as the starting vertex of the MST.
2. Follow steps 3 to 5 till there are vertices that are not included in the MST (known as fringe vertex).
3. Find edges connecting any tree vertex with the fringe vertices.
4. Find the minimum among these edges.
5. Add the chosen edge to the MST if it does not form any cycle.
6. Return the MST and exit

Input: For the given graph G find the minimum cost spanning tree.

Output: The final structure of the MST is as follows and the weight of the edges of the MST is (4 + 8 + 1
+ 2 + 4 + 2 + 7 + 9) = 37.
Hints:
# Prim's Minimum Spanning Tree (MST) algorithm.
# The program is for adjacency matrix representation of the graph

# Library for INT_MAX


import sys

class Graph():
def __init__(self, vertices):
self.V = vertices
self.graph = [[0 for column in range(vertices)]
for row in range(vertices)]

# A utility function to print


# the constructed MST stored in parent[]
def printMST(self, parent):
print("Edge \tWeight")
for i in range(1, self.V):
print(parent[i], "-", i, "\t", self.graph[i][parent[i]])

# A utility function to find the vertex with


# minimum distance value, from the set of vertices
# not yet included in shortest path tree
def minKey(self, key, mstSet):


def primMST(self):

# Driver's code
g = Graph(5)
g.graph = [[0, 2, 0, 6, 0],
[2, 0, 3, 8, 5],
[0, 3, 0, 0, 7],
[6, 8, 0, 0, 9],
[0, 5, 7, 9, 0]]

g.primMST()

Output:
Edge Weight

0-1 2

1-2 3

0-3 6

1-4 5
TRY
1. Write a program to implement kruskal’s algorithm and prim’s algorithm by consider the below graph
and verify the results.

11. Roots of Equations


11.1 Bisection Method
The Bisection method is also called the interval halving method, the binary search method or the
dichotomy method. This method is used to find root of an equation in a given interval that is value of ‘x’
for which f(x) = 0. The method is based on The Intermediate Value Theorem which states that if f(x) is a
continuous function and there are two real numbers a and b such that f(a) * f(b) 0 and f(b) < 0), then it is
guaranteed that it has at least one root between them.

Assumptions:
1. f(x) is a continuous function in interval [a, b]
2. f(a) * f(b) < 0

Steps:
1. Find middle point c= (a + b)/2.
2. If f(c) == 0, then c is the root of the solution.
3. Else f(c) != 0
 If value f(a)*f(c) < 0 then root lies between a and c. So we recur for a and c
 Else If f(b)*f(c) < 0 then root lies between b and c. So we recur b and c.
 Else given function doesn’t follow one of assumptions.

Since root may be a floating point number, we repeat above steps while difference between a and b is
greater than and equal to a value? (A very small value).
Hints:
# An example function whose solution is determined using Bisection Method.
# The function is x^3 - x^2 + 2
def func(x):
return x*x*x - x*x + 2

# Prints root of func(x) with error of EPSILON


def bisection(a,b):
# Write your code here

# Driver code
# Initial values assumed
a =-200
b = 300
bisection (a, b)

Output: The value of root is : -1.0025

TRY
1. Take an input function x^2 - x^3 + 2 and verify the results.
2. Take an input function x^3 - x^3 + 4 and verify the results.

11.2 Method of False Position


Given a function f(x) on floating number x and two numbers ‘a’ and ‘b’ such that f(a)*f(b) < 0 and f(x) is
continuous in [a, b]. Here f(x) represents algebraic or transcendental equation. Find root of function in
interval [a, b] (Or find a value of x such that f(x) is 0).

Input: A function of x, for example x3 – x2 + 2.


And two values: a = -200 and b = 300 such that
f(a)*f(b) < 0, i.e., f(a) and f(b) have opposite signs.
Output: The value of root is : -1.00
OR any other value close to root.
Hints:
MAX_ITER = 1000000

# An example function whose solution is determined using Regular Falsi Method.


# The function is x^3 - x^2 + 2
def func( x ):
return (x * x * x - x * x + 2)

# Prints root of func(x) in interval [a, b]


def regulaFalsi( a , b):
# Write your code here

# Driver code to test above function


# Initial values assumed
a =-200
b = 300
regulaFalsi(a, b)

TRY
1. Take an input function x^2 - x^3 + 2 and verify the results.
2. Take an input function x^3 - x^3 + 4 and verify the results.

11.3 Newton Raphson Method


Given a function f(x) on floating number x and an initial guess for root, find root of function in interval.
Here f(x) represents algebraic or transcendental equation.
3 2 2
Input: A function of x (for example x – x + 2), derivative function of x (3x – 2x for above example) and
an initial guess x0 = -20

Output: The value of root is: -1.00 or any other value close to root.

Algorithm:
Input: initial x, func(x), derivFunc(x)
Output: Root of Func()

1. Compute values of func(x) and derivFunc(x) for given initial x


2. Compute h: h = func(x) / derivFunc(x)
3. While h is greater than allowed error ε
 h = func(x) / derivFunc(x)
 x=x–h

Hints:
# Implementation of Newton Raphson Method for solving equations
# An example function whose solution is determined using Bisection Method.
# The function is x^3 - x^2 + 2
def func( x ):
return x * x * x - x * x + 2

# Derivative of the above function which is 3*x^x - 2*x


def derivFunc( x ):
return 3 * x * x - 2 * x

# Function to find the root


def newtonRaphson( x ):
# Write your code here

# Driver program
x0 = -20
newtonRaphson(x0)

TRY
1. Take an input function x^2 - x^3 + 2 and verify the results.
2. Take an input function x^3 - x^3 + 4 and verify the results.

11.4 Secant Method


The secant method is used to find the root of an equation f(x) = 0. It is started from two distinct estimates
x1 and x2 for the root. It is an iterative procedure involving linear interpolation to a root. The iteration
stops if the difference between two intermediate values is less than the convergence factor.

Input: Equation = x3 + x – 1
x1 = 0, x2 = 1, E = 0.0001

Output: Root of the given equation = 0.682326


No. of iteration=5

Algorithm
Initialize: x1, x2, E, n // E = convergence indicator
calculate f(x1),f(x2)

if(f(x1) * f(x2) = E); //repeat the loop until the convergence


print 'x0' //value of the root
print 'n' //number of iteration
}
else
print "cannot found a root in the given interval"

Hints:
# Find root of an equations using secant method
# Function takes value of x and returns f(x)
def f(x):
# we are taking equation as x^3+x-1
f = pow(x, 3) + x - 1;
return f;
def secant(x1, x2, E):
# Write your code here

# Driver code
# initializing the values
x1 = 0;
x2 = 1;
E = 0.0001;
secant(x1, x2, E);

TRY
1. Take an input function x^2 - x + 2 and verify the results.
2. Take an input function x^3 - x^2 + 4 and verify the results.

11.5 Muller Method


Given a function f(x) on floating number x and three initial distinct guesses for root of the function, find
the root of function. Here, f(x) can be an algebraic or transcendental function.

Input: A function f(x) = x + 2x + 10x - 20 and three initial guesses - 0, 1 and 2 .

Output: The value of the root is 1.3688 or any other value within permittable deviation from the root.

Input: A function f(x) = x - 5x + 2 and three initial guesses - 0, 1 and 2.

Output: The value of the root is 0.4021 or any other value within permittable deviation from the root.

Hints:
# Find root of a function, f(x)
import math;

MAX_ITERATIONS = 10000;

# Function to calculate f(x)


def f(x):
# Taking f(x) = x ^ 3 + 2x ^ 2 + 10x - 20
return (1 * pow(x, 3) + 2 * x * x +
10 * x - 20);

def Muller(a, b, c):


# Write your code here

# Driver Code
a = 0;
b = 1;
c = 2;
Muller(a, b, c);
TRY
1. Take an input function x^2 - x^3 + 2 and verify the results.
2. Take an input function x^3 - x^3 + 4 and verify the results.

12. Numerical Integration


12.1 Trapezoidal Rule for Approximate Value of Definite Integral
Trapezoidal rule is used to find the approximation of a definite integral. The basic idea in Trapezoidal rule
is to assume the region under the graph of the given function to be a trapezoid and calculate its area.

Hints:
# Implement Trapezoidal rule

# A sample function whose definite integral's approximate value is


# computed using Trapezoidal rule
def y( x ):

# Declaring the function


# f(x) = 1/(1+x*x)
return (1 / (1 + x * x))

# Function to evaluate the value of integral


def trapezoidal (a, b, n):
# Write your code here

# Driver code
# Range of definite integral
x0 = 0
xn = 1

# Number of grids. Higher value means more accuracy


n = 6
print ("Value of integral is ",
"%.4f"%trapezoidal(x0, xn, n))

12.2 Simpson’s 1/3 Rule


Simpson’s 1/3 rule is a method for numerical approximation of definite integrals. Specifically, it is the
following approximation:
Procedure:
In order to integrate any function f(x) in the interval (a, b), follow the steps given below:

1. Select a value for n, which is the number of parts the interval is divided into.
2. Calculate the width, h = (b-a)/n
3. Calculate the values of x0 to xn as x0 = a, x1 = x0 + h, …..xn-1 = xn-2 + h, xn = b.
Consider y = f(x). Now find the values of y (y0 to yn) for the corresponding x (x0 to xn) values.
4. Substitute all the above found values in the Simpson’s Rule Formula to calculate the integral value.

Approximate value of the integral can be given by Simpson’s Rule:

Input: Evaluate logx dx within limit 4 to 5.2.

First we will divide interval into six equal parts as number of interval should be even.

x : 4 4.2 4.4 4.6 4.8 5.0 5.2

logx : 1.38 1.43 1.48 1.52 1.56 1.60 1.64

Output: Now we can calculate approximate value of integral using above formula:

= h/3[(1.38 + 1.64) + 4 * (1.43 + 1.52 + 1.60) +2 *(1.48 + 1.56)]

= 1.84

Hence the approximation of above integral is

1.827 using Simpson's 1/3 rule.

Hints:
# Simpson's 1 / 3 rule
import math

# Function to calculate f(x)


def func(x):
return math.log(x)

# Function for approximate integral


def simpsons_(ll, ul, n):
# Write your code here

# Driver code
lower_limit = 4 # Lower limit
upper_limit = 5.2 # Upper limit
n = 6 # Number of interval
print("%.6f"% simpsons_(lower_limit, upper_limit, n))
12.3 Simpson’s 3/8 Rule
The Simpson’s 3/8 rule was developed by Thomas Simpson. This method is used for performing numerical
integrations. This method is generally used for numerical approximation of definite integrals. Here,
parabolas are used to approximate each part of curve.

Input: lower_limit = 1, upper_limit = 10, interval_limit = 10

Output: integration_result = 0.687927

Input: lower_limit = 1, upper_limit = 5, interval_limit = 3

Output: integration_result = 0.605835

Hints:
# Implement Simpson's 3/8 rule

# Given function to be integrated


def func(x):
return (float(1) / ( 1 + x * x ))

# Function to perform calculations


def calculate(lower_limit, upper_limit, interval_limit ):
# Write your code here

# driver function
interval_limit = 10
lower_limit = 1
upper_limit = 10

integral_res = calculate(lower_limit, upper_limit, interval_limit)

# rounding the final answer to 6 decimal places


print (round(integral_res, 6))

13. Ordinary Differential Equations


13.1 The Euler Method
Given a differential equation dy/dx = f(x, y) with initial condition y(x0) = y0. Find its approximate solution
using Euler method.

Euler Method:
In mathematics and computational science, the Euler method (also called forward Euler method) is a first-
order numerical procedure for solving ordinary differential equations (ODEs) with a given initial value.

Consider a differential equation dy/dx = f(x, y) with initial condition y(x0) = y0


then a successive approximation of this equation can be given by:
y(n+1) = y(n) + h * f(x(n), y(n))
where h = (x(n) – x(0)) / n, h indicates step size. Choosing smaller values of h leads to more accurate
results and more computation time.

Example:
Consider below differential equation dy/dx = (x + y + xy) with initial condition y(0) = 1 and step size h =
0.025. Find y(0.1).

Solution:
f(x, y) = (x + y + xy)
x0 = 0, y0 = 1, h = 0.025
Now we can calculate y1 using Euler formula
y1 = y0 + h * f(x0, y0)
y1 = 1 + 0.025 *(0 + 1 + 0 * 1)
y1 = 1.025
y(0.025) = 1.025.
Similarly we can calculate y(0.050), y(0.075), ....y(0.1).
y(0.1) = 1.11167
Hints:
# Find approximation of an ordinary differential equation using Euler method.

# Consider a differential equation


# dy / dx =(x + y + xy)
def func( x, y ):
return (x + y + x * y)

# Function for Euler formula


def euler( x0, y, h, x ):
# write code here

# Driver Code
# Initial Values
x0 = 0
y0 = 1
h = 0.025

# Value of x at which we need approximation


x = 0.1
euler(x0, y0, h, x)

13.2 Runge-Kutta Second Order Method


Given the following inputs:

1. An ordinary differential equation that defines the value of dy/dx in the form x and y.
2. Initial value of y, i.e., y(0).

The task is to find the value of unknown function y at a given point x, i.e. y(x).
Input: x0 = 0, y0 = 1, x = 2, h = 0.2

Output: y(x) = 0.645590

Input: x0 = 2, y0 = 1, x = 4, h = 0.4;

Output: y(x) = 4.122991

Approach:
The Runge-Kutta method finds an approximate value of y for a given x. Only first-order ordinary
differential equations can be solved by using the Runge-Kutta 2nd-order method.
Below is the formula used to compute the next value yn+1 from the previous value yn. Therefore:
yn+1 = value of y at (x = n + 1)
yn = value of y at (x = n)
where 0 ? n ? (x - x0)/h, h is step height
xn+1 = x0 + h
The essential formula to compute the value of y(n+1):

K1 = h * f(x, y)

K2 = h * f(x/2, y/2) or K1/2


2 3
yn+1 = yn + K + (h )

The formula basically computes the next value yn+1 using current yn plus the weighted average of two
increments:
 K1 is the increment based on the slope at the beginning of the interval, using y.
 K2 is the increment based on the slope at the midpoint of the interval, using (y + h*K1/2).

Hints:
# Implement Runge-Kutta method

# A sample differential equation


# "dy/dx = (x - y)/2"

def dydx(x, y):


return (x + y - 2)

# Finds value of y for a given x using step size h and initial value y0 at x0.
def rungeKutta(x0, y0, x, h):
# write code here

# Driver Code
x0 = 0
y = 1
x = 2
h = 0.2
print("y(x) =", rungeKutta(x0, y, x, h))
14. Final Notes
The only way to learn programming is program, program and program on challenging problems. The
problems in this tutorial are certainly NOT challenging. There are tens of thousands of challenging
problems available – used in training for various programming contests (such as International Collegiate
Programming Contest (ICPC), International Olympiad in Informatics (IOI)). Check out these sites:
 The ACM - ICPC International collegiate programming contest (https://icpc.global/ )
 The Topcoder Open (TCO) annual programming and design contest (https://www.topcoder.com/ )
 Universidad de Valladolid’s online judge (https://uva.onlinejudge.org/ ).
 Peking University’s online judge (http://poj.org/ ).
 USA Computing Olympiad (USACO) Training Program @ http://train.usaco.org/usacogate.
 Google’s coding competitions (https://codingcompetitions.withgoogle.com/codejam,
https://codingcompetitions.withgoogle.com/hashcode )
 The ICFP programming contest (https://www.icfpconference.org/ )
 BME International 24-hours programming contest (https://www.challenge24.org/ )
 The International Obfuscated C Code Contest (https://www0.us.ioccc.org/main.html )
 Internet Problem Solving Contest (https://ipsc.ksp.sk/ )
 Microsoft Imagine Cup (https://imaginecup.microsoft.com/en-us )
 Hewlett Packard Enterprise (HPE) Codewars (https://hpecodewars.org/ )
 OpenChallenge (https://www.openchallenge.org/ )

Coding Contests Scores


Students must solve problems and attain scores in the following coding contests:
Name of the contest Minimum number of problems to solve Required score
 CodeChef 20 200
 Leetcode 20 200
 GeeksforGeeks 20 200
 SPOJ 5 50
 InterviewBit 10 1000
 Hackerrank 25 250
 Codeforces 10 100
 BuildIT 50 500
Total score need to obtain 2500
Student must have any one of the following certification:
1. HackerRank - Problem Solving Skills Certification (Basic and Intermediate)
2. GeeksforGeeks – Data Structures and Algorithms Certification
3. CodeChef - Learn Python Certification
4. Interviewbit – DSA pro / Python pro
5. NPTEL – Programming, Data Structures and Algorithms
6. NPTEL – The Joy of Computing using Python

V. TEXT BOOKS:
1. Eric Matthes, “Python Crash Course: A Hands-On, Project-based Introduction to Programming”, No Starch
Press, 3rd Edition, 2023.
2. John M Zelle, “Python Programming: An Introduction to Computer Science”, Ingram short title, 3rd Edition,
2016.
VI. REFERENCE BOOKS:
1. Yashavant Kanetkar, Aditya Kanetkar, “Let Us Python”, BPB Publications, 2nd Edition, 2019.
2. Martin C. Brown, “Python: The Complete Reference”, Mc. Graw Hill, Indian Edition, 2018.
3. Paul Barry, “Head First Python: A Brain-Friendly Guide”, O’Reilly, 2nd Edition, 2016
4. Taneja Sheetal, Kumar Naveen, “Python Programming – A Modular Approach”, Pearson, 1st Edition, 2017.
5. R Nageswar Rao, “Core Python Programming”, Dreamtech Press, 2018.
VII. ELECTRONICS RESOURCES
1. https://realPython.com/Python3-object-oriented-programming/
2. https://Python.swaroopch.com/oop.html
3. https://Python-textbok.readthedocs.io/en/1.0/Object_Oriented_Programming.html
4. https://www.programiz.com/Python-programming/
5. https://www.geeksforgeeks.org/python-programming-language/

VIII. MATERIALS ONLINE


1. Course template
2. Lab Manual

You might also like