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

Daa Record 1 To 5

Uploaded by

gmreddyqowi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views

Daa Record 1 To 5

Uploaded by

gmreddyqowi
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 29

1(A)-IMPLEMENT RECURSIVE ALGORITHM

(LINEAR SEARCH)

PROGRAM:

import time
import matplotlib.pyplot as plt

# Linear Search function


def linear_search(arr, target):
for i in range(len(arr)):
if arr[i] == target:
return i
return -1

# Measure the time taken for linear search


def measure_time(arr, target):
start_time = time.time()
linear_search(arr, target)
end_time = time.time()
return end_time - start_time

# Plotting the graph


list_sizes = []
times_taken = []

# Testing the linear search for different list sizes


for size in range(1000, 10001, 1000): # Increase the size of the list
arr = list(range(size))
target = size - 1 # Target is the last element for worst-case scenario
time_taken = measure_time(arr, target)

list_sizes.append(size)
times_taken.append(time_taken)

# Plot the graph


plt.plot(list_sizes, times_taken, marker='o')
plt.title('Linear Search Performance')
plt.xlabel('List Size')
plt.ylabel('Time Taken (seconds)')
plt.grid(True)
plt.show()
OUTPUT:
1(C)-IMPLEMENT OF NON-RECURSIVE ALGORITHM
(BINARY SEARCH)

PROGRAM:

import time
import matplotlib.pyplot as plt

# Binary Search function


def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1

# Measure the time taken for binary search


def measure_time(arr, target):
start_time = time.time()
binary_search(arr, target)
end_time = time.time()
return end_time - start_time

# Plotting the graph


list_sizes = []
times_taken = []

# Testing the binary search for different list sizes


for size in range(1000, 100001, 5000): # Increase the size of the list
arr = list(range(size))
target = size - 1 # Target is the last element for worst-case scenario
time_taken = measure_time(arr, target)

list_sizes.append(size)
times_taken.append(time_taken)

# Plot the graph


plt.plot(list_sizes, times_taken, marker='o')
plt.title('Binary Search Performance')
plt.xlabel('List Size')
plt.ylabel('Time Taken (seconds)')
plt.grid(True)
plt.show()
OUTPUT:
1(B)-IMPLEMENT OF RECURSIVE ALGORITHM
(FACTORIAL)

PROGRAM:

import time
import math
import matplotlib.pyplot as plt

# Generate a list of factorial numbers up to a certain size


def generate_factorial_list(size):
return [math.factorial(i) for i in range(1, size + 1)]

# Search for a factorial number


def search_factorial(arr, target):
try:
return arr.index(target)
except ValueError:
return -1

# Measure the time taken for the factorial number search


def measure_time(arr, target):
start_time = time.time()
search_factorial(arr, target)
end_time = time.time()
return end_time - start_time

# Plotting the graph


list_sizes = []
times_taken = []

# Testing the search for different list sizes


for size in range(1, 101): # Generate factorials up to 100!
arr = generate_factorial_list(size)
target = math.factorial(size) # Search for the largest factorial in the list
time_taken = measure_time(arr, target)

list_sizes.append(size)
times_taken.append(time_taken)

# Plot the graph


plt.plot(list_sizes, times_taken, marker='o')
plt.title('Factorial Number Search Performance')
plt.xlabel('Factorial N (Factorial of N!)')
plt.ylabel('Time Taken (seconds)')
plt.grid(True)
plt.show()
OUTPUT:
2-DIVIDE AND CONQUER
STRASSEN’S MATRIX MULTIPLICATION

PROGRAM:

# Function to perform Strassen's Matrix Multiplication for 2x2 matrices


def strassen_2x2(A, B):
# Extract elements from matrix A
a, b = A[0][0], A[0][1]
c, d = A[1][0], A[1][1]

# Extract elements from matrix B


e, f = B[0][0], B[0][1]
g, h = B[1][0], B[1][1]

# Compute the 7 intermediate products


P1 = a * (f - h)
P2 = (a + b) * h
P3 = (c + d) * e
P4 = d * (g - e)
P5 = (a + d) * (e + h)
P6 = (b - d) * (g + h)
P7 = (a - c) * (e + f)

# Compute the resulting matrix C


C11 = P5 + P4 - P2 + P6
C12 = P1 + P2
C21 = P3 + P4
C22 = P1 + P5 - P3 - P7
# Return the resulting matrix as a 2x2 list
return [[C11, C12], [C21, C22]]

# Function to take runtime input for the 2x2 matrices


def get_input():
print("Enter the elements of matrix A (2x2):")
A = [[int(input(f"Enter A[{i+1}][{j+1}]: ")) for j in range(2)] for i in range(2)]

print("Enter the elements of matrix B (2x2):")


B = [[int(input(f"Enter B[{i+1}][{j+1}]: ")) for j in range(2)] for i in range(2)]

return A, B

# Main function
if __name__ == "__main__":
A, B = get_input()

