Download as pdf or txt
Download as pdf or txt
You are on page 1of 16

Printed Pages: 2 Sub Code:KNC-402

Paper Id: 238061 Roll No.

B.Tech.
(SEM IV) THEORY EXAMINATION 2022-23
PYTHON PROGRAMMING
MODEL SOLUTION

Time: 3 Hours Total Marks: 100

Note: Attempt all Sections. If require any missing data; then choose suitably.

SECTION A

1. Attempt all questions in brief. 2 x 10 = 20


a. Define the programming cycle for Python.
Python‟s programming cycle is shorter than that of traditional programming cycle. In
Python, there are no compile or link steps. Python programming cycle is give below.

b. Describe the use of class ` init ()` method.


In object-oriented programming, particularly in languages like Python, the __init__()
method (often referred to as the "constructor") is a special method that is
automatically called when an instance of a class is created. The primary purpose of
the __init__() method is to initialize the attributes (or properties) of the object and
perform any necessary setup operations that need to be done when an object is
instantiated.
c. Explain features of any two Python IDEs.
 It has wide range of applications from Web development, scientific and
mathematical computing to desktop graphical user Interfaces.
 The syntax of the language is clean and length of the code is relatively short.
d. Discuss the purpose of the break and continue statement in loops.
loops are used to execute a block of code repeatedly based on a certain condition.
The break and continue statements are control flow tools that can be used within
loops to alter the normal flow of execution.
The break statement is used to immediately terminate the current loop and exit its
execution. This can be particularly useful when you want to exit a loop based on a
certain condition, even if the loop's condition hasn't been completely satisfied.
for i in range(1, 11):
if i == 5:
break
print(i)
Similarly, The continue statement is used to skip the current iteration of a loop and
move on to the next iteration.
e. Explain the mutable sequence in python
Mutable sequences in Python, like lists, enable modification of their elements post-
creation. Lists offer flexibility through adding, changing, and removing elements.
They're indexed, and elements can be altered using indexes. Lists also support
methods for appending and inserting elements, as well as removing them. Slicing
helps in extracting sublists.
numbers = [1, 2, 3, 4, 5] #creating list
numbers[2] = 10 $#updating list element
numbers.append(6) # Adding element using append
numbers.remove(4) # removing an element.
f. Explain the output of following function.
def printalpha (abc_list, num_list):
for char in abc_list:
for num in
num_list:
print(char, num)
return
printalpha (['a', 'b', 'c'], [1, 2, 3])

Output of the above code will be :


a1
a2
a3
b1
b2
b3
c1
c2
c3
The outer loop iterates over the characters 'a', 'b', and 'c' in the abc_list. For each
character, the inner loop iterates over the numbers 1, 2, and 3 in the num_list. The
print statement inside the inner loop prints the current character and the current
number, separated by a space. As a result of this nested iteration, all possible
combinations of characters from abc_list with numbers from num_list are printed,
generating a total of 9 lines of output.
g. Discuss the special methods le and ne .
The special methods __le__ and __ne__ are comparison methods in Python, often
referred to as "magic methods". These methods allow you to customize the behavior
of the comparison operators <= (less than or equal to) and != (not equal to) for
objects of your custom classes.
h. Discuss various file opening modes of python.
File opening modes in Python provide specific ways to interact with files. The 'read'
mode ('r') enables reading text from the start, while the 'write' mode ('w') creates a
new file or truncates an existing one for writing. The 'append' mode ( 'a') appends
text at the end of an existing file or creates it if absent. The 'exclusive creation' mode
('x') writes text to a new file, raising an error if the file already exists. Choosing the
right mode ensures proper handling of file operations based on their intended use.
e.g. with open('example.txt', 'r') as file:
content = file.read()
print(content)
i. Compare assert, try-except and raise statements.

Assert is used for debugging by checking conditions, raising AssertionError if


