0% found this document useful (0 votes)
2 views21 pages

15 Marks Python .

The document contains answer keys for a data structures course using Python, including various programming tasks. It covers topics such as regex matching, Armstrong numbers, hierarchical inheritance, circular queues, and B+ trees. Each section provides code examples and expected outputs for the given problems.

Uploaded by

esakim877
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)
2 views21 pages

15 Marks Python .

The document contains answer keys for a data structures course using Python, including various programming tasks. It covers topics such as regex matching, Armstrong numbers, hierarchical inheritance, circular queues, and B+ trees. Each section provides code examples and expected outputs for the given problems.

Uploaded by

esakim877
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

19CS303 – Fundamentals of Data Structures using Python

ANSWER KEY
PART A

PART C

*QC10 (a)
1 I) Create a Python program to find the sequences of one Lower case letter followed by Upper
case letters. (8 Marks)

Ans

import re
def text_match(text):
patterns = '[A-Z]+[a-z]+$'
if [Link](patterns, text):
return 'Found a match!'
else:
return('Not matched!')
print(text_match("AaBbGg"))
print(text_match("Python"))
print(text_match("python"))
print(text_match("PYTHON"))
print(text_match("aA"))
print(text_match("Aa"))

OUTPUT:
Found a match!
Found a match!
Not matched!
Not matched!
Not matched!
Found a match!

II) Design a Python program to check whether a number is an Armstrong number or not. (7
marks)

Ans:

def is_armstrong(number):
# Convert the number to string to get the number of digits
num_str = str(number)
num_digits = len(num_str)
1
# Calculate the sum of digits raised to the power of the number of digits
total = sum(int(digit) ** num_digits for digit in num_str)

# Check if the sum is equal to the original number


return total == number

# Main function
def main():
# Accept number input
number = int(input("Enter a number: "))

# Check if it's Armstrong


if is_armstrong(number):
print(f"{number} is an Armstrong number.")
else:
print(f"{number} is not an Armstrong number.")

# Run the program


main()

Enter a number: 153


153 is an Armstrong number.

Enter a number: 123


123 is not an Armstrong number.
(b) Write a Python program that accepts a sentence from the user, and then:
1. Counts the number of vowels.
2. Reverses the sentence.
3. Counts how many words are in the sentence.
4. Converts every word's first letter to uppercase (title case).

# Function to count vowels in a sentence


def count_vowels(sentence):
vowels = "aeiouAEIOU"
count = 0
for char in sentence:
if char in vowels:
count += 1
return count
*QC10
1
# Function to reverse a sentence
def reverse_sentence(sentence):
return sentence[::-1]

# Function to count words


def count_words(sentence):
words = [Link]()
return len(words)

# Function to title-case each word


def title_case(sentence):
return [Link]()

# Main function
2
def main():
sentence = input("Enter a sentence: ")

print("\n--- Results ---")


print("Original Sentence:", sentence)
print("Number of Vowels:", count_vowels(sentence))
print("Reversed Sentence:", reverse_sentence(sentence))
print("Number of Words:", count_words(sentence))
print("Title Case Sentence:", title_case(sentence))

# Run the program


main()

Output:

Enter a sentence:
hello how are you

--- Results ---


Original Sentence: hello how are you
Number of Vowels: 7
Reversed Sentence: uoy era woh olleh
Number of Words: 4
Title Case Sentence: Hello How Are You

(a) Write a Python program to Get the employee and patient details & display it using Hierarchical
inheritance.
Note: create a parent (base) class name Details and two child (derived) classes
named Employee and Patient.

# Base class
class Details:
def __init__(self, id, name, gender):
[Link] = id
[Link] = name
[Link] = gender

def display_details(self):
print(f"Id: {[Link]}")
*QC20 print(f"Name: {[Link]}")
1 print(f"Gender: {[Link]}")

# Derived class: Employee


class Employee(Details):
def __init__(self, id, name, gender, company, department):
super().__init__(id, name, gender)
[Link] = company
[Link] = department

def display_details(self):
print("Employee Object")
super().display_details()
print(f"Company: {[Link]}")
print(f"Department: {[Link]}")

3
# Derived class: Patient
class Patient(Details):
def __init__(self, id, name, gender, hospital, department):
super().__init__(id, name, gender)
[Link] = hospital
[Link] = department

