DAA Lab Manual
DAA Lab Manual
DAA Lab Manual
1. Write a program to implement linear search algorithm. Repeat the experiment for
different values of n, the number of elements in the list to be searched and plot a
graph of time taken versus n.
import timeit
import matplotlib.pyplot as plt
# Linear Searching
def linear_search(Array, key):
for x in Array:
if x == key:
return True
return False
# Main Block()
N = []
CPU = []
trail = int(input("Enter no. of trails : "))
for t in range(0, trail):
Array = []
print("-----> TRAIL NO : ", t + 1)
n = int(input("Enter number of elements : "))
Input(Array, n)
print(Array)
key = int(input("Enter key :"))
start = timeit.default_timer()
s = linear_search(Array, key)
print("Element Found = ", s)
times = timeit.default_timer() - start
N.append(n)
CPU.append(round(float(times) * 1000000, 2))
print("N CPU")
for t in range(0, trail):
print(N[t], CPU[t])
# Plotting Graph
plt.plot(N, CPU)
plt.scatter(N, CPU, color= "red", marker= "*", s=50)
# naming the x axis
plt.xlabel('Array Size - N')
# naming the y axis
plt.ylabel('CPU Processing Time')
# giving a title to graph
plt.title('Linear Search Time efficiency')
# function to show the plot
plt.show()
Output :
Enter no. of trails : 3
-----> TRAIL NO : 1
Enter number of elements : 5
Arr : 10
Arr : 20
Arr : 30
Arr : 40
Arr : 50
[10, 20, 30, 40, 50]
Enter key :30
Element Found = True
-----> TRAIL NO : 2
Enter number of elements : 7
Arr : 1
Arr : 2
Arr : 3
Arr : 4
Arr : 5
Arr : 6
Arr : 7
[1, 2, 3, 4, 5, 6, 7]
Enter key :2
Element Found = True
-----> TRAIL NO : 3
Enter number of elements : 3
Arr : 100
Arr : 200
Arr : 300
[100, 200, 300]
Enter key :300
Element Found = True
N CPU
5 58.5
7 45.4
3 38.3
2. Write a program to implement binary search algorithm. Repeat the experiment for
different values of n, the number of elements in the list to be searched and plot a
graph of time taken versus n.
import timeit
import matplotlib.pyplot as plt
# Binary Searching
def binary_search(Array, key):
while len(Array) > 0:
mid = (len(Array))//2
if Array[mid] == key:
return True
elif Array[mid] < key:
Array = Array[:mid]
else:
Array = Array[mid + 1:]
return False
# Main Block()
N = []
CPU = []
trail = int(input("Enter no. of trails : "))
for t in range(0, trail):
Array = []
print("-----> TRAIL NO : ", t + 1)
n = int(input("Enter number of elements : "))
Input(Array, n)
print(Array)
key = int(input("Enter key :"))
start = timeit.default_timer()
s = binary_search(Array, key)
print("Element Found = ", s)
times = timeit.default_timer() - start
N.append(n)
CPU.append(round(float(times) * 1000000, 2))
print("N CPU")
for t in range(0, trail):
print(N[t], CPU[t])
# Plotting Graph
plt.plot(N, CPU)
plt.scatter(N, CPU, color= "red", marker= "*", s=50)
# naming the x axis
plt.xlabel('Array Size - N')
# naming the y axis
plt.ylabel('CPU Processing Time')
# giving a title to graph
plt.title('Binary Search Time efficiency')
# function to show the plot
plt.show()
Output :
3. Write a program to solve towers of Hanoi problem and execute it for different
number of disks.
# Recursive Python function to solve the tower of hanoi
# Main Block
n=int(input("Enter number of disk : "))
TowerOfHanoi(n, 'A', 'B', 'C')
# A, C, B are the name of rods
Output :
Enter number of disk : 4
Move disk 1 from source A to destination C
Move disk 2 from source A to destination B
Move disk 1 from source C to destination B
Move disk 3 from source A to destination C
Move disk 1 from source B to destination A
Move disk 2 from source B to destination C
Move disk 1 from source A to destination C
Move disk 4 from source A to destination B
Move disk 1 from source C to destination B
Move disk 2 from source C to destination A
Move disk 1 from source B to destination A
Move disk 3 from source C to destination B
Move disk 1 from source A to destination C
Move disk 2 from source A to destination B
Move disk 1 from source C to destination B
4. Write a program to sort a given set of numbers using selection sort algorithm.
Repeat the experiment for different values of n, the number of elements in the list
to be sorted and plot a graph of the time taken versus n. The elements can be read
from a file or can be generated using random number generator.
import timeit
import random
import matplotlib.pyplot as plt
# Selection Sort
def selectionSort(Array, size):
for ind in range(size):
min_index = ind
# Main Block()
N = []
CPU = []
trail = int(input("Enter no. of trails : "))
for t in range(0, trail):
Array = []
print("-----> TRAIL NO : ", t + 1)
n = int(input("Enter number of elements : "))
Input(Array, n)
start = timeit.default_timer()
selectionSort(Array,n)
times = timeit.default_timer() - start
print("Sorted Array :")
print(Array)
N.append(n)
CPU.append(round(float(times) * 1000000, 2))
print("N CPU")
for t in range(0, trail):
print(N[t], CPU[t])
# Plotting Graph
plt.plot(N, CPU)
plt.scatter(N, CPU, color= "red", marker= "*", s=50)
# naming the x axis
plt.xlabel('Array Size - N')
# naming the y axis
plt.ylabel('CPU Processing Time')
# giving a title to graph
plt.title('Selection Sort Time efficiency')
# function to show the plot
plt.show()
Output :
Enter no. of trails : 4
-----> TRAIL NO : 1
Enter number of elements : 5
Sorted Array :
[14, 17, 23, 26, 37]
-----> TRAIL NO : 2
Enter number of elements : 6
Sorted Array :
[18, 19, 20, 28, 38, 48]
-----> TRAIL NO : 3
Enter number of elements : 7
Sorted Array :
[13, 24, 29, 35, 35, 47, 49]
-----> TRAIL NO : 4
Enter number of elements : 8
Sorted Array :
[5, 6, 7, 9, 10, 21, 25, 33]
N CPU
5 6.1
6 8.3
7 8.7
8 9.4
5. Write a program to find an using (a) Brute-force based algorithm
(b) Divide and conquer based algorithm
# Main block
a=int(input("Enter a :"))
n=int(input("Enter n :"))
print("Brute Force method a^n : ",bpower(a,n))
print("Divide and Conquer a^n : ",dpower(a,n))
Output
Enter a :2
Enter n :3
Brute Force method a^n : 8
Divide and Conquer a^n : 8
6. Write a program to sort a given set of numbers using quick sort algorithm. Repeat
the experiment for different values of n, the number of elements in the list to be
sorted and plot a graph of the time taken versus n.
import timeit
import random
import matplotlib.pyplot as plt
# divide function
def partition(Array,low,high):
i = ( low-1 )
pivot = Array[high] # pivot element
for j in range(low , high):
# If current element is smaller
if Array[j] <= pivot:
# increment
i = i+1
Array[i],Array[j] = Array[j],Array[i]
Array[i+1],Array[high] = Array[high],Array[i+1]
return ( i+1 )
# Quick sort
def quickSort(Array,low,high):
if low < high:
# index
pi = partition(Array,low,high)
# sort the partitions
quickSort(Array, low, pi-1)
quickSort(Array, pi+1, high)
# Main Block()
N = []
CPU = []
trail = int(input("Enter no. of trails : "))
for t in range(0, trail):
Array = []
print("-----> TRAIL NO : ", t + 1)
n = int(input("Enter number of elements : "))
Input(Array, n)
start = timeit.default_timer()
quickSort(Array,0,n-1)
times = timeit.default_timer() - start
print("Sorted Array :")
print(Array)
N.append(n)
CPU.append(round(float(times) * 1000000, 2))
print("N CPU")
for t in range(0, trail):
print(N[t], CPU[t])
# Plotting Graph
plt.plot(N, CPU)
plt.scatter(N, CPU, color= "red", marker= "*", s=50)
# naming the x axis
plt.xlabel('Array Size - N')
# naming the y axis
plt.ylabel('CPU Processing Time')
# giving a title to graph
plt.title('Quick Sort Time efficiency')
# function to show the plot
plt.show()
7. Write a program to find binomial co-efficient C(n,k) [ where n and k are integers and
n > k ] using brute force algorithm and also dynamic programming based algorithm.
# Recursive Call
return binomialCoeff_BF(n - 1, k - 1) + binomialCoeff_BF(n - 1, k)
return C[n][k]
# Main block
n=int(input("Enter n :"))
k=int(input("Enter k :"))
print("Brute Force method n^k : ",binomialCoeff_BF(n, k))
print("Divide and Conquer n^k : ",binomialCoef_DC(n, k))
Output
Enter n :5
Enter k :2
Brute Force method n^k : 10
Divide and Conquer n^k : 10
Overlapping Subproblems
It should be noted that the above function computes the same subproblems again
and again. See the following recursion tree for n = 5 and k = 2. The function C(3, 1) is
called two times. For large values of n, there will be many common subproblems.
Since the same subproblems are called again, this problem has the Overlapping
Subproblems property. So the re-computations of the same subproblems can be
avoided by constructing a temporary 2D-array C[][] in a bottom-up manner. Above is
Dynamic Programming-based implementation.
8. Write a program to implement Flyod’s algorithm and find the lengths of the shortest
paths from every pairs of vertices in a weighted graph.
# Number of vertices
nV = 4
INF = 999
# Algorithm
def floyd(G):
dist = list(map(lambda p: list(map(lambda q: q, p)), G))
Output :
0 5 15 10
20 0 10 5
30 35 0 15
15 20 5 0
Creating matrix D0 contains the distance between each node with ‘0’ as an intermediate node.
Updating matrix D1 which contains the distance between each node with ‘1’ as an intermediate node. Update
distance if minimum distance value smaller than existing distance value found.
Updating matrix D2 contains the distance between two nodes with ‘2’ as an intermediate node.
Updating matrix D4 contains the distance between two nodes with ‘4’ as an intermediate node. Update
distance if minimum distance value smaller than existing distance value found.
def polynomial_BF(poly,x,n):
# Declaring the result
result = 0
# Running a for loop to traverse through the list
for i in range(n):
start2 = timeit.default_timer()
horner(poly,x,n)
t2 = timeit.default_timer() - start2
Output :
Brute Force method : In this approach, the following methodology will be followed. This
is the most naive approach to do such questions.
• First coefficient cn will be multiplied with xn
• Then coefficient cn-1 will be multiplied with xn-1
• The results produced in the above two steps will be added
• This will go on till all the coefficient are covered.
Horner’s method can be used to evaluate polynomial in O(n) time. To understand the
method, let us consider the example of 2x3 – 6x2 + 2x – 1. The polynomial can be
evaluated as ((2x – 6)x + 2)x – 1. The idea is to initialize result as the coefficient of
xn which is 2 in this case, repeatedly multiply the result with x and add the next
coefficient to result. Finally, return the result.
10.Write a program to solve the string matching problem using Boyer-Moore approach.
Note :
A string searching algorithm based upon Boyer-Moore string searching, which is considered one of the
most efficient string searching algorithms. Boyer-Moore-Horspool only uses the bad-suffix window for
matching and is therefore simpler to implement and faster than normal BM. This algorithm is more
efficient than KMP and has low overhead to implement. It is one of the few string searching algorithms
that balances memory consumption and speed very well. There have been many comparisons and studies
on this and other string searching algorithms in the field and charts can be found which prove the usefulness
of this algorithm. According to Moore himself, this algorithm gets faster the larger the pattern.
#Main block
if __name__ == '__main__':
text = "this is the string to search in"
pattern = "the"
s = BoyerMooreHorspool(pattern, text)
print ('Text:',text)
print ('Pattern:',pattern)
if s > -1:
print ('Pattern \"' + pattern + '\" found at position',s)
Output :
Text: this is the string to search in
Pattern: the
Pattern "the" found at position 8
11.Write a program to solve the string matching problem using KMP algorithm.
def KMP_String(pattern, text):
a = len(text)
b = len(pattern)
prefix_arr = get_prefix_arr(pattern, b)
initial_point = []
m=0
n=0
while m != a:
if text[m] == pattern[n]:
m += 1
n += 1
else:
n = prefix_arr[n - 1]
if n == b:
initial_point.append(m - n)
n = prefix_arr[n - 1]
elif n == 0:
m += 1
return initial_point
while m != b:
if pattern[m] == pattern[n]:
n += 1
prefix_arr[m] = n
m += 1
elif n != 0:
n = prefix_arr[n - 1]
else:
prefix_arr[m] = 0
m += 1
return prefix_arr
# Main module
string = "ABABDABACDABABCABABCABAB"
pat = "ABABCABAB"
Output :
String : ABABDABACDABABCABABCABAB
Pattern : ABABCABAB
pattern is found in the string at index number 10
pattern is found in the string at index number 15
String = “ABABDABACDABABCABABCABAB”
Pattern = “ABABCABAB”
Here the pattern first checks with the string. At index 5 there will be a mismatch. Now
the pattern shifts one position. That means, now the pattern starts checking from index
1. Here KMP String Matching algorithms optimizes over Normal String Matching.
According to Normal String Matching algorithm, the pattern starts checking from string
‘A’, that means index 0 in pattern to the end of the pattern. Even though similar strings
are present in both the pattern and in the given string from index 0 to index 4, Normal
String Matching algorithm checks from the starting of the pattern.
But, KMP String Matching algorithm starts checking from index 5 of letter ‘C’ because
we know first four characters will anyway match, we skipped matching first four
characters. This is how optimization is done in this algorithm.
12.Write a program to implement BFS traversal algorithm.
graph = {
'5' : ['3','7'],
'3' : ['2', '4'],
'7' : ['8'],
'2' : [],
'4' : ['8'],
'8' : []
}
# Main module
print("Following is the Breadth-First Search")
bfs(visited, graph, '5') # function calling
Output :
Following is the Breadth-First Search
5 37248
13. Write a program to find minimum spanning tree of a given graph using Prim’s
Algorithm.
# Prim's Algorithm in Python
INF = 9999999
V=5
G =[[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]]
selected = [0, 0, 0, 0, 0]
no_edge = 0
selected[0] = True
print("Edge : Weight\n")
while (no_edge < V - 1):
minimum = INF
x=0
y=0
for i in range(V):
if selected[i]:
for j in range(V):
if ((not selected[j]) and G[i][j]):
# not in selected and there is an edge
if minimum > G[i][j]:
minimum = G[i][j]
x=i
y=j
print(str(x) + "-" + str(y) + ":" + str(G[x][y]))
selected[y] = True
no_edge += 1
Output :
Edge : Weight
0-1 : 2
1-2 : 3
1-4 : 5
0-3 : 6
14(a). Write a program to obtain the topological ordering of vertices in a given
digraph.
from collections import defaultdict
class Graph:
def __init__(self, directed=False):
self.graph = defaultdict(list)
self.directed = directed
def topoSort(self):
visited = {i: False for i in self.graph}
sortlist = []
for v in self.graph:
if not visited[v]:
self.topoSortvisit(v, visited, sortlist)
print(sortlist)
# Main block
if __name__ == '__main__':
g = Graph(directed=True)
g.addEdge(1, 2)
g.addEdge(1, 3)
g.addEdge(2, 4)
g.addEdge(2, 5)
g.addEdge(3, 4)
g.addEdge(3, 6)
g.addEdge(4, 6)
print("Topological Sort:")
g.topoSort()
Output
Topological Sort:
[1, 3, 2, 5, 4, 6]
14(b). Write a program to compute transitive closure of a given directed graph
using Warshall’s algorithm.
# Python program for transitive closure using Floyd Warshall Algorithm
# Complexity : O(V^3)
#Main module
g = Graph(4)
graph = [[1, 1, 0, 1],
[0, 1, 1, 0],
[0, 0, 1, 1],
[0, 0, 0, 1]]
Output :
Following matrix transitive closure of the given graph
1 1 1 1
0 1 1 1
0 0 1 1
0 0 0 1
15.Write a program to find subset of a given set S={s1,s2,….sn} of n positive
integers whose sum is equal to given positive integer d. For example if
S={1,2,5,6,8} and d=9 then two solutions {1,2,6} and {1,8}. A suitable message is to
be displayed if given problem doesn’t have solution.
if sum(my_sub_set) == d:
print(list(my_sub_set))
count=count+1
if(count==0) :
print("Subset Not found for the given d=",d)
#Main module
S = []
n = int(input("Enter size :"))
Input(S, n)
print(S)
d = int(input("Enter sum d :"))
print("The result is :")
sub_set_sum(n, S, d)
Output:
Enter size :5
Arr : 1
Arr : 2
Arr : 5
Arr : 6
Arr : 8
[1, 2, 5, 6, 8]
Enter sum d :9
The result is :
[1, 8]
[1, 2, 6]
Enter size :3
Arr : 1
Arr : 2
Arr : 3
[1, 2, 3]
Enter sum d :10
The result is :
Subset Not found for the given d= 10