false. try-except handles exceptions, preventing crashes, using try for code and
except for handling. raise raises custom or built-in exceptions to signal specific
errors. assert The assert statement finds its application in debugging and
testing scenarios. The try-except statement is pivotal for handling
exceptions gracefully. The raise statement finds application in customizing
exception handling.

j. Write python function to perform linear search.

def linear_search(arr, target):


for i in range(len(arr)):
if arr[i] == target:
return i # Return the index of the target element
return -1 # Return -1 if the target element is not found

# Example usage
my_list = [4, 2, 7, 1, 9, 5]
search_value = 7

SECTION B

2. Attempt any three of the following: 10x3=30

a. Write Python code snippet to display n terms of Fibonacci series using


recursion.
def fibonacci_recursive(n):
if n <= 0:
return []
elif n == 1:
return [0]
elif n == 2:
return [0, 1]
else:
fib_series = fibonacci_recursive(n - 1)
fib_series.append(fib_series[-1] + fib_series[-2])
return fib_series
# Example usage
n_terms = 10
fibonacci_terms = fibonacci_recursive(n_terms)
print(f"Fibonacci series of {n_terms} terms:", fibonacci_terms)
b. Write and explain an algorithm through python code to generate prime
numbers.
Sieve of Eratosthenes Algo.: This algorithm is used to generate prime numbers. The
main steps of algorithm are given below.
1. Define a list of consecutive integers from 2 to given value of n: (2, 3, 4, …, n).
2. Start from first prime number 2 To find next prime
3. Move to p2 (Square of p)with increments of p thereafter and mark/strike or
delete every such element till n.
4. Find the first number greater than Previous p in the list that is not
marked/striked/deleted.This is next prime number. If there was no such number,
stop.
5. Repeat from step 3 for next prime numbers
The python code for the algorithm is given below.

c. Compare list and tuple data structure with suitable examples. Explain the
conceptof list comprehension.
Characteristic Lists Tuples
Mutable (can be modified after Immutable (cannot be
Mutability
creation) modified after creation)
Syntax Created using parentheses
Created using square brackets [ ] ( )
Dynamic Sizing Yes No
Elements can be added, modified, Elements cannot be
Modifications
removed changed after creation
Suitable for constant
Usage Suitable for dynamic collections
collections
Example fruits = ['apple', 'banana'] coordinates = (3, 4)
Example fruits.append('orange') Not applicable
Modification

List comprehension is a concise and powerful way to create lists in Python. It


provides a compact syntax for generating a new list by applying an expression to
each element in an existing iterable, such as a list, tuple, or range.
e.g. numbers = [1, 2, 3, 4, 5]
squared_numbers = [x**2 for x in numbers]

In this example, the list comprehension [x**2 for x in numbers] generates a


new list squared_numbers by squaring each element in the numbers list. The
result is [1, 4, 9, 16, 25]. Other example is

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


even_squared = [x**2 for x in numbers if x % 2 == 0]
Output will be : even_squared is [4, 16, 36, 64, 100]
d. Explain the python implementation of stack ADT.

Classes are the Python representation for “Abstract Data Types”. Considering Stack
as ADT. We need to understand what operations it needs to perform:
Push(): To insert the element in stack list
Pop(): To delete the element from stack list
Create(): To create a stack
Isempty: To check whether stack empty or not
Size(): to Know size of stack
such signature of various operation on ADT under consideration are said to be
interface to ADT.

The python implementation of Stack ADT is given below


class Stack:
def __init__(self):
self.items = []
def IsEmpty(self):
return self.items == []
def push(self,item):
self.items.append(item)
def pop(self):
return self.items.pop()
def top(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)!

The provided class Stack represents a basic implementation of a stack data structure
using Python. A stack is a linear data structure that follows the Last-In-First-Out
(LIFO) principle, where the last element added is the first one to be removed. The
class includes methods to interact with the stack:

__init__(self): The constructor initializes an empty stack by creating an empty list


items.

IsEmpty(self): This method checks if the stack is empty by comparing the list
items with an empty list. If the two lists are equal, it returns True; otherwise, it
returns False.