def display_details(self):
print("Patient Object")
super().display_details()
print(f"Hospital: {[Link]}")
print(f"Department: {[Link]}")

# Main function
def main():
# Input for Employee
eid = int(input())
ename = input()
egender = input()
ecompany = input()
edepartment = input()

employee = Employee(eid, ename, egender, ecompany, edepartment)

# Input for Patient


pid = int(input())
pname = input()
pgender = input()
phospital = input()
pdepartment = input()

patient = Patient(pid, pname, pgender, phospital, pdepartment)

# Output
employee.display_details()
print()
patient.display_details()

# Run the program


main()

OUTPUT:

121
Srini
Male
AMS
EEE
201
Raj
Male
AIMS
Ear
Employee Object
4
Id: 121
Name: Srini
Gender: Male
Company: AMS
Department: EEE

Patient Object
Id: 201
Name: Raj
Gender: Male
Hospital: AIMS
Department: Ear
(b) Design a python code to implement a parameterized constructor that will initialize the
employee_name, employee_id , basic pay, da, hra, cca, pf, ded of an employee and print
the details using user defined function.

class Employee:
def __init__(self, employee_name, employee_id, basic_pay, da, hra, cca, pf, ded):
# Parameterized constructor
self.employee_name = employee_name
self.employee_id = employee_id
self.basic_pay = basic_pay
[Link] = da
[Link] = hra
[Link] = cca
[Link] = pf
[Link] = ded

def display_details(self):
# User-defined function to print details
print(f"\nEmployee Details:")
print(f"Name : {self.employee_name}")
*QC20 print(f"Employee ID : {self.employee_id}")
1 print(f"Basic Pay : {self.basic_pay}")
print(f"DA : {[Link]}")
print(f"HRA : {[Link]}")
print(f"CCA : {[Link]}")
print(f"PF : {[Link]}")
print(f"Deductions : {[Link]}")

gross_pay = self.basic_pay + [Link] + [Link] + [Link]


net_pay = gross_pay - [Link] - [Link]
print(f"Gross Pay : {gross_pay}")
print(f"Net Pay : {net_pay}")

# Example usage:
emp1 = Employee(
employee_name="Alice Smith",
employee_id="EMP123",
basic_pay=30000,
da=5000,
hra=8000,
cca=1000,
5
pf=2000,
ded=1500
)

emp1.display_details()

OUTPUT:

Employee Details:
Name : Alice Smith
Employee ID : EMP123
Basic Pay : 30000
DA : 5000
HRA : 8000
CCA : 1000
PF : 2000
Deductions : 1500
Gross Pay : 44000
Net Pay : 40500

(a) I) Create a Python function to delete a float element from and insert a float element into the
circular queue.

Ans

class CircularQueue:
def __init__(self, size):
[Link] = size
[Link] = [None] * size # Initialize empty queue
[Link] = -1
[Link] = -1

def enqueue(self, value):


if not isinstance(value, float):
print("Only float values are allowed.")
return
QC301
# Check if queue is full
if ([Link] + 1) % [Link] == [Link]:
print("Queue is full. Cannot insert.")
return

# First element to be inserted


if [Link] == -1:
[Link] = 0
[Link] = 0
else:
[Link] = ([Link] + 1) % [Link]

[Link][[Link]] = value
print(f"Inserted: {value}")

def dequeue(self):
if [Link] == -1:

6
print("Queue is empty. Cannot delete.")
return None

removed = [Link][[Link]]
[Link][[Link]] = None

# If the queue becomes empty after deletion


if [Link] == [Link]:
[Link] = -1
[Link] = -1
else:
[Link] = ([Link] + 1) % [Link]

print(f"Deleted: {removed}")
return removed

def display(self):
if [Link] == -1:
print("Queue is empty.")
return

print("Queue elements:")
i = [Link]
while True:
print([Link][i], end=" ")
if i == [Link]:
break
i = (i + 1) % [Link]
print()

# Example usage
cq = CircularQueue(5)
[Link](1.1)
[Link](2.2)
[Link](3.3)
[Link]()
[Link]()
[Link]()
[Link](4.4)
[Link](5.5)
[Link](6.6) # This may fill the queue
[Link]()
[Link](7.7) # Should print "Queue is full"

OUTPUT:
Inserted: 1.1
Inserted: 2.2
Inserted: 3.3
Queue elements:
1.1 2.2 3.3
Deleted: 1.1
Queue elements:
2.2 3.3
Inserted: 4.4
Inserted: 5.5
7
Inserted: 6.6
Queue elements:
2.2 3.3 4.4 5.5 6.6
Queue is full.