# Perform Strassen's Matrix Multiplication for 2x2 matrices


C = strassen_2x2(A, B)

# Output the result


print("Resulting Matrix C (A x B):")
for row in C:
print(row)
OUTPUT:

Enter the elements of matrix A (2x2):


Enter A[1][1]: 1
Enter A[1][2]: 2
Enter A[2][1]: 3
Enter A[2][2]: 4

Enter the elements of matrix B (2x2):


Enter B[1][1]: 5
Enter B[1][2]: 6
Enter B[2][1]: 7
Enter B[2][2]: 8

Resulting Matrix C (A x B):


[19, 22]
[43, 50]
3-DECREASE AND CONQUER
TOPOLOGICAL SORTING

PROGRAM:

from collections import deque

# Function to perform Topological Sort using Decrease-and-Conquer approach


def topological_sort(vertices, graph):
# Initialize in-degree (number of incoming edges) for each vertex
in_degree = {v: 0 for v in vertices}
for v in vertices:
for neighbor in graph[v]:
in_degree[neighbor] += 1

# Use a deque to process vertices with in-degree 0


zero_in_degree_queue = deque([v for v in vertices if in_degree[v] == 0])

top_order = []

while zero_in_degree_queue:
# Remove a vertex from the queue
vertex = zero_in_degree_queue.popleft()
top_order.append(vertex)

# Decrease the in-degree of neighbors


for neighbor in graph[vertex]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
zero_in_degree_queue.append(neighbor)

# If the topological order contains all vertices, it's valid


if len(top_order) == len(vertices):
return top_order
else:
raise ValueError("The graph contains a cycle, so topological sort is not possible.")

# Input function to get graph details


def get_input():
n = int(input("Enter the number of vertices: "))

# Initialize graph (empty adjacency list for each vertex)


graph = {i: [] for i in range(n)}

m = int(input(f"Enter the number of directed edges: "))

print("Enter the edges (u v) representing u -> v:")


for _ in range(m):
u, v = map(int, input().split())
graph[u].append(v)

vertices = list(graph.keys()) # List of all vertices


return vertices, graph

# Main function
if __name__ == "__main__":
vertices, graph = get_input()
try:
# Perform Topological Sort
top_order = topological_sort(vertices, graph)

# Output the topological order


print("Topological Order:", top_order)

except ValueError as e:
print(e)
OUTPUT:

Enter the number of vertices: 6


Enter the number of directed edges: 6
Enter the edges (u v) representing u -> v:
52
50
40
41
23
31
Topological Order: [5, 4, 2, 3, 1, 0]
4-TRANSFORM AND CONQUER
HEAP SORT

PROGRAM:

import time
import matplotlib.pyplot as plt

# Function to heapify a subtree rooted at index i (build max heap)


def heapify(arr, n, i):
largest = i # Initialize largest as root
left = 2 * i + 1 # Left child
right = 2 * i + 2 # Right child

# If left child is larger than root


if left < n and arr[left] > arr[largest]:
largest = left

# If right child is larger than largest so far


if right < n and arr[right] > arr[largest]:
largest = right

# If largest is not root, swap and heapify the affected subtree


if largest != i:
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr, n, largest)

# Function to perform heap sort


def heap_sort(arr):
n = len(arr)

# Build a max heap (rearrange the array)