push(self, item): This method adds an item to the top of the stack by appending it
to the items list.

pop(self): This method removes and returns the top item from the stack using the
pop() method of the items list.

top(self): This method returns the top item of the stack (the last item in the items
list) without removing it. It uses indexing to access the last element.

size(self): This method returns the number of items in the stack using the built-in
len() function.
e. Describe python program to implement selection sort. Simulate your code
on thefollowing data
2,52,1,5,2,54,62,64.

Selection sort is a simple comparison-based sorting algorithm. The main idea is to


repeatedly find the smallest (or largest) element from the unsorted part of the array
and swap it with the first element of the unsorted part. This process continues until the
entire array is sorted.The python code for selection sort implementation is given
below.

def selection_sort(arr):
n = len(arr)
for i in range(n - 1):
min_index = i
for j in range(i + 1, n):
if arr[j] < arr[min_index]:
min_index = j
arr[i], arr[min_index] = arr[min_index], arr[i]

# Example data
data = [2, 52, 1, 5, 2, 54, 62, 64]

print("Original data:", data)


selection_sort(data)
print("Sorted data:", data)

Simulation on the Given Data [2, 52, 1, 5, 2, 54, 62, 64]:

 Original data: [2, 52, 1, 5, 2, 54, 62, 64]


 After the first iteration: [1, 52, 2, 5, 2, 54, 62, 64]
 After the second iteration: [1, 2, 52, 5, 2, 54, 62, 64]
 After the third iteration: [1, 2, 2, 5, 52, 54, 62, 64]
 After the fourth iteration: [1, 2, 2, 5, 52, 54, 62, 64]
 After the fifth iteration: [1, 2, 2, 5, 52, 54, 62, 64]
 After the sixth iteration: [1, 2, 2, 5, 52, 54, 62, 64]
 After the seventh iteration: [1, 2, 2, 5, 52, 54, 62, 64]
 Sorted data: [1, 2, 2, 5, 52, 54, 62, 64]

After sorting, the data becomes: [1, 2, 2, 5, 52, 54, 62, 64]. The selection sort algorithm
performs n - 1 comparisons in the first iteration, n - 2 in the second, and so on. It's not
the most efficient sorting algorithm for large datasets, but it's easy to understand and
implement.
SECTION C
3. Attempt any one part of the following: 10x1=10
a. Discuss various categories of operators in python. Find and explain
stepwisesolution of following expressions if a=3, b=5, c=10.

i) a &b<<2//5**2+c^b
ii) b>>a**2<<2 >> b**2^c**3
In Python, operators are special symbols or keywords that perform
operations on one or more operands. Operators are categorized into several
groups based on their functionality and purpose:
1. Arithmetic Operators: These operators perform arithmetic operations like
addition, subtraction, multiplication, division, etc.
2. Comparison Operators: Also known as relational operators, they are used to
compare values and return boolean results (True or False).
3. Logical Operators: These operators perform logical operations like AND,
OR, NOT on boolean values.
4. Bitwise Operators: They perform bit-level operations on integers.
5. Assignment Operators: These operators assign values to variables and can
perform an operation in conjunction with assignment.
6. Identity Operators: They are used to compare the memory locations of two
objects.
7. Membership Operators: These operators test if a value is a member of a
sequence, like a list, string, or tuple.
8. Unary Operators: These operators work on a single operand.
Now, let's break down and explain the stepwise solutions of the given
expressions for the provided values a=3, b=5, and c=10.
i) a &b<<2//5**2+c^b # first evaluate **
a &b<<2//25+c^b # evaluate //
a &b<<0+c^b #evaluate + operation 0+10 =10
a & 5120 ^b # evaluate <<
3 & 5120 ^5 # evaluate &
0^5 # evaluate ^
5 Ans.
ii) b>>a**2<<2 >> b**2^c**3 # first evaluate ** in right to left
b>>9<<2 >> 25^1000 # now evaluate << or >> in left to right order
5>>9<<2 >> 25^1000 # evaluate left most right shift
0<<2>>25^1000 # evaluate next shif operation
0>>25^1000 # evaluate next shift
0^1000 # finally evaluate xor to get ans.
1000 Ans.