(b) i)Write a Python program to insert 14, 15 at FRONT END of deque using collection built-in
function. (8 marks)
For example:
Input Result

11 The deque after appending is :


12 deque([15, 14, 11, 12, 13])
13

from collections import deque

# Create an empty deque


d = deque()

# Take 3 user inputs and append to the deque


for _ in range(3):
num = int(input())
[Link](num)

# Insert 15 and 14 at the front end


[Link](14)
[Link](15)

# Display the final deque


*QC30
print("The deque after appending is :")
1
print(d)

Output:
11
12
13
The deque after appending is :
deque([15, 14, 11, 12, 13])

ii)Write a Python program to delete element at REAR END of deque using collection built-in
function. (7 marks)

For example:
Input Result

p The deque after deleting at right is :


y deque(['p', 'y'])
t

from collections import deque

# Create an empty deque


d = deque()
8
# Take 3 character inputs
for _ in range(3):
ch = input()
[Link](ch)

# Delete from rear (right side)


[Link]()

# Display the final deque


print("The deque after deleting at right is :")
print(d)

Output:

p
y
t
The deque after deleting at right is :
deque(['p', 'y'])
[Link]() removes the last element from the deque (i.e., from the right/rear).
(a) Write a python function def insert(self, k): to insert the nodes in a B+ Tree.

PROGRAM
class Node(object):

def __init__(self, order):

[Link] = order
[Link] = []
[Link] = []
[Link] = True

def add(self, key, value):

if not [Link]:
[Link](key)
*QC40 [Link]([value])
1 return None

for i, item in enumerate([Link]):

if key == item:
[Link][i].append(value)
break

elif key < item:


[Link] = [Link][:i] + [key] + [Link][i:]
[Link] = [Link][:i] + [[value]] + [Link][i:]
break

elif i + 1 == len([Link]):
[Link](key)
9
[Link]([value])

def split(self):

left = Node([Link])
right = Node([Link])
mid = [Link] // 2

[Link] = [Link][:mid]
[Link] = [Link][:mid]

[Link] = [Link][mid:]
[Link] = [Link][mid:]

[Link] = [[Link][0]]
[Link] = [left, right]
[Link] = False

def is_full(self):

return len([Link]) == [Link]

def show(self, counter=0):

print(counter, str([Link]))

if not [Link]:
for item in [Link]:
[Link](counter + 1)

class BPlusTree(object):

def __init__(self, order=8):


[Link] = Node(order)

def _find(self, node, key):

for i, item in enumerate([Link]):


if key < item:
return [Link][i], i
return [Link][i + 1], i + 1

def _merge(self, parent, child, index):

[Link](index)
pivot = [Link][0]

for i, item in enumerate([Link]):


if pivot < item:
[Link] = [Link][:i] + [pivot] + [Link][i:]
[Link] = [Link][:i] + [Link] + [Link][i:]
break

10
elif i + 1 == len([Link]):
[Link] += [pivot]
[Link] += [Link]
break

def insert(self, key, value):

parent = None
child = [Link]

while not [Link]:


parent = child
child, index = self._find(child, key)

[Link](key, value)

if child.is_full():
[Link]()

if parent and not parent.is_full():


self._merge(parent, child, index)

def retrieve(self, key):

child = [Link]

while not [Link]:


child, index = self._find(child, key)

for i, item in enumerate([Link]):


if key == item:
return [Link][i]

return None
def show(self):

[Link]()

def demo_node():
node = Node(order=4)
[Link]('a', 'alpha')
[Link]('b', 'bravo')
[Link]('c', 'charlie')
[Link]('d', 'delta')
[Link]()

print('\nSplitting node...')
[Link]()
[Link]()

def demo_bplustree():
print('B+ tree...')

11
bplustree = BPlusTree(order=4)
x=’f’
y=’ab’
[Link]('a', 'alpha')
[Link]('b', 'bravo')
[Link]('c', 'charlie')
[Link]('d', 'delta')
[Link]('e', 'echo')
[Link](x,y)
[Link]()

if __name__ == '__main__':
demo_node()
print('\n')
demo_bplustree()

(b) Explain Set Operations such as a) UNION b) FIND c) INTERSECTION using TREE Data
Structure?