for i in range(n // 2 - 1, -1, -1):
heapify(arr, n, i)

# One by one extract elements from the heap


for i in range(n-1, 0, -1):
# Swap the root (maximum element) with the last element
arr[i], arr[0] = arr[0], arr[i]

# Heapify the root of the tree


heapify(arr, i, 0)

# Function to take runtime input and sort the list


def get_input():
n = int(input("Enter the number of elements in the array: "))
arr = [int(input(f"Enter element {i+1}: ")) for i in range(n)]
return arr

# Function to plot the time complexity graph


def plot_time_complexity():
sizes = [10, 100, 1000, 5000, 10000]
times = []

for size in sizes:


# Generate a random array of given size
arr = [i for i in range(size, 0, -1)] # Worst-case (sorted in reverse order)

start_time = time.time()
heap_sort(arr)
end_time = time.time()

# Measure the time it took to sort


times.append(end_time - start_time)

# Plotting the graph


plt.plot(sizes, times, marker='o')
plt.xlabel("Array Size")
plt.ylabel("Time (seconds)")
plt.title("Heap Sort Time Complexity")
plt.grid(True)
plt.show()

# Main function
if __name__ == "__main__":
# Option 1: Heap sort with user input
arr = get_input()
print(f"Original Array: {arr}")
heap_sort(arr)
print(f"Sorted Array: {arr}")

# Option 2: Plot time complexity graph


plot_time_complexity()
OUTPUT:

Enter the number of elements in the array: 5


Enter element 1: 7
Enter element 2: 2
Enter element 3: 9
Enter element 4: 1
Enter element 5: 5
Original Array: [7, 2, 9, 1, 5]
Sorted Array: [1, 2, 5, 7, 9]
5(A)-DYNAMIC PROGRAMMING
(COIN CHANGING PROBLEM)

PROGRAM:

# Function to find the minimum number of coins needed to make the given amount
def coin_change(coins, amount):
# Create a dp array to store the minimum coins required for each amount up to the target
amount
dp = [float('inf')] * (amount + 1)
dp[0] = 0 # Base case: 0 coins are needed to make 0 amount

# Iterate over each coin denomination


for coin in coins:
# Update the dp array for each amount from coin value to the target amount
for i in range(coin, amount + 1):
dp[i] = min(dp[i], dp[i - coin] + 1)

# If dp[amount] is still infinity, return -1, meaning it's not possible to form that amount
return dp[amount] if dp[amount] != float('inf') else -1

# Function to take runtime input for coins and amount


def get_input():
n = int(input("Enter the number of coin denominations: "))
coins = list(map(int, input(f"Enter the {n} coin denominations (space separated): ").split()))
amount = int(input("Enter the total amount: "))
return coins, amount

# Main function
if __name__ == "__main__":
# Get user input for coins and amount
coins, amount = get_input()

# Call the coin_change function to find the result


result = coin_change(coins, amount)

# Print the result


if result == -1:
print("It is not possible to make the amount with the given coins.")
else:
print(f"The minimum number of coins needed to make the amount {amount} is: {result}")
OUTPUT:

Enter the number of coin denominations: 3


Enter the 3 coin denominations (space separated): 1 2 5
Enter the total amount: 11
The minimum number of coins needed to make the amount 11 is: 3
5(B)-DYNAMIC PROGRAMING
WARSHALL’S AND FLOYD’S ALGORITHM

PROGRAM:

# Floyd-Warshall Algorithm for All-Pairs Shortest Paths


def floyd_warshall(graph, V):
# Initialize distance matrix
dist = [[float('inf')] * V for _ in range(V)]

# Set distance to 0 for all diagonal elements (distance from a vertex to itself)
for i in range(V):
dist[i][i] = 0

# Populate the initial distances based on the input graph


for u in range(V):
for v, weight in graph[u]:
dist[u][v] = weight

# Perform Floyd-Warshall algorithm


for k in range(V):
for i in range(V):
for j in range(V):
# Update the distance matrix with the shortest path between i and j
if dist[i][j] > dist[i][k] + dist[k][j]:
dist[i][j] = dist[i][k] + dist[k][j]

return dist
# Function to take input for graph
def get_input_floyd():
V = int(input("Enter the number of vertices in the graph: "))
graph = [[] for _ in range(V)]

E = int(input(f"Enter the number of edges: "))


print("Enter each edge as 'u v weight' where u, v are vertices and weight is the edge weight:")
for _ in range(E):
u, v, w = map(int, input().split())
graph[u].append((v, w)) # Directed edge u -> v with weight w

return graph, V

# Main function for Floyd-Warshall


if __name__ == "__main__":
graph, V = get_input_floyd()
dist = floyd_warshall(graph, V)

# Print the shortest path matrix


print("\nShortest Path Matrix:")
for row in dist:
print(row)
OUTPUT:

Enter the number of vertices in the graph: 4


Enter the number of edges: 5
Enter each edge as 'u v weight' where u, v are vertices and weight is the edge weight:
015
0 2 10
123
231
302
Shortest Path Matrix:
[0, 5, 8, 7]
[5, 0, 3, 4]
[6, 6, 0, 1]
[2, 7, 3, 0]
5(C)-DYNAMIC PROGRAMING
KNAPSACK PROBLEM

PROBLEM:

# Function to solve the knapsack problem using dynamic programming


def knapsack(weights, values, W, n):
# Create a DP table with (n+1) rows and (W+1) columns
dp = [[0] * (W + 1) for _ in range(n + 1)]

# Fill the DP table


for i in range(1, n + 1):
for w in range(1, W + 1):
if weights[i - 1] <= w: # If the item can fit in the knapsack
dp[i][w] = max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1])
else:
dp[i][w] = dp[i - 1][w]

return dp[n][W]

# Function to take runtime input


def get_input():
n = int(input("Enter the number of items: "))
weights = list(map(int, input(f"Enter the weights of {n} items (space separated): ").split()))
values = list(map(int, input(f"Enter the values of {n} items (space separated): ").split()))
W = int(input("Enter the weight capacity of the knapsack: "))
return weights, values, W, n

# Main function
if __name__ == "__main__":
weights, values, W, n = get_input()

max_value = knapsack(weights, values, W, n)

print(f"\nMaximum value that can be obtained: {max_value}")


OUTPUT:

Enter the number of items: 4


Enter the weights of 4 items (space separated): 2 3 4 5
Enter the values of 4 items (space separated): 3 4 5 6
Enter the weight capacity of the knapsack: 5
Maximum value that can be obtained: 7

You might also like