b. Discuss why python is interpreted language. Explain history and features of


python while comparing python version 2 and 3.

Python is classified as an interpreted language because it is executed line by line,


and each line is translated into machine code or intermediate code and executed
immediately. There is no separate compilation step as seen in languages like C or
C++. Instead, the Python interpreter reads the source code, converts it into bytecode
(an intermediate representation), and then executes it directly. This provides
benefits like ease of development, platform independence, and dynamic typing.
Python was developed by Guido van Rossum in 1991 at the National Research
Institute for Mathematics and Computer Science in the Netherlands. Python is
derived from many other languages, including ABC, Modula-3, C, C++, Algol-68,
SmallTalk, and Unix shell combining features of all the languages.
Summary of comparison of Python 2 and python 3 is given below.

Python 2 Python 3

>>7 / 5 >>7/5
Results: 1 Results: 1.4
print “message” print (“Message”)

Xrange Range

Exception alias mentioned with , Alias mentioned with „as‟


except NameError, err: except NameError as err:
In order to suppress a newline while in Python 3, you have to use the end keyword argument.
printing, you had to use a trailing print(2, end =" ") print(4)
comma in Python 2. 24
print 2, print 4
24
In Python 2, both != and <> used to work in python 3, the alternative of != has been completely removed.
perfectly fine as inequality operators. Basically now there is only one way of doing it. By using the !=
operator.
raw_input(), input both supported, The Python 3, the raw input() has been removed. There is only the
difference was that, input() was able to input() method and it parses the user input as string for every
read and store any data type and store it data type.
as the same type. In order to store every
input as a string, you had to use
raw_input()

Features:

 Readability: Python's syntax emphasizes readability and uses indentation to indicate


code blocks, which makes code easier to understand.
 Dynamically Typed: Python is dynamically typed, meaning variable types are
determined at runtime, allowing for more flexibility but requiring careful handling.
 High-Level: Python's abstraction levels allow developers to focus on solving
problems rather than managing low-level system details.
 Interpreted: Python code is executed line by line by an interpreter, providing faster
development cycles and easier debugging.
 Large Standard Library: Python comes with a vast collection of modules and
libraries that simplify tasks and reduce code length.
 Cross-Platform: Python is available on various platforms (Windows, macOS,
Linux), ensuring code portability.
 Object-Oriented: Python supports object-oriented programming principles,
encouraging code organization through classes and objects
4. Attempt any one part of the following: 10x1=10
a. Write a python program to count the vowels present in given input string.
Explain the output of program through example.
def count_vowels(input_string):
vowels = "AEIOUaeiou"
vowel_count = 0
for char in input_string:
if char in vowels:
vowel_count += 1
return vowel_count
# Input string
input_str = input("Enter a string: ")
result = count_vowels(input_str)
print("Number of vowels:", result)
The function is designed to receive an input string as its parameter. Within the
program, a vowels string is established, encompassing both uppercase and
lowercase vowels. To keep track of vowel occurrences, the vowel count variable
is initialized. The operation entails iterating through each character of the input
string, achieved through a for loop. During each iteration, a verification is
performed to ascertain whether the character exists within the vowels string.
Upon identification of a vowel, the vowel_count undergoes incrementation.
Subsequent to the complete traversal of the input string, the function furnishes
the ultimate vowel count as its output.

b. Write a program that accepts sequence of lines as input and prints the
linesafter making all characters in the sentence capitalized.
e.g. If Input:
Hello world
Practice makes perfect
Then, Output:
HELLO WORLD
PRACTICE MAKES PERFECT

# Accept input lines


input_lines = []
while True:
line = input("Enter a line (or 'exit' to stop): ")
if line.lower() == 'exit':
break
input_lines.append(line)