Ans

Union Find

A Union-Find/Disjoint set data structure is used to maintain a set of elements partitioned into a

number of mutually non-overlapping subsets.

Disjoint Set —A disjoint set is a group of sets where no item can be in more than one set. In other

words, if we take any two sets from the Disjoint set then their intersection will result in an empty set.

QC401 In even simpler terms a disjoint set is a data structure where similar elements are kept in a single

group.

There are two main operations DSU performs on sets:

12
Find — Tells us an element/node belongs to which subset.

Union — Join two subsets, if they share a common attribute

In this approach, we represent the nodes using an array, and the value of the item at that index tells

which set that node belongs to. Depending upon the strategy used the value may represent its

parent or the reference to the representative of the set.

Quick Find

class QuickFind():
def __init__(self,N):
self._parents = list(range(0, N))def find(self, p):
return(self._parents[p])

def union(self, p, q):


root_p, root_q = self._parents[p], self._parents[q]
for i in range(0, len(self._parents)):
if(self._parents[i] == root_p):
self._parents[i] = root_q def connected(self,p,q):
return self._parents[p] == self._parents[q]

Quick Union

class QuickUnion():
def __init__(self,N):
self._parents = list(range(0,N))

13
def find(self, p):
while(p != self._parents[p]):
p = self._parents[p]
return p

def union(self, p, q):


root_p, root_q = [Link](p), [Link](q)
self._parents[i] = root_q def connected(self, p, q):
return [Link](p)==[Link](q)

Optimized Disjoint Set

We can significantly improve the implementation of the disjoint set by using two techniques:

Union By Rank — Union by rank always attaches the shorter tree to the root of the taller tree.

Path Compression — By making every other node in the path point to its grandparent's node, we

can constantly flatten the tree by altering the parent node to the root node and halving the path

length.

Weighted Quick Union with optimization

class DisJointSets():
def __init__(self,N):
# Initially, all elements are single element subsets
self._parents = [node for node in range(N)]
self._ranks = [1 for _ in range(N)]

def find(self, u):


while u != self._parents[u]:
# path compression technique
self._parents[u] = self._parents[self._parents[u]]
u = self._parents[u]
return u

def connected(self, u, v):

14
return [Link](u) == [Link](v)

def union(self, u, v):


# Union by rank optimization
root_u, root_v = [Link](u), [Link](v)
if root_u == root_v:
return True
if self._ranks[root_u] > self._ranks[root_v]:
self._parents[root_v] = root_u
elif self._ranks[root_v] > self._ranks[root_u]:
self._parents[root_u] = root_v
else:
self._parents[root_u] = root_v
self._ranks[root_v] += 1
return False

Time Complexity

Find — log(N)

Union — log(N)

Problem 1

N students applied for admission to ABC Academy. An array of integers B is given representing

the strengths of N people i.e. B[i] represents the strength of the ith student. Among the N students,

some of them knew each other. A matrix C of size M x 2 is given which represents relations where

ith relations depict that C[i][0] and C[i][1] knew each other. All students who know each other are

placed in one batch. The strength of a batch is equal to the sum of the strength of all the students in

it. ABC sets criteria for selection: All those batches having a strength of at least D are selected.

Find the number of batches selected.

Example:

N=7
B = [1, 6, 7, 2, 9, 4, 5]
C = [[1, 2], [2, 3], [5, 6], [5, 7]]
D = 12Ans: 2
Initial Batches :
Batch 1 = {1, 2, 3} Batch Strength = 1 + 6 + 7 = 14
Batch 2 = {4} Batch Strength = 2
Batch 3 = {5, 6, 7} Batch Strength = 9 + 4 + 5 = 18
Selected Batches are Batch 1 and Batch 2.

15
We have to create subsets where only students who are friends are in a single subset. Disjoint Sets

will be the right choice here.

Code Implementation

def solve(N, B, C, D):


parent = list(range(N))
def find(x):
if x != parent[x]:
parent[x] = find(parent[x])
return parent[x]

def union(x, y):


parent_x = find(x)
parent_y = find(y)
if parent_x != parent_y:
parent[parent_y] = parent_x

for x, y in C:
union(x-1, y-1)

from collections import defaultdict


dict_pair = defaultdict(list)
for idx, val in enumerate(parent):
dict_pair[find(val)].append(B[idx])

