DAA RECORD
DAA RECORD
DAA RECORD
Submitted by
Name :
Register No :
Semester/year :
Department :
EX: 1 A Implement recursive and non-recursive algorithm and
DATE: study the order of growth from logn to n!
AIM:
ALGORITHM:
PROGRAM:
Recursive algorithm:
def factorial(n):
if (n == 1 or n == 0):
return 1
else:
return (n * factorial(n - 1))
num = 5
print("number: ", num)
print("Factorial: ", factorial(num))
Output:
number: 5
Factorial: 120
Output:
Enter the number:5
Factorial of the number:120
AIM:
ALGORITHM:
EX: 1B
Program (Linear Search):
import time
import matplotlib.pyplot as plt # Plotting the graph
def linear_search(arr, x):
for i in range(len(arr)):
if arr[i] == x:
return i
return -1
def measure_time(n):
arr = [i for i in range(n)]
start_time = time.time()
linear_search(arr, n + 1)
return time.time() - start_time
def time_taken(arr, x):
start_time = time.time()
linear_search(arr, x)
return time.time() - start_time
if __name__ == '__main__':
n_values = [10, 100, 1000, 10000, 100000, 1000000]
times = [measure_time(n) for n in n_values]
print(n_values)
print(times)
# Example usage of time_taken function
arr = [i for i in range(1000000)]
x = 999999
print(f"Time taken to find {x} in arr using linear search: {time_taken(arr, x)} seconds")
plt.plot(n_values, times)
plt.xlabel('n - number of elements in list')
plt.ylabel('Time taken (in seconds)')
plt.title('Linear search performance')
plt.show()
OUTPUT:
[10, 100, 1000, 10000, 100000, 1000000]
[2.6226043701171875e-06, 7.867813110351562e-06, 0.0027456283569335938,
0.000804901123046875, 0.028525352478027344, 0.10596990585327148]
Time taken to find 999999 in arr using linear search: 0.07597494125366211 seconds
RESULT:
EX: 1C
AIM:
ALGORITHM:
EX: 1C
Program (Binary Search):
import time
import matplotlib.pyplot as plt
def binary_search_recursive(arr, x, left, right):
if right >= left:
mid = (left + right) // 2
if arr[mid] == x:
return mid
elif arr[mid] > x:
return binary_search_recursive(arr, x, left, mid-1)
else:
return binary_search_recursive(arr, x, mid+1, right)
else:
return -1
def measure_time(n):
arr = [i for i in range(1, n + 1)]
x = arr[-1] # searching for the last element
start = time.time()
binary_search_recursive(arr, x, 0, len(arr) - 1)
end = time.time()
return end - start
n_values = [10, 100, 1000, 10000, 100000, 1000000]
time_values = [measure_time(n) for n in n_values]
print(n_values)
print(time_values)
plt.plot(n_values, time_values)
plt.xscale('log')
plt.xlabel('Number of elements (log scale)'
plt.ylabel('Time taken (seconds)')
plt.title('Recursive Binary Search Performance')
plt.show()
Output:
[10, 100, 1000, 10000, 100000, 1000000]
[3.5762786865234375e-06, 3.337860107421875e-06, 6.9141387939453125e-06,
1.049041748046875e-05, 1.4543533325195312e-05, 2.1457672119140625e-05]
RESULT:
EX:2
AIM:
ALGORITHM:
Program:
x = [[0, 2], [0, 1]]
print("Matrix x is:")
for i in range(len(x)):
print("\t", x[i])
y = [[0, 0], [3, 4]]
print("Matrix y is:")
for i in range(len(y)):
print("\t", y[i])
def strassen(a, b):
S = [b[0][1] - b[1][1],
EX: 2
a[0][0] + a[0][1],
a[1][0] + a[1][1],
b[1][0] - b[0][0],
a[0][0] + a[1][1],
b[0][0] + b[1][1],
a[0][1] - a[1][1],
b[1][0] + b[1][1],
a[0][0] - a[1][0],
b[0][0] + b[0][1]]
P = [a[0][0] * S[0],
S[1] * b[1][1],
S[2] * b[0][0],
a[1][1] * S[3],
S[4] * S[5],
S[6] * S[7],
S[8] * S[9]]
C = [[P[4] + P[3] - P[1] + P[5], P[0] + P[1]],
[P[2] + P[3], P[4] + P[0] - P[2] - P[6]]]
print("Strassen's Matrix multiplication of x and y is.")
print(S)
print(P)
print(C)
strassen(x, y)
Output:
matrix x is:
[0, 2]
[0, 1]
matrix y is:
[0, 0]
[3, 4]
Strassen's Matrix multiplication of x and y is.
[-4, 2, 1, 3, 1, 4, 1, 7, 0, 0]
[0, 8, 0, 3, 4, 7, 0]
[[6, 8], [3, 4]]
EX: 3
AIM:
ALGORITHM:
EX: 3
Program:
from collections import defaultdict
def topological_sort(vertices, edges):
sorted_order = []
in_degree = {vertex: 0 for vertex in vertices}
graph = defaultdict(list)
# Create the graph
for edge in edges:
src, dest = edge
graph[src].append(dest)
in_degree[dest] += 1
# Create a queue and add all vertices with 0 in-degree
queue = []
for vertex in in_degree:
if in_degree[vertex] == 0:
queue.append(vertex)
# Start the topological sort
while queue:
vertex = queue.pop(0)
sorted_order.append(vertex)
# Decrease in-degree for all neighbors
for neighbor in graph[vertex]:
in_degree[neighbor] -= 1
# Add to queue if in-degree becomes 0
if in_degree[neighbor] == 0:
queue.append(neighbor)
# Check for a cycle
if len(sorted_order) != len(vertices):
return [] # Cycle detected, no topological order possible
else:
return sorted_order
vertices = [1, 2, 3, 4, 5, 6]
edges = [(1, 2), (1, 5), (2, 3), (2, 5), (3, 4), (4, 6), (5, 6)]
print(topological_sort(vertices, edges))
Output:
[1, 2, 5, 3, 4, 6]
RESULT:
EX: 4
AIM:
ALGORITHM:
heapify(arr, n, largest)
def heap_sort(arr):
n = len(arr)
heapify(arr, n, i)
heapify(arr, i, 0)
times = []
for n in n_values:
start_time = time.time()
heap_sort(arr)
end_time = time.time()
times.append(end_time - start_time)
plt.plot(n_values, times)
plt.xlabel('n')
plt.ylabel('Time (s)')
plt.show()
Output:
AIM:
ALGORITHM:
EX: 5A
Program:
class Solution(object):
def coinChange(self, coins, amount):
if amount == 0:
return 0
return -1
dp = [-1] + [float('inf')] * amount
for i in coins:
if i <= amount:
dp[i] = 1
for j in range(1, amount + 1):
for coin in coins:
if j - coin >= 0 and dp[j - coin] != float('inf'):
if dp[j] == -1:
dp[j] = dp[j - coin] + 1
else:
dp[j] = min(dp[j], dp[j - coin] + 1)
return dp[amount]
ob1 = Solution()
print(ob1.coinChange([1, 2, 5], 11))
Output:
3
RESULT:
EX: 5B Compute the transitive closure of a given directed graph
DATE: using Warshall's algorithm
AIM:
ALGORITHM:
EX: 5B
Program (Warshall's algorithm):
import time
import matplotlib.pyplot as plt
def transitiveClosure(graph):
V = len(graph)
reach = list(map(lambda i: list(map(lambda j: j, i)), graph))
for k in range(V):
for i in range(V):
for j in range(V):
reach[i][j] = reach[i][j] or (reach[i][k] and reach[k][j])
return reach
def time_taken(graph):
print("Computing transitive closure...")
start = time.time()
result = transitiveClosure(graph)
end = time.time()
print("Time taken:", end - start)
return result
# Example usage
graph = [[1, 1, 0, 1],
[0, 1, 1, 0],
[0, 0, 1, 1],
[0, 0, 0, 1]]
transitive_closure_result = time_taken(graph)
print("Transitive Closure Matrix:")
for row in transitive_closure_result:
print(row)
Output:
[[1, 1, 1, 1], [0, 1, 1, 1], [0, 0, 1, 1], [0, 0, 0, 1]]
Time taken to compute transitive closure: 2.4557113647460938e-05
RESULT:
EX: 5C Implement Floyd’s algorithm for the All-Pairs- Shortest-
DATE: problem
AIM:
ALGORITHM:
EX: 5C
Program (Floyd’s algorithm):
import time
import matplotlib.pyplot as plt
def floydWarshall(graph):
V = len(graph)
dist = list(map(lambda i: list(map(lambda j: j, i)), graph))
for k in range(V):
for i in range(V):
for j in range(V):
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
return dist
def time_taken(graph):
print("Computing Floyd-Warshall...")
start_time = time.time()
result = floydWarshall(graph)
end_time = time.time()
print("Time taken:", end_time - start_time)
return result
graph = [[0, 5, 99999, 99999],
[50, 0, 15, 5],
[30, 99999, 0, 99999],
[15, 99999, 5, 0]]
floyd_warshall_result = time_taken(graph)
print("Shortest Distance Matrix:")
for row in floyd_warshall_result:
print(row)
Output:
[[0, 5, 15, 10], [20, 0, 10, 5], [30, 35, 0, 40], [15, 20, 5, 0]]
time of my program is 4.506111145019531e-05 sec
RESULT:
EX:5D
DATE: Dynamic Programming-Knapsack problem
AIM:
ALGORITHM:
EX: 5D
Program:
def knapSack(W, wt, val, n):
K = [[0 for x in range(W + 1)] for x in range(n + 1)]
for i in range(n + 1):
for w in range(W + 1):
if i == 0 or w == 0:
K[i][w] = 0
elif wt[i - 1] <= w:
K[i][w] = max(val[i - 1] + K[i - 1][w - wt[i - 1]], K[i - 1][w])
else:
K[i][w] = K[i - 1][w]
return K[n][W]
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
print(knapSack(W, wt, val, n))
Output:
220
RESULT:
EX:6 A
DATE: Greedy Technique-Dijkstra’s algorithm
AIM:
ALGORITHM:
PROGRAM: EX: 6A
import heapq
import time
def dijkstra(graph, start):
distances = {vertex: float('infinity') for vertex in graph}
distances[start] = 0
priority_queue = [(0, start)]
while priority_queue:
current_distance, current_vertex = heapq.heappop(priority_queue)
if current_distance > distances[current_vertex]:
continue
for neighbor, weight in graph[current_vertex].items():
distance = current_distance + weight
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(priority_queue, (distance, neighbor))
return distances
def time_taken(graph, start):
print("Time taken by dijkstra function:")
start_time = time.time()
dijkstra(graph, start)
end_time = time.time()
return end_time - start_time
graph = {
'A': {'B': 1, 'C': 4}
'B': {'A': 1, 'C': 2, 'D': 5},
'C': {'A': 4, 'B': 2, 'D': 1},
'D': {'B': 5, 'C': 1}
}
start_node = 'A'
print(dijkstra(graph, start_node))
print("Time taken by dijkstra function: {} seconds".format(time_taken(graph, start_node)))
Output:
{'A': 0, 'B': 1, 'C': 3, 'D': 4}
Time taken by dijkstra function: 1.8596649169921875e-05 seconds
RESULT:
EX:6 B
DATE: Greedy Technique-Huffman Trees and codes
AIM:
ALGORITHM:
PROGRAM: EX: 6B
import heapq
import itertools
pq = []
entry_finder = {}
REMOVED = '<removed-task>'
counter = itertools.count()
def add_task(task, priority=0):
if task in entry_finder:
remove_task(task)
count = next(counter)
entry = [priority, count, task]
entry_finder[task] = entry
heapq.heappush(pq, entry)
def remove_task(task):
entry = entry_finder.pop(task)
entry[-1] = REMOVED
def pop_task():
while pq:
priority, count, task = heapq.heappop(pq)
if task is not REMOVED:
del entry_finder[task]
return task
raise KeyError('pop from an empty priority queue')
def inorder(root):
if root is not None:
inorder(root.left)
print(root.frequency)
inorder(root.right)
class Node():
def __init__(self, d, f):
self.data = d
self.frequency = f
self.left = None
self.right = None
def greedy_huffman():
while len(pq) > 1:
left = pop_task()
right = pop_task()
freq = left.frequency + right.frequency
z = Node(None, freq)
z.left = left
z.right = right
add_task(z, z.frequency)
return pop_task()
if __name__ == '__main__':
a = Node('a', 42)
b = Node('b', 20)
c = Node('c', 5)
d = Node('d', 10)
e = Node('e', 11)
f = Node('f', 12)
add_task(a, a.frequency)
add_task(b, b.frequency)
add_task(c, c.frequency)
add_task(d, d.frequency)
add_task(e, e.frequency)
add_task(f, f.frequency)
tree = greedy_huffman()
inorder(tree)
Output:
42
100
11
23
12
58
5
15
10
35
20
RESULT:
EX: 07
DATE: Iterative improvement-simplex method
AIM:
ALGORITHM:
PROGRAM:
from numpy import *
Output:
None
RESULT:
EX: 8 A
DATE: Backtracking-N-Queen problem
AIM:
ALGORITHM:
EX: 8A
PROGRAM:
import time
Output:
[1, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 1, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1]
[0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 1, 0, 0]
[0, 0, 1, 0, 0, 0, 0, 0]
RESULT:
EX: 8 B
DATE: Backtracking-Subset sum problem
AIM:
ALGORITHM:
PROGRAM:
Output:
Found a subset with given sum
RESULT:
EX: 9 A
DATE: Branch and bound-Assignment problem
AIM:
ALGORITHM:
PROGRAM:
from queue import PriorityQueue
if i == N - 1:
return new_cost
q.put((new_cost, new_state, new_cost))
return None
# Example usage
cost = [[9, 2, 7, 8], [6, 4, 3, 7], [5, 8, 1, 8], [7, 6, 9, 4]]
N=4
print(find_min_cost(cost, N))
Output:
16
RESULT:
EX: 9 B
DATE: Branch and bound-Travelling salesman problem
AIM:
ALGORITHM:
PROGRAM: EX: 9B
if len(state) == n:
return min_cost + graph[last][start]
for i in range(n):
if not visited[i]:
new_visited = visited.copy()
new_visited[i] = True
new_state = state + [i]
new_cost = min_cost + graph[last][i]
q.put((new_cost, new_state, new_visited))
return None
# Example usage
graph = [[0, 10, 15, 20],
[10, 0, 35, 25],
[15, 35, 0, 30],
[20, 25, 30, 0]]
start = 0
print(tsp(graph, start))
Output:
80
RESULT: