Ds Lab Assignments-1
Ds Lab Assignments-1
def compute_average_borrowings(records):
total_books = sum(len(books) for books in records.values())
total_members = len(records)
average = total_books / total_members if total_members > 0 else 0
return average
def book_borrow_counts(records):
counter = Counter ()
for books in records.values():
counter.update(books)
return counter
def highest_lowest_borrowed(counter):
if not counter:
return None, None
most = counter.most_common(1)[0]
least = min(counter.items(), key=lambda x: x[1])
return most, least
def count_non_borrowers(records):
return sum(1 for books in records.values() if len(books) == 0)
def most_frequent_book(counter):
if not counter:
return None
mode_count = max(counter.values())
modes = [book for book, count in counter.items() if count == mode_count]
return modes
# Execution
average = compute_average_borrowings(borrow_records)
counter = book_borrow_counts(borrow_records)
highest, lowest = highest_lowest_borrowed(counter)
non_borrowers = count_non_borrowers(borrow_records)
most_frequent = most_frequent_book(counter)
# Output
print (f"Average number of books borrowed: {average:.2f}")
print (f"Book with highest borrowings: {highest}")
print (f"Book with lowest borrowings: {lowest}")
print (f"Number of members who have not borrowed any books:
{non_borrowers}")
print (f"Most frequently borrowed book(s): {most_frequent}")
GROUP A-2
In an e-commerce system, customer account IDs are stored in a list, and you
are tasked with
Writing a program that implements the following:
•LinearSearch:Check if a particular customer account ID exists in the list.
linear_search(account_list, target_id):
for account_id in account_list:
if account_id == target_id:
return True # Found
return False # Not found
# ID to search for
target = 'C103'
if mid_id == target_id:
return True # Found
elif mid_id < target_id:
low = mid + 1
else:
high = mid - 1
# ID to search
target = 'C103'
Selection Sort
python
def selection_sort(salaries):
for i in range(len(salaries)):
min_index = i
for j in range (i+1, len(salaries)):
if salaries[j] < salaries[min_index]:
min_index = j
salaries[i], salaries[min_index] = salaries[min_index], salaries[i]
return salaries
Bubble Sort
python
def bubble_sort(salaries):
n = len(salaries)
for i in range(n):
for j in range (0, n-i-1):
if salaries[j] > salaries[j+1]:
salaries[j], salaries[j+1] = salaries[j+1], salaries[j]
return salaries
Once sorted, you can display the five highest like so:
python
def top_five_highest(salaries):
return salaries [-5:] # last 5 elements after ascending sort
Combine everything:
python
salaries = [56000.75, 42000.50, 78000.00, 89000.25, 62000.80, 51000.30,
99000.00]
sorted_salaries = selection_sort(salaries.copy())
print ("Top 5 highest salaries (Selection Sort):",
top_five_highest(sorted_salaries))
sorted_salaries = bubble_sort(salaries.copy())
print ("Top 5 highest salaries (Bubble Sort):",
top_five_highest(sorted_salaries))
GROUP B-1
Implementing a real-time undo/redo system for M a text editing application
using a Stack data
Implementing a real-time undo/redo system for a text editing application
using a Stack data
structure. The system should support the following operations:
• Make a Change: A new change to the document is made.
• Undo Action: Revert the most recent change and store it for potential
redo.
• Redo Action: Reapply the most recently undone action.
• Display Document State: Show the current state of the document after
undoing or redoing an action
class TextEditor:
def __init__(self):
self.undo_stack = []
self.redo_stack = []
self.current_state = ""
def undo_action(self):
if not self.undo_stack:
print ("Nothing to undo.")
return
self.redo_stack.append(self.current_state)
self.current_state = self.undo_stack.pop()
print ("Undo performed.")
def redo_action(self):
if not self.redo_stack:
print ("Nothing to redo.")
return
self.undo_stack.append(self.current_state)
self.current_state = self.redo_stack.pop()
print ("Redo performed.")
def display_document_state(self):
print (f" Current Document State:\n{self.current_state}")
editor = TextEditor()
editor.make_change("Hello")
editor.make_change("Hello, World!")
editor.display_document_state()
editor.undo_action()
editor.display_document_state()
editor.redo_action()
editor.display_document_state()
#OUTPUT
Change made.
Change made.
Current Document State:
Hello, World!
Undo performed.
Current Document State:
Hello
Redo performed.
Current Document State:
Hello, World!
GROUP B-2
Implement a real-time event processing system using a Queue data
structure. The system
should support the following features:
• Add an Event: When a new event occurs, it should be added to the event
queue.
• Process the Next Event: The system should process and remove the
event that has been in the queue the longest.
• Display Pending Events: Show all the events currently waiting to be
processed.
• Cancel an Event: An event can be canceled if it has not been processed.
class EventProcessor:
def __init__(self):
self.event_queue = deque ()
def process_next_event(self):
if not self.event_queue:
print (" No events to process.")
return
event = self.event_queue.popleft()
print (f"Processed event: {event}")
def display_pending_events(self):
if not self.event_queue:
print (" No pending events.")
else:
print (" Pending Events:")
for idx, event in enumerate (self.event_queue, 1):
print(f"{idx}. {event}")
#OUT PUT
Event added: User Login
Event added: File Upload
Event added: Data Backup
Pending Events:
1. User Login
2. File Upload
3. Data Backup
Canceled event: File Upload
Pending Events:
1. User Login
2. Data Backup
Processed event: User Login
Pending Events:
1. Data Backup
Group C - Hashing
Implement a hash table of size 10 and use the division method as a hash
function. In case of
a collision, use chaining. Implement the following operations:
• Insert(key): Insert key-value pairs into the hash table.
• Search(key): Search for the value associated with a given key.
• Delete(key): Delete a key-value pair from the hash table
hash_index = key % 10
class HashTable:
def __init__(self, size=10):
self.size = size
self.table = [[ ] for _ in range(size)] # Each slot is a list for chaining
def display(self):
for i, chain in enumerate(self.table):
print(f"Index {i}: {chain}")
#output
Design and implement a hash table of fixed size. Use the division method for
the hash
function and resolve collisions using linear probing. Allow the user to perform
the following operations:
• Insert a key
• Search for a key
• Delete a key
• Display the table
Special Note: We use a sentinel value (None) for empty slots and a special
marker ("DELETED") to indicate deleted entries.
class LinearProbingHashTable:
def __init__(self, size=10):
self.size = size
self.table = [None] * size
def display(self):
print("Hash Table Contents:")
for i, val in enumerate(self.table):
print(f"Index {i}: {val}")
ht = LinearProbingHashTable()
ht.insert(10)
ht.insert(20)
ht.insert(30)
ht.insert(25) # Will cause collision with 10 if size is 10
print("Search 20:", ht.search(20)) # True
print("Search 99:", ht.search(99)) # False
ht.delete(20)
print("Search 20 after deletion:", ht.search(20)) # False
ht.display()
Implement a hash table with extendible hashing. The hash table should
dynamically expand
when the number of keys in a bucket exceeds a certain threshold. Perform
the following operations:
• Insert(key): Insert key-value pairs into the hash table
• Search(key): Search for the value associated with a given key
• Delete(key): Delete a key-value pair from the hash table
class Bucket:
def __init__(self, depth, size_limit):
self.local_depth = depth
self.size_limit = size_limit
self.items = {}
def is_full(self):
return len(self.items) >= self.size_limit
class ExtendibleHashTable:
def __init__(self, bucket_size=2):
self.global_depth = 1
self.bucket_size = bucket_size
self.directory = [Bucket(depth=1, size_limit=bucket_size) for _ in
range(2)]
def _hash(self, key):
return hash(key) & ((1 << self.global_depth) - 1)
if not bucket.is_full():
bucket.insert(key, value)
else:
if bucket.local_depth == self.global_depth:
self._double_directory()
self._split_bucket(index)
self.insert(key, value) # Retry insertion
def _double_directory(self):
self.global_depth += 1
new_directory = []
for bucket in self.directory:
new_directory.append(bucket)
new_directory.append(bucket)
self.directory = new_directory
# Redistribute keys
keys_to_redistribute = list(old_bucket.items.items())
old_bucket.items.clear()
for key, value in keys_to_redistribute:
new_index = hash(key) & ((1 << self.global_depth) - 1)
if (hash(key) >> (new_depth - 1)) & 1:
new_bucket.insert(key, value)
else:
old_bucket.insert(key, value)
#output
ht = ExtendibleHashTable(bucket_size=2)
ht.insert("apple", 1)
ht.insert("banana", 2)
ht.insert("cherry", 3)
ht.insert("date", 4)
print(ht.search("banana")) # Output: 2
ht.delete("banana")
print(ht.search("banana")) # Output: None
#include <stdio.h>
#include <stdlib.h>
#define MAX 5
int visitedDFS[MAX];
void buildAdjList() {
for (int i = 0; i < MAX; i++)
adjList[i] = NULL;
return 0;
}
DFS Traversal (Adjacency Matrix) starting from A:
ABDCE
// Dijkstra's algorithm
void dijkstra(int src) {
for (int i = 0; i < n; i++) {
dist[i] = INF;
visited[i] = 0;
}
dist[src] = 0;
// Main function
int main() {
int src;
printf("Enter number of locations: ");
scanf("%d", &n);
dijkstra(src);
return 0;
}
#output
Enter number of locations: 5
Enter time matrix:
0 10 0 30 100
10 0 50 0 0
0 50 0 20 10
30 0 20 0 60
100 0 10 60 0
Enter pizza shop location (0 to 4): 0
#include <stdio.h>
#include <stdlib.h>
// In-order traversal
void inorder(struct Node* root) {
if (root != NULL) {
inorder(root->left);
printf("%d ", root->data);
inorder(root->right);
}
}
// Main function
int main() {
struct Node* root = NULL;
int choice, value;
while (1) {
printf("\n--- Binary Search Tree Operations ---\n");
printf("1. Insert\n2. Delete\n3. Search\n4. Display (In-order)\n5. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter value to insert: ");
scanf("%d", &value);
root = insert(root, value);
break;
case 2:
printf("Enter value to delete: ");
scanf("%d", &value);
root = delete(root, value);
break;
case 3:
printf("Enter value to search: ");
scanf("%d", &value);
if (search(root, value))
printf("Value found in BST.\n");
else
printf("Value not found.\n");
break;
case 4:
printf("BST in-order traversal: ");
inorder(root);
printf("\n");
break;
case 5:
printf("Exiting...\n");
exit(0);
default:
printf("Invalid choice. Try again.\n");
}
}
return 0;
}
## output
--- Binary Search Tree Operations ---
1. Insert
2. Delete
3. Search
4. Display (In-order)
5. Exit
Enter your choice: 1
Enter value to insert: 50
4. Construct an expression tree from the given prefix expression, e.g., +--
a*bc/def, traverse it using post-order traversal (non-recursive), and
then delete the entire tree.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void initStack(Stack* s) {
s->top = -1;
}
int isEmpty(Stack* s) {
return s->top == -1;
}
Node* pop(Stack* s) {
return s->items[s->top--];
}
int len = 0;
while (expr[len] != '\0') len++;
if (isOperator(ch)) {
node->left = pop(&s);
node->right = pop(&s);
}
push(&s, node);
}
return pop(&s);
}
push(&s1, root);
while (!isEmpty(&s1)) {
Node* node = pop(&s1);
push(&s2, node);
while (!isEmpty(&s2)) {
Node* node = pop(&s2);
printf("%c ", node->data);
}
}
// Main function
int main() {
char expr[] = "+--a*bc/def"; // Example prefix expression
Node* root = buildTree(expr);
deleteTree(root);
printf("Expression tree deleted.\n");
return 0;
}
Post-order traversal (non-recursive): a b c * - d e f / - +
Expression tree deleted.
A list stores city names and their populations. Use a Binary Search Tree
for implementation.
Provide a facility for adding new cities, deleting a city, and updating
population values. Provide a facility to display all the city names in
ascending/descending order. Also, find how many maximum
comparisons are required to search for a particular city.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME 50
// Delete a city
Node* delete(Node* root, char* city) {
if (root == NULL) return NULL;
if (strcmp(city, root->city) < 0)
root->left = delete(root->left, city);
else if (strcmp(city, root->city) > 0)
root->right = delete(root->right, city);
else {
if (root->left == NULL) {
Node* temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL) {
Node* temp = root->left;
free(root);
return temp;
}
Node* temp = findMin(root->right);
strcpy(root->city, temp->city);
root->population = temp->population;
root->right = delete(root->right, temp->city);
}
return root;
}
// Update population
void updatePopulation(Node* root, char* city, int newPop) {
while (root != NULL) {
int cmp = strcmp(city, root->city);
if (cmp == 0) {
root->population = newPop;
printf("Population updated.\n");
return;
}
else if (cmp < 0)
root = root->left;
else
root = root->right;
}
printf("City not found.\n");
}
// Main function
int main() {
Node* root = NULL;
int choice, population;
char city[MAX_NAME];
while (1) {
printf("\n--- City Population Manager ---\n");
printf("1. Add City\n2. Delete City\n3. Update Population\n4.
Display Ascending\n5. Display Descending\n6. Search Comparisons\n7.
Exit\n");
printf("Enter choice: ");
scanf("%d", &choice);
getchar(); // consume newline
switch (choice) {
case 1:
printf("Enter city name: ");
fgets(city, MAX_NAME, stdin);
city[strcspn(city, "\n")] = 0;
printf("Enter population: ");
scanf("%d", &population);
root = insert(root, city, population);
break;
case 2:
printf("Enter city name to delete: ");
fgets(city, MAX_NAME, stdin);
city[strcspn(city, "\n")] = 0;
root = delete(root, city);
break;
case 3:
printf("Enter city name to update: ");
fgets(city, MAX_NAME, stdin);
city[strcspn(city, "\n")] = 0;
printf("Enter new population: ");
scanf("%d", &population);
updatePopulation(root, city, population);
break;
case 4:
printf("\nCities in Ascending Order:\n");
displayAsc(root);
break;
case 5:
printf("\nCities in Descending Order:\n");
displayDesc(root);
break;
case 6:
printf("Enter city name to search: ");
fgets(city, MAX_NAME, stdin);
city[strcspn(city, "\n")] = 0;
int comps = searchComparisons(root, city);
printf("Maximum comparisons made: %d\n", comps);
break;
case 7:
exit(0);
default:
printf("Invalid choice.\n");
}
}
return 0;
}
#output