# Capitalize and print the lines


for line in input_lines:
capitalized_line = line.upper()
print(capitalized_line)
5. Attempt any one part of the following: 10x1=10

a. Discuss list data structure of python. Explain various inbuilt methods of list
withsuitable example of each.

A list is a versatile and fundamental data structure in Python that allows you to
store a collection of items. Lists are ordered, mutable (modifiable), and can
contain elements of different data types, including other lists. Lists are defined
using square brackets [] and elements are separated by commas.
Example of creating a list:
fruits = ['apple', 'banana', 'orange', 'grape']
Various Inbuilt Methods of List with Examples:
append(item): Adds an element to the end of the list. E.g.
fruits = ['apple', 'banana', 'orange']
fruits.append('grape')
# fruits is now ['apple', 'banana', 'orange', 'grape']

insert(index, item): Inserts an element at a specific index in the list.


fruits = ['apple', 'banana', 'orange']
fruits.insert(1, 'grape')
# fruits is now ['apple', 'grape', 'banana', 'orange']

remove(item): Removes the first occurrence of a specified item from the


list.
fruits = ['apple', 'banana', 'orange', 'banana']
fruits.remove('banana')
# fruits is now ['apple', 'orange', 'banana']

pop(index): Removes and returns the element at a specific index. If no


index is provided, the last element is removed.
fruits = ['apple', 'banana', 'orange']
removed_item = fruits.pop(1)
# fruits is now ['apple', 'orange']
# removed_item is 'banana'

index(item): Returns the index of the first occurrence of the specified item.
fruits = ['apple', 'banana', 'orange']
index = fruits.index('banana')
# index is 1

count(item): Returns the number of times the specified item appears in the
list.
fruits = ['apple', 'banana', 'banana', 'orange']
count = fruits.count('banana')
# count is 2

sort(): Sorts the list in ascending order.


numbers = [5, 2, 8, 1, 3]
numbers.sort()
# numbers is now [1, 2, 3, 5, 8]

reverse(): Reverses the elements of the list in-place.


numbers = [1, 2, 3, 5, 8]
numbers.reverse()
# numbers is now [8, 5, 3, 2, 1]
copy(): Returns a shallow copy of the list.
fruits = ['apple', 'banana', 'orange']
fruits_copy = fruits.copy()
These are just a few of the many inbuilt methods available for lists in Python.
Lists are highly versatile and widely used in various programming scenarios
due to their flexibility and ease of use.

b. Compare list and dictionary data structure. Explain various dictionary


methodswith suitable examples of each.

Comparison between List and Dictionary Data Structures:

Aspect List Dictionary


Indexing Integer-based indices Key-based indices
Ordered Ordered Insertion order preserved (Python 3.7+)
Mutable Mutable Mutable
Homogeneous Typically
Key-value pairs
Elements heterogeneous
Memory
Lower Higher
Overhead
Use Case Sequence of elements Mapping of keys

Explanation of Various Dictionary Methods with Examples:

clear(): Removes all items from the dictionary.


student = {'name': 'Alice', 'age': 20}
student.clear()

get(key, default=None): Returns the value associated with the key. If the key is
not found, returns the default value.
student = {'name': 'Alice', 'age': 20}
age = student.get('age', 0)
grade = student.get('grade', 'N/A')

keys(): Returns a view of the keys in the dictionary.


student = {'name': 'Alice', 'age': 20}
key_view = student.keys()
# key_view is dict_keys(['name', 'age'])

values(): Returns a view of the values in the dictionary.


student = {'name': 'Alice', 'age': 20}
value_view = student.values()
# value_view is dict_values(['Alice', 20])

items(): Returns a view of the key-value pairs in the dictionary.