res = 0
for v in dict_pair.values():
if sum(v) >= D:
res += 1
return res

(a) Write a Python program to implement BFS and DFS traversal from a given source vertex.

from collections import deque, defaultdict

class Graph:
def __init__(self):
[Link] = defaultdict(list)

*QC50 def add_edge(self, u, v):


1 [Link][u].append(v)
# Uncomment the next line if the graph is
undirected:
# [Link][v].append(u)

def bfs(self, start):


visited = set()
queue = deque([start])
[Link](start)

16
print("BFS Traversal:", end=" ")

while queue:
vertex = [Link]()
print(vertex, end=" ")

for neighbor in [Link][vertex]:


if neighbor not in visited:
[Link](neighbor)
[Link](neighbor)

print()

def dfs_util(self, vertex, visited):


[Link](vertex)
print(vertex, end=" ")

for neighbor in [Link][vertex]:


if neighbor not in visited:
self.dfs_util(neighbor, visited)

def dfs(self, start):


visited = set()
print("DFS Traversal:", end=" ")
self.dfs_util(start, visited)
print()

# Main program
if __name__ == "__main__":
g = Graph()

n = int(input("Enter number of edges: "))


print("Enter edges in the format 'u v':")
for _ in range(n):
u, v = input().split()
g.add_edge(u, v)

source = input("Enter source vertex for


traversal:”)

[Link](source)
[Link](source)

Output:
Enter number of edges: 5
Enter edges in the format 'u v':
AB
AC
BD
CD
DE
Enter source vertex for traversal: A

BFS Traversal: A B C D E
DFS Traversal: A B D E C
17
(b) Explain Kruskal’s algorithm in detail. Write a Python program for the same to find the
Minimum Spanning Tree of a given connected, undirected and weighted graph.

Kruskal's Algorithm for Minimum Spanning Tree (MST)

Kruskal’s Algorithm is a greedy algorithm used to find the Minimum Spanning Tree (MST) of
a connected, undirected, and weighted graph.

Key Concepts

A Spanning Tree is a subgraph that includes all the vertices of the original graph and is a single
connected tree.

A Minimum Spanning Tree (MST) is a spanning tree with the least total edge weight.

Kruskal’s algorithm selects edges in increasing order of weight and adds them to the MST only
if they don’t form a cycle.

Steps of Kruskal’s Algorithm

Sort all edges in the graph by their weights in ascending order.

Initialize the MST as an empty set.


QC501 Use a Disjoint Set Union (DSU) or Union-Find structure to keep track of connected
components.

Iterate through the sorted edges and for each edge:

If the vertices it connects are in different sets, include the edge in the MST and merge the sets.

If they are in the same set, skip it (to avoid a cycle).

Repeat until MST contains (V - 1) edges, where V is the number of vertices.

Python Implementation

class DisjointSet:

def __init__(self, vertices):

[Link] = {v: v for v in vertices}

[Link] = {v: 0 for v in vertices}

def find(self, v):

if [Link][v] != v:

18
[Link][v] = [Link]([Link][v]) # Path compression

return [Link][v]

def union(self, u, v):

root_u = [Link](u)

root_v = [Link](v)

if root_u != root_v:

# Union by rank

if [Link][root_u] > [Link][root_v]:

[Link][root_v] = root_u

elif [Link][root_u] < [Link][root_v]:

[Link][root_u] = root_v

else:

[Link][root_v] = root_u

[Link][root_u] += 1

return True

return False

def kruskal(vertices, edges):

ds = DisjointSet(vertices)

mst = []

total_weight = 0

# Sort edges by weight

[Link](key=lambda edge: edge[2])

for u, v, weight in edges:

if [Link](u, v):

19
[Link]((u, v, weight))

total_weight += weight

return mst, total_weight

# Example usage

vertices = ['A', 'B', 'C', 'D', 'E']

edges = [

('A', 'B', 1),

('A', 'C', 3),

('B', 'C', 1),

('B', 'D', 6),

('C', 'D', 4),

('C', 'E', 2),

('D', 'E', 5)

mst, weight = kruskal(vertices, edges)

print("Edges in MST:")

for u, v, w in mst:

print(f"{u} - {v}: {w}")

print(f"Total Weight of MST: {weight}")

Output

Edges in MST:

A - B: 1

B - C: 1

C - E: 2

C - D: 4

Total Weight of MST: 8

20
21

You might also like