student = {'name': 'Alice', 'age': 20}
item_view = student.items()
# item_view is dict_items([('name', 'Alice'), ('age', 20)])
pop(key, default=None): Removes the key-value pair associated with the key
and returns the value. If the key is not found, returns the default value.
student = {'name': 'Alice', 'age': 20}
name = student.pop('name', 'Unknown')
# name is 'Alice', and 'name' key is removed from the dictionary
grade = student.pop('grade', 'N/A')
# grade is 'N/A'

popitem(): Removes and returns a random key-value pair as a tuple.


student = {'name': 'Alice', 'age': 20}
item = student.popitem()
# item is a tuple, e.g., ('age', 20), and a random key-value pair
is removed

update(dict): Updates the dictionary with key-value pairs from another


dictionary.
student = {'name': 'Alice', 'age': 20}
new_info = {'age': 21, 'grade': 'A'}
student.update(new_info)
# student is now {'name': 'Alice', 'age': 21, 'grade': 'A'}

6. Attempt any one part of the following: 10x1=10

a. Discuss the concept of Iterators in python. Explain, how we can create text
file in python? Describe python program to write the number of letters and
digits in given input string into a File object.

An iterator in Python is an object that represents a stream of data, allowing you to


iterate over each element without needing to load the entire dataset into memory.
Iterators provide a memory-efficient and lazy evaluation approach to working with
data sequences. The core idea is to provide an interface for iterating over a
sequence of elements one by one, fetching the next element when requested.

Iterators are used with objects that implement two methods: __iter__() and
__next__(). The __iter__() method returns the iterator object itself, and the
__next__() method returns the next value from the iterator.

You can create a text file in Python using the built-in open() function and
specifying the file mode as 'w' (write). This mode will create a new file or
overwrite an existing file with the same name.

Example of creating a text file:

python
file = open('example.txt', 'w')
file.write("Hello, this is a text file.")
file.close()

Python program that takes an input string and writes the count of letters and digits
into a text file:

def count_letters_digits(input_str):
letters = 0
digits = 0
for char in input_str:
if char.isalpha():
letters += 1
elif char.isdigit():
digits += 1
return letters, digits
input_str = input("Enter a string: ")
letters_count, digits_count = count_letters_digits(input_str)
with open('count.txt', 'w') as file:
file.write(f"Number of letters: {letters_count}\n")
file.write(f"Number of digits: {digits_count}\n")
print("Counts written to file 'count.txt'")

b. Illustrate through examples, how we can implement different type of


inheritance in python? Explain the static, instance and class method through
suitable example.
In Python, you can implement different types of inheritance: single inheritance,
multiple inheritance, hierarchical inheritance, and multilevel inheritance.

1. Single Inheritance: In single inheritance, a class inherits from only one base class.
python
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
dog = Dog()
print(dog.speak()) # Output: Woof!

2. Multiple Inheritance: In multiple inheritance, a class inherits from multiple base


classes.
python
class A:
def speak(self):
return "Class A"
class B:
def speak(self):
return "Class B"
class C(A, B):
pass
c = C()
print(c.speak()) # Output: Class A

3. Hierarchical Inheritance: In hierarchical inheritance, multiple classes inherit from


a single base class.
python
class Vehicle:
def drive(self):
pass
class Car(Vehicle):
def drive(self):
return "Driving a car"
class Bike(Vehicle):
def drive(self):
return "Riding a bike"
car = Car()
bike = Bike()
print(car.drive()) # Output: Driving a car
print(bike.drive()) # Output: Riding a bike

4. Multilevel Inheritance: In multilevel inheritance, a class inherits from a base


class, which in turn inherits from another base class.
python
class Animal:
def speak(self):
pass
class Mammal(Animal):
pass
class Dog(Mammal):
def speak(self):
return "Woof!"
dog = Dog()
print(dog.speak()) # Output: Woof!

Explanation of Static, Instance, and Class Methods:

1. Static Method: A static method belongs to a class rather than an instance. It can be
called using the class name and doesn't have access to instance-specific or class-
specific attributes.
python
class MathOperations:
@staticmethod
def add(x, y):
return x + y

result = MathOperations.add(3, 5)
print(result) # Output: 8

2. Instance Method: An instance method operates on an instance of a class and can


access instance attributes and methods.
python
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
rectangle = Rectangle(4, 5)
print(rectangle.area()) # Output: 20

3. Class Method: A class method operates on the class itself and can access class
attributes and methods.
python
class Circle:
pi = 3.14159
def __init__(self, radius):
self.radius = radius
@classmethod
def get_pi(cls):
return cls.pi
circle = Circle(3)
print(circle.get_pi()) # Output: 3.14159
7. Attempt any one part of the following: 10x1=10

a. Explain the Tower of Hanoi problem and its recursive solution in Python.

Tower of Hanoi Problem:

The Tower of Hanoi is a classic mathematical puzzle that involves moving a stack of discs
from one peg to another, with the help of an auxiliary peg, following certain rules:

1. Only one disc can be moved at a time.


2. Each move consists of taking the top disc from one of the stacks and placing it on
top of another stack.
3. No disc may be placed on top of a smaller disc.

The problem starts with all the discs on one peg (source peg) arranged in decreasing order
of size, and the goal is to move all the discs to another peg (destination peg) while using a
third peg (auxiliary peg) as temporary storage.

Recursive Solution in Python:

The Tower of Hanoi problem can be elegantly solved using a recursive algorithm. The key
insight is to break down the problem into smaller subproblems by moving a smaller subset
of discs. The steps can be summarized as follows:

1. Move n-1 discs from the source peg to the auxiliary peg, using the destination peg
as the auxiliary storage.
2. Move the remaining largest disc from the source peg to the destination peg.
3. Move the n-1 discs from the auxiliary peg to the destination peg, using the source
peg as the auxiliary storage.

Here's the Python code implementing the recursive solution:

def tower_of_hanoi(n, source, destination, auxiliary):


if n == 1:
print(f"Move disc 1 from {source} to {destination}")
return
tower_of_hanoi(n - 1, source, auxiliary, destination)
print(f"Move disc {n} from {source} to {destination}")
tower_of_hanoi(n - 1, auxiliary, destination, source)

# Example usage
n=3
tower_of_hanoi(n, 'A', 'C', 'B')
b. Write python program to implement merge sort algorithm. Discuss, how we
can compare the time complexity of two algorithms?
Merge Sort is a divide-and-conquer sorting algorithm that divides the unsorted list
into smaller sublists, sorts them, and then merges the sorted sublists to produce
the final sorted list.
def merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2
left_half = arr[:mid]
right_half = arr[mid:]

merge_sort(left_half)
merge_sort(right_half)

i=j=k=0

while i < len(left_half) and j < len(right_half):


if left_half[i] < right_half[j]:
arr[k] = left_half[i]
i += 1
else:
arr[k] = right_half[j]
j += 1
k += 1

while i < len(left_half):


arr[k] = left_half[i]
i += 1
k += 1

while j < len(right_half):


arr[k] = right_half[j]
j += 1
k += 1

# Example usage
arr = [38, 27, 43, 3, 9, 82, 10]
merge_sort(arr)
print("Sorted array:", arr)
timeit.timeit() function can be used to measure the execution time of the provided code snippets
(lambda functions) for each input size. The number=1 argument specifies that each code snippet
is executed only once that can be changed also. By comparing the execution times, you can
observe the relative performance of the Merge Sort and Bubble Sort algorithms as the input size
increases. E.g.
input_sizes = [100, 1000, 5000, 10000]
for size in input_sizes:
random_array = [random.randint(1, 1000) for _ in range(size)]

merge_sort_time = timeit.timeit(lambda:merge_sort(random_array.copy()),
number=1)
bubble_sort_time = timeit.timeit(lambda:bubble_sort(random_array.copy()),
number=1)
print(f"Input size: {size}")
print(f"Merge Sort Time: {merge_sort_time:.6f} seconds")
print(f"Bubble Sort Time: {bubble_sort_time:.6f} seconds")

You might also like