0% found this document useful (0 votes)
36 views54 pages

Pdf24 Merged

Uploaded by

Aaniya Jain
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)
36 views54 pages

Pdf24 Merged

Uploaded by

Aaniya Jain
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/ 54

Register No.

SRM Institute of Science and Technology


College of Engineering and Technology
SET - C
School of Computing
(Common to all branches)
Academic Year: 2023-24 (ODD)

Test: CLA-T2 Date: 2-11-2023


Course Code & Title: 21CSC203P Advanced Programming Practice Duration: 100 minutes
Year & Sem: II Year / III Sem Max. Marks: 50

Course Articulation Matrix: (to be placed)


S.No. Course PO1 PO2 PO3 PO4 PO5 PO6 PO7 PO8 PO9 PO10 PO11 PO12 PSO1 PSO2 PSO3
Outcome

1 CO1 3 2 - - - - - - - - - - - 2 -

2 CO2 3 2 - 1 - - - - - - - - - 2 -

3 CO3 3 - 2 - 2 - - - - 1 - - - 2 -

4 CO4 3 2 - 1 - - - - - - - - - 2 -

5 CO5 3 - 2 1 2 - - - - 1 - - - 2 -

Part – A - (5 x 4 = 20 Marks)
Answer any 5 Questions
1 What is the difference between process-based multitasking 4 L3 1 1 1.6.1
and thread-based multitasking? In which scenarios would y

Process-based multitasking and thread-based multitasking


are two approaches to achieving multitasking in computer
systems. They differ in how they manage and execute
multiple tasks concurrently. Here's an overview of the
differences between the two and when to choose one over
the other:

1. Process-Based Multitasking:

Processes: In process-based multitasking, each task or job is


a separate process, which means it has its own memory
space, program counter, and system resources. These
processes run independently of each other.

Isolation: Processes are isolated from each other, so if one


process crashes or encounters an issue, it generally does not
affect other processes.

Scalability: Creating new processes can be resource-


intensive because each process requires a separate memory
allocation and operating system overhead.

Scenarios for Process-Based Multitasking:


Isolation: When you need strong isolation between tasks, so
that if one task fails, it doesn't affect others. This is
important in critical systems like operating systems, web
servers, or mission-critical applications.

Parallelism on Multi-core CPUs: When you want to take


advantage of multi-core processors by running different
tasks in separate processes, utilizing the full capabilities of
the hardware.

2. Thread-Based Multitasking:

Threads: In thread-based multitasking, multiple threads


within the same process share the same memory space and
system resources. Threads are smaller units of execution
within a process.

Lightweight: Threads are generally more lightweight to


create and manage compared to processes. They can be
created and destroyed more quickly.

Communication: Threads within the same process can


communicate more easily since they share memory.

Scenarios for Thread-Based Multitasking:

Efficiency: When you need a more efficient way to achieve


multitasking, especially on single-core systems or in cases
where the overhead of creating separate processes is
prohibitive.

Shared Data: When tasks need to share data or collaborate


closely, using threads within the same process can simplify
communication and data sharing.

User Interface Applications: Many graphical user interface


(GUI) applications use threads for responsive user
interfaces, where one thread manages the UI, while other
threads handle background tasks.

The choice between process-based and thread-based


multitasking depends on your specific requirements and the
trade-offs you are willing to make. In some cases, a
combination of both may be used to take advantage of their
respective strengths. For example, a program may use
multiple threads for multitasking within a single process
and also launch multiple processes for specific tasks that
require strong isolation.

2 What programming languages and libraries are commonly 4 L3 2 2 2.6.4


used for concurrent programming, and what features do
they offer to facilitate concurrent development?
Concurrent programming is a crucial aspect of modern
software development, as it allows applications to
efficiently utilize multi-core processors and handle multiple
tasks concurrently. Various programming languages and
libraries provide features and tools to facilitate concurrent
development. Here are some commonly used programming
languages and libraries for concurrent programming and the
features they offer:

1. Java:

Java Threads: Java provides a built-in thread model using


the java.lang.Thread class. Developers can create and
manage threads to achieve concurrency.

Java Concurrency Utilities: The java.util.concurrent


package offers a range of high-level concurrency utilities,
such as thread pools, concurrent data structures, and
synchronization primitives like Locks and Semaphores.

2. C++:

C++ Threads: The C++11 standard introduced the <thread>


library, which provides a standard way to work with
threads. Developers can use the std::thread class to create
and manage threads.

C++ Standard Library Concurrency Features: C++ also


offers other concurrency features in the <mutex>,
<condition_variable>, and <future> headers for
synchronization and managing asynchronous operations.

3. Python:

Threading and Multiprocessing: Python has a built-in


threading module for thread-based concurrency and a
multiprocessing module for process-based concurrency.
These modules provide easy ways to create and manage
threads and processes.

Asyncio: Python's asyncio library enables asynchronous,


event-driven programming, allowing developers to write
non-blocking, concurrent code using coroutines and event
loops.

4. Go (Golang):

Goroutines: Go is known for its lightweight concurrency


model with goroutines. Goroutines are lightweight threads
managed by the Go runtime, making it easy to create and
manage thousands of concurrent tasks.

Channels: Go's built-in channels facilitate communication


and synchronization between goroutines, making it easy to
coordinate concurrent tasks.

5. Rust:

Ownership System: Rust's ownership system enforces


memory safety and concurrency safety without the need for
a garbage collector. It provides features like ownership,
borrowing, and lifetimes to prevent data races and ensure
thread safety.

Standard Library: The Rust standard library offers


concurrency primitives like std::thread, std::sync, and
std::mpsc (multi-producer, single-consumer channels) for
managing concurrency safely.

6. Erlang:

Actor Model: Erlang is built around the actor model, where


concurrent tasks are represented as independent actors.
Each actor communicates via message passing, providing
isolation and fault tolerance.

OTP (Open Telecom Platform): Erlang's OTP library


provides a framework for building robust, fault-tolerant,
and scalable concurrent systems.

7. .NET (C#):

Task Parallel Library (TPL): .NET offers TPL for


concurrent programming. Developers can use the Task class
to represent asynchronous and parallel operations.

Asynchronous Programming: .NET supports asynchronous


programming with the async and await keywords, allowing
developers to write non-blocking code.

These programming languages and libraries offer various


features to support concurrent programming, including
thread management, synchronization mechanisms, and
abstractions for parallelism. The choice of language and
library depends on your specific project requirements and
the level of control and safety you need when working with
concurrency.

3 What are the limitations or challenges of shared memory 4 L4 1 1 1.6.1


system?

Data Race Conditions: Shared memory systems are


susceptible to data race conditions when multiple threads or
processes access and modify shared data concurrently
without proper synchronization. Data races can lead to
unpredictable behavior, crashes, or corruption of data.

Synchronization Overhead: To avoid data races, shared


memory systems often require synchronization mechanisms
like locks, semaphores, or mutexes. Implementing and
managing these synchronization mechanisms can add
complexity to the code and introduce overhead, potentially
slowing down the system.

Deadlocks: Incorrectly managed locks and synchronization


can lead to deadlocks, where two or more processes or
threads are stuck, unable to make progress because they are
waiting for resources held by each other.

Resource Contention: As multiple processes or threads


compete for access to shared resources, resource contention
can occur, leading to reduced performance and throughput.

Complexity: Developing and debugging shared memory


systems can be more challenging than other forms of
concurrency due to the need for careful management of
shared data and synchronization primitives.

4 What is the role of the bind() function in socket 4 L4 2 1 1.7.1


configuration? How do you use it to specify a local address
and port for a TCP socket?

The bind() function is a critical step in socket programming,


particularly when working with TCP sockets. Its primary
role is to associate a specific local network address and port
with a socket, which means it specifies the endpoint on the
local system to which the socket should be bound. This is
necessary for both server and client sockets. The bind()
function is typically used with Internet Protocol (IP)
sockets, such as TCP or UDP.

Here's how you use the bind() function to specify a local


address and port for a TCP socket:

Create a Socket: Before you can use bind(), you need to


create a socket using the socket() function. In the case of a
TCP socket, you would typically use SOCK_STREAM as
the socket type.
Define a struct sockaddr_in: You should create a struct
sockaddr_in that holds the local address and port
information. This structure is used to specify the local
endpoint to which the socket will be bound.
5 What is the significance of the listen() function in TCP 4 L3 1 2 2.6.4
socket configuration, and what is the maximum number of
pending connections it can handle?

The listen() function is an important step in the


configuration of a TCP socket, specifically on the server
side of a network application. Its primary purpose is to
make a TCP socket passive, enabling it to accept incoming
client connections. The listen() function is typically used in
conjunction with the bind() function, which specifies the
local address and port to which the server socket should be
bound.
Server Setup: The listen() function is called after a socket is
created using the socket() function and bound to a specific
local address and port using the bind() function. The socket
is configured to listen for incoming client connections.

Queue for Incoming Connections: When a server socket is


in the listening state, it establishes a queue for incoming
connection requests. These connection requests are
typically placed in a queue known as the "backlog."
Backlog Size: The listen() function allows you to specify
the size of the backlog, which is essentially the maximum
number of pending connections that can be queued while
the server is processing existing connections. The actual
maximum number of pending connections a server can
handle depends on the operating system and its
configuration.
6 How do symbolic programming languages handle variables 4 L5 1 3 2.4.1
and bindings differently from languages in other paradigms,
such as procedural or object-oriented languages?

Symbolic programming languages, like Lisp, and other


paradigms, such as procedural or object-oriented languages,
handle variables and bindings differently due to the unique
characteristics and goals of symbolic programming. Here
are some key differences in how variables and bindings are
managed in symbolic programming languages compared to
other paradigms:

Procedural/Object-Oriented Languages: Many procedural


and object-oriented languages use static typing, where
variables have fixed types at compile time. This provides
type safety but may be less flexible in symbolic
manipulation.

7 Can events in a database system be monitored or logged? 4 L5 2 3 2.4.1

The listen() function is an important step in the


configuration of a TCP socket, specifically on the server
side of a network application. Its primary purpose is to
make a TCP socket passive, enabling it to accept incoming
client connections. The listen() function is typically used in
conjunction with the bind() function, which specifies the
local address and port to which the server socket should be
bound.

Server Setup: The listen() function is called after a socket is


created using the socket() function and bound to a specific
local address and port using the bind() function. The socket
is configured to listen for incoming client connections.

Queue for Incoming Connections: When a server socket is


in the listening state, it establishes a queue for incoming
connection requests. These connection requests are
typically placed in a queue known as the "backlog."

Backlog Size: The listen() function allows you to specify


the size of the backlog, which is essentially the maximum
number of pending connections that can be queued while
the server is processing existing connections. The actual
maximum number of pending connections a server can
handle depends on the operating system and its
configuration.

Part – B
(3x10=30 Marks)

8.a(i) Explain in detail about Concurrent Programming Paradigm. 4 L3 2 3 2.1.2

Concurrent programming is a programming paradigm that


focuses on writing software that can execute multiple tasks
concurrently. Concurrency allows for more efficient and
responsive software by taking advantage of modern multi-
core processors and distributed systems.

Concurrency is the ability of a system to handle multiple


tasks at the same time. Concurrency can be achieved
through techniques such as multi-threading, multi-
processing, or asynchronous programming.

Threads and Processes: Threads and processes are the basic


units of concurrent programming. A thread is a lightweight
unit of a process. Multiple threads can exist within a single
process and share the same memory space, making thread
communication and synchronization easier.

A process is an independent program with its own memory


space. Processes are typically used for more significant
isolation and can communicate via inter-process
communication (IPC) mechanisms.

Synchronization: To ensure that concurrent threads or


processes work correctly, synchronization mechanisms like
locks, semaphores, and mutexes are used. These
mechanisms prevent data races and ensure that shared
resources are accessed safely.

Shared Memory vs. Message Passing: In shared memory


systems, threads or processes communicate by sharing
memory. In message-passing systems, threads or processes
communicate by passing messages. This approach is more
isolated but can be less efficient due to message overhead.

Benefits of Concurrent Programming:

Improved Performance: Concurrent programs can take


advantage of multiple CPU cores and execute tasks in
parallel, leading to improved performance and
responsiveness.

Responsiveness: Concurrency can make software more


responsive, especially in user interfaces and networked
applications, by allowing tasks to run concurrently without
blocking the main thread or process.

Resource Utilization: Concurrent programming can


maximize resource utilization, making efficient use of CPU,
memory, and other system resources.

Scalability: Concurrent systems can scale to handle


increased workloads, making them suitable for multi-user
systems and server applications.

Challenges of Concurrent Programming:

Data Races: Data races occur when multiple threads or


processes access shared data concurrently without proper
synchronization, leading to unpredictable and erroneous
behavior.

Deadlocks: Deadlocks are situations where threads or


processes are stuck waiting for resources that won't be
released. They can bring the entire system to a standstill.

Synchronization Overhead: Synchronization mechanisms


add overhead to code execution, potentially reducing the
performance gains of concurrency.

Programming Languages for Concurrent Programming


include Java, C++, Python and Go. These languages offer
constructs for creating threads, managing synchronization,
and implementing concurrent algorithms.

a(ii) Write a java program that implements a multi-thread 6 L3 2 3 2.1.4


application that has three threads. First thread generates
random integer every 1 second and if the value is even,
second thread computes the square of the number and
prints. If the value is odd, the third thread will print the
value of cube of the number.

import java.util.Random;
public class MultithreadExample {
public static void main(String[] args) {
RandomNumberGenerator generator =
new RandomNumberGenerator();
SquareCalculator squareThread =
new SquareCalculator(generator);
CubePrinter cubeThread =
new CubePrinter(generator);

generator.start();
squareThread.start();
cubeThread.start();
}
}
class RandomNumberGenerator extends Thread {
private boolean running = true;

@Override
public void run() {
Random random = new Random();
while (running) {
int randomNumber = random.nextInt(100);
System.out.println("Generated: " +
randomNumber);

if (randomNumber % 2 == 0) {
SquareCalculator.newNumber(randomNumber);
} else {
CubePrinter.newNumber(randomNumber);
}
try {
Thread.sleep(1000); // Sleep for 1 second
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stopGenerating() {
running = false;
}
}

class SquareCalculator extends Thread {


private static int number;

public SquareCalculator(RandomNumberGenerator
generator){
generator.start();
}

public static void newNumber(int num) {


number = num;
}

@Override
public void run() {
while (true) {
if (number % 2 == 0) {
int square = number * number;
System.out.println("Square: " + square);
}
}
}
}

class CubePrinter extends Thread {


private static int number;

public CubePrinter(RandomNumberGenerator generator)


{
generator.start();
}
public static void newNumber(int num) {
number = num;
}

@Override
public void run() {
while (true) {
if (number % 2 != 0) {
int cube = number * number * number;
System.out.println("Cube: " + cube);
}
}
}
}
(OR)
8.b(i) Discuss the five steps for connecting JDBC. 4 L3 2 2 1.4.1
Connecting to a relational database using JDBC (Java
Database Connectivity) typically involves five steps. JDBC
is a Java-based API that allows Java applications to interact
with relational databases. Here are the five steps for
connecting to a database using JDBC:
Import Required Packages:
Import the necessary JDBC packages. The key package to
import is java.sql, which contains the core JDBC classes
and interfaces.
import java.sql.*;
Load and Register the JDBC Driver: JDBC drivers are
platform-specific implementations that allow Java to
communicate with the database. To use a specific database,
you need to load and register the appropriate JDBC driver.
This step is usually performed using the Class.forName()
method or driver-specific methods.
Class.forName("com.mysql.cj.jdbc.Driver");
Establish a Database Connection: Use the DriverManager
class to establish a connection to your database. You need
to provide the database URL, username, and password as
parameters to the getConnection() method.
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "your_username";
String password = "your_password";
Connection connection =DriverManager.getConnection(url,
username, password);
Execute SQL Queries and Process Results:
To interact with the database, you need to create a
Statement or PreparedStatement object. A Statement is used
for executing simple SQL queries, while a
PreparedStatement is used for parameterized queries and
offers better security against SQL injection.
PreparedStatement preparedstatement =
connection.prepareStatement("SELECT * FROM mytable
WHERE id = ?");
Use the execute(), executeQuery(), or executeUpdate()
methods of the Statement or PreparedStatement to execute
SQL queries against the database.
ResultSet resultSet = statement.executeQuery("SELECT *
FROM mytable");
// Process the result set
while (resultSet.next()) {
//Retrieve data using resultSet.getXXX() methods
int id = resultSet.getInt("id");
String name = resultSet.getString("name"); }
Close the Connection and Resources: After you're done
with the database operations, it's essential to close the
database connection and any associated resources, such as
Statement, PreparedStatement, and ResultSet objects, to
release resources and ensure proper clean-up.
resultSet.close();
statement.close();
connection.close();
These five steps outline the fundamental process for
connecting to a database using JDBC in Java.

b(ii) Create a java program for the following 6 L3 1 1 1.2.1

Use ThreadA to find number of digits present in the string k


and store into variable dc, finally print the value of
dc(output format: ThreadA:digitscount). Use ThreadB to
find number of alphabetic present in the string k and store
into variable cc, finally print the value of cc (output
format:ThreadB:digitscount).

public class CharacterCount {


private static String k = "Hello123World456"; // Replace
with your input string

public static void main(String[] args) {


ThreadA threadA = new ThreadA();
ThreadB threadB = new ThreadB();

threadA.start();
threadB.start();

try {
threadA.join();
threadB.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

int dc = threadA.getDigitCount();
int cc = threadB.getCharacterCount();

System.out.println("ThreadA:" + dc);
System.out.println("ThreadB:" + cc);
}
}

class ThreadA extends Thread {


private int digitCount = 0;

@Override
public void run() {
for (char c : CharacterCount.k.toCharArray()) {
if (Character.isDigit(c)) {
digitCount++;
}
}
}

public int getDigitCount() {


return digitCount;
}
}

class ThreadB extends Thread {


private int characterCount = 0;

@Override
public void run() {
for (char c : CharacterCount.k.toCharArray()) {
if (Character.isLetter(c)) {
characterCount++;
}
}
}

public int getCharacterCount() {


return characterCount;
}
}

9.a(i) Write a program to implement First Order Logic. 4 L4 1 2 2.1.1

from pyke import knowledge_engine


# Define a simple knowledge base with facts and rules.
facts = [ ("man", "John"),
("woman", "Mary"),
("parent", "John", "Tom"),
("parent", "Mary", "Tom"),
]
engine = knowledge_engine.engine(__file__)
with engine.prove_goal("man($x)") as gen:
for vars, plan in gen:
print(f"{vars['x']} is a man.")
with engine.prove_goal("parent($x, Tom)") as gen:
for vars, plan in gen:
print(f"{vars['x']} is a parent of Tom.")

a(ii) Write a python program to Check if a Number is Even or 6 L4 2 1 2.1.1


Odd and also check whether it is Prime or not.

def is_even_or_odd(number):
if number % 2 == 0:
return "Even"
else:
return "Odd"

def is_prime(number):
if number <= 1:
return False
if number <= 3:
return True
if number % 2 == 0 or number % 3 == 0:
return False
i=5
while i * i <= number:
if number % i == 0 or number % (i + 2) == 0:
return False
i += 6
return True

# Input a number from the user


num = int(input("Enter a number: "))

# Check if the number is even or odd


even_or_odd = is_even_or_odd(num)
print(f"{num} is {even_or_odd}.")

# Check if the number is prime or not


prime = is_prime(num)
if prime:
print(f"{num} is a prime number.")
else:
print(f"{num} is not a prime number.")

(OR)
9.b(i) Illustrate the prolog features with examples. 4 L4 3 1 1.2.1

Prolog is a powerful logic programming language used for


knowledge representation, rule-based reasoning, and
symbolic reasoning. It's designed to work with facts and
rules that express relationships and logical implications.
Here are some key Prolog features illustrated with
examples:

Facts and Rules: Prolog allows you to define facts and rules
using predicates. Facts are statements that are always true,
while rules define relationships and conditions. Here's an
example:

% Facts

likes(john, pizza).

likes(mary, pizza).

likes(mary, ice_cream).

% Rule

eats(john, X) :- likes(john, X).

In this example, we have facts about who likes what and a


rule that defines what John eats based on his likes.

Querying and Inference: Prolog allows you to query the


knowledge base to make inferences. For example:
?- likes(john, pizza).

true.

?- eats(john, ice_cream). false.

Prolog can determine that John likes pizza (based on the


facts) and that John doesn't eat ice cream (because it's not
defined in the facts or rules).

Variables: Prolog uses variables to represent unknown


values. You can use variables in queries and rules. For
example:

?- likes(X, pizza).

X = john ;

X = mary.

Prolog can find all individuals who like pizza by using the
variable X.

Negation: Prolog allows you to express negation through


the not or \+ operator. For example:

% Rule for dislikes

dislikes(Person, Food) :- \+ likes(Person, Food).

?- dislikes(john, ice_cream). true.

The dislikes rule is defined as the negation of the likes rule.

Lists: Prolog supports lists and provides predicates for list


manipulation. For example:

% Recursive rule to calculate the sum of a list of numbers

sum_list([], 0).

sum_list([Head | Tail], Sum) :- sum_list(Tail, RestSum),


Sum is Head + RestSum.

?- sum_list([1, 2, 3, 4], Sum).

Sum = 10.

Recursion: Prolog is well-suited for recursive definitions.


Here's an example of a recursive rule to find the factorial of
a number:

factorial(0, 1).

factorial(N, Result) :- N > 0, N1 is N - 1, factorial(N1,


PartialResult), Result is N * PartialResult.
You can calculate the factorial of a number using this rule.
Prolog is widely used in artificial intelligence, expert
systems, and natural language processing due to its
declarative and rule-based nature.

b(ii) Write a python program to calculate the area and perimeter 6 L4 3 2 2.1.3
of different geometric shapes (circle, rectangle, triangle,
etc.).

import math

# Function to calculate the area and perimeter of a circle


def circle_area_and_perimeter(radius):
area = math.pi * radius**2
perimeter = 2 * math.pi * radius
return area, perimeter

# Function to calculate the area and perimeter of a rectangle

def rectangle_area_and_perimeter(length, width):


area = length * width
perimeter = 2 * (length + width)
return area, perimeter

# Function to calculate the area and perimeter of a triangle


def triangle_area_and_perimeter(base, height, side1, side2,
side3):
area = 0.5 * base * height
perimeter = side1 + side2 + side3
return area, perimeter

# Example usage
shape = input("Enter the shape (circle, rectangle, triangle):
")

if shape == "circle":
radius = float(input("Enter the radius: "))
area, perimeter = circle_area_and_perimeter(radius)
elif shape == "rectangle":
length = float(input("Enter the length: "))
width = float(input("Enter the width: "))
area, perimeter = rectangle_area_and_perimeter(length,
width)
elif shape == "triangle":
base = float(input("Enter the base length: "))
height = float(input("Enter the height: "))
side1 = float(input("Enter the length of side 1: "))
side2 = float(input("Enter the length of side 2: "))
side3 = float(input("Enter the length of side 3: "))
area, perimeter = triangle_area_and_perimeter (base,
height, side1, side2, side3)
else:
print("Unsupported shape")
if shape in ["circle", "rectangle", "triangle"]:
print(f"Area: {area}")
print(f"Perimeter: {perimeter}")

10.a(i) How can you use third-party libraries with Tkinter to 4 L5 1 3 1.4.1
enhance its functionality? How do you install Tkinter?

Tkinter is a standard library for building graphical user


interfaces (GUIs) in Python. While Tkinter provides a basic
set of widgets and functionality for creating GUI
applications, you can enhance its functionality by
integrating third-party libraries. These libraries can add
features, custom widgets, and additional capabilities to your
Tkinter-based applications.

Here are the steps to use third-party libraries with Tkinter:

Install Tkinter:

Tkinter is included in Python's standard library, so you


typically do not need to install it separately. To ensure you
have Tkinter available, make sure you have Python installed
on your system.

Install Third-Party Libraries:

To enhance Tkinter's functionality, you can install third-


party libraries using package managers like pip. For
example:

pip install library_name

Import the Library: In your Python code, import the third-


party library that you've installed. For example:

import library_name

Use the Library's Features:

Utilize the features provided by the third-party library to


enhance your Tkinter application. This may involve
creating custom widgets, adding new functionality, or
modifying the appearance of your GUI.

Integrate with Tkinter:

Depending on the library, you may need to integrate its


features with your Tkinter application. This often involves
creating Tkinter widgets and binding events to handle
interactions with the library's components.

Customization and Styling:

Some third-party libraries allow you to customize the


appearance and style of your GUI components. You can use
these features to create a more appealing and user-friendly
interface.

Here are a few third-party libraries that are commonly used


in conjunction with Tkinter to enhance its functionality:

ttkthemes: This library provides additional themed Tkinter


widgets and allows you to customize the appearance of your
GUI components with various themes.

Pillow (PIL): The Python Imaging Library (PIL) or Pillow


allows you to work with images and perform image
processing within your Tkinter application.

Matplotlib: Matplotlib is a popular library for creating data


visualizations, including charts and plots. You can embed
Matplotlib figures within your Tkinter application.

ttkwidgets: This library offers additional themed Tkinter


widgets, enhancing the default set of widgets provided by
Tkinter.

Each library may have its own documentation and usage


instructions, so refer to the library's documentation for
specific details on how to use its features in your Tkinter
application.

a(ii) Construct a NFA and give the transmission table for the 6 L5 1 2 2.1.2
following regular expression for the given language = (a +
ba)*bb (a + ab)*.

To construct a Non-Deterministic Finite Automaton (NFA)


for the regular expression `(a + ba)*bb (a + ab)*`, we can
break down the expression into two parts: `(a + ba)*` and
`(a + ab)*`.

Each part can be implemented as a separate NFA, and then


we can combine them. Let's create NFAs for each part and
then combine them:

1. NFA for `(a + ba)*`:

- State q0: Initial state


- State q1: Accepting state for `(a + ba)*`
- Transitions:
- q0 on 'a' goes to q0 (loop for 'a')
- q0 on 'b' goes to q1 (transition for 'ba')
- q1 on 'a' goes to q0 (loop for 'a')
- q1 on 'b' goes to q1 (stay for 'ba')

2. NFA for `(a + ab)*`:

- State q2: Initial state


- State q3: Accepting state for `(a + ab)*`
- Transitions:
- q2 on 'a' goes to q3 (transition for 'a')
- q2 on 'b' goes to q2 (loop for 'b')
- q3 on 'a' goes to q3 (stay for 'ab')
- q3 on 'b' goes to q3 (stay for 'ab')

Now, we can combine these two NFAs into a single NFA:

3. Combined NFA for `(a + ba)*bb (a + ab)*`:

- State q0: Initial state


- State q1: Accepting state for `(a + ba)*`
- State q2: Initial state for `(a + ab)*`
- State q3: Accepting state for `(a + ab)*`
- Transitions:
- q0 on 'a' goes to q0 (loop for `(a + ba)*`)
- q0 on 'b' goes to q1 (transition for `(a + ba)*`)
- q1 on 'b' goes to q1 (stay for `(a + ba)*`)
- q1 on 'a' goes to q0 (loop for `(a + ba)*`)
- q2 on 'a' goes to q3 (transition for `(a + ab)*`)
- q2 on 'b' goes to q2 (loop for `(a + ab)*`)
- q3 on 'a' goes to q3 (stay for `(a + ab)*`)
- q3 on 'b' goes to q3 (stay for `(a + ab)*`)

Transmission Table for the Combined NFA:

| State | 'a' | 'b' |


|-------|------|------|
| q0 | q0 | q1 |
| q1 | q0 | q1 |
| q2 | q3 | q2 |
| q3 | q3 | q3 |

This NFA recognizes strings that match the regular


expression `(a + ba)*bb (a + ab)*`. It can be used to
determine if a given string belongs to the specified
language.

In python, we implement this as follows -

# Define the NFA transitions using a dictionary


nfa = {
0: {'a': {0}, 'b': {1}},
1: {'b': {1}},
2: {'a': {3}, 'b': {2}},
3: {'a': {3}},
}
# Define the set of accepting states
accepting_states = {1, 3}

# Function to simulate the NFA


def simulate_nfa(input_string):
current_states = {0}
for char in input_string:
next_states = set()
for state in current_states:
if char in nfa[state]:
next_states.update(nfa[state][char])
current_states = next_states
return any(state in current_states for state in
accepting_states)

# Test the NFA with some strings


test_strings = ["bb", "abb", "abab", "baa", "aabbaab"]
for string in test_strings:
if simulate_nfa(string):
print(f"'{string}' is in the language")
else:
print(f"'{string}' is not in the language")

(OR)
10.b(i) What functions are available for solving equations in 4 L5 3 2 1.2.1
SymPy?

SymPy is a Python library for symbolic mathematics, and it


provides a wide range of functions and tools for solving
equations symbolically.
Here are some of the key functions available for solving
equations in SymPy:

A. solve Function: The `solve` function is the primary tool


for solving equations in SymPy. It can solve equations and
systems of equations symbolically, including algebraic,
transcendental, and differential equations.

Example:
from sympy import symbols, Eq, solve
x, y = symbols('x y')
equation = Eq(x**2 + y, 5)
solutions = solve(equation, x)

B. solveset Function: The `solveset` function finds solutions


to equations, inequalities, and systems of equations. It
returns a `FiniteSet`, `Interval`, `Union`, or other set
representations of the solutions.

Example:
from sympy import symbols, Eq, solveset
x = symbols('x')
equation = Eq(x**2 - 4, 0)
solutions = solveset(equation, x, domain=S.Reals)

C. linsolve Function: The `linsolve` function is specifically


designed for solving systems of linear equations. It returns
solutions in the form of a tuple of expressions or as a set.

Example:
from sympy import symbols, linsolve
x, y = symbols('x y')
system = (2*x + 3*y - 5, 4*x - 6*y - 2)
solutions = linsolve(system, x, y)

D. dsolve Function: The `dsolve` function is used for


solving ordinary differential equations (ODEs). It can
handle a wide range of differential equations and return the
symbolic solutions.
Example:
python
from sympy import symbols, Eq, Function, dsolve
x = symbols('x')
f = Function('f')(x)
ode = Eq(f.diff(x) - 2*f, 0)
solution = dsolve(ode, f)

These are some of the fundamental functions in SymPy for


solving equations, inequalities, and differential equations.
SymPy's symbolic math capabilities make it a powerful tool
for algebraic manipulation and solving mathematical
problems.

b(ii) Develop a Python function that takes an NFA and returns e L5 3 2 2.1.4
the set of states that can be reached from a given state on a
specific input symbol.

We can implement a depth-first search (DFS) algorithm.


The DFS algorithm will explore the transitions of the NFA
to find all reachable states on the given input symbol.

Here's a Python function that accomplishes this:

def find_reachable_states(nfa, start_state, input_symbol):


def dfs(current_state):
# Initialize the set of reachable states with the current state.
reachable_states = {current_state}

# Get the transitions for the current state and input symbol.
transitions =
nfa.get(current_state, {}).get(input_symbol, set())

# Explore each transition recursively.


for next_state in transitions:
# Perform a depth-first search from the next state.
reachable_states.update(dfs(next_state))

return reachable_states

# Start the DFS from the given start state.


reachable_states = dfs(start_state)
return reachable_states

nfa = {
'q0': {'a': {'q0', 'q1'}, 'b': {'q0'}},
'q1': {'a': {'q1'}, 'b': {'q2'}},
'q2': {'a': {'q2'}, 'b': {'q2'}}
}

start_state = 'q0'
input_symbol = 'a'

reachable_states = find_reachable_states(nfa, start_state,


input_symbol)
print("Reachable states:", reachable_states)

In this example, the find_reachable_states function takes


the NFA represented as a dictionary, the start state, and the
input symbol. It uses a recursive DFS algorithm to find all
reachable states starting from the given state on the
specified input symbol. The reachable states are stored in a
set, and the function returns this set.

*Program Indicators are available separately for Computer Science and Engineering in AICTE
examination reforms policy.

Course Outcome (CO) and Bloom’s level (BL) Coverage in Questions

Approved by the Audit Professor/Course Coordinator


Register No.

SRM Institute of Science and Technology


College of Engineering and Technology
SET - A
School of Computing
(Common to all branches)
Academic Year: 2023-24 (ODD)

Test: CLA-T2 Date: 2-11-2023


Course Code & Title: 21CSC203P Advanced Programming Practice Duration: 100 minutes
Year & Sem: II Year / III Sem Max. Marks: 50

Course Articulation Matrix: (to be placed)


S.No. Course PO1 PO2 PO3 PO4 PO5 PO6 PO7 PO8 PO9 PO10 PO11 PO12 PSO1 PSO2 PSO3
Outcome

1 CO1 3 2 - - - - - - - - - - - 2 -

2 CO2 3 2 - 1 - - - - - - - - - 2 -

3 CO3 3 - 2 - 2 - - - - 1 - - - 2 -

4 CO4 3 2 - 1 - - - - - - - - - 2 -

5 CO5 3 - 2 1 2 - - - - 1 - - - 2 -

Part - A
(5 x4 = 20 Marks)
Instructions: Answer any 5 Questions
PI
Q. No Question Marks BL CO PO
Code

What are the advantages of multi-threading?


Ans:

1. Responsiveness

2. Resource Sharing,

3. Message Passing ,Shared Memory

1 4. Economy 4 L2 3 1 2.4.1
5. Scalability

6. Better Communication

7. Utilization of multiprocessor architecture

8. Minimized system resource usage

Note: Explain list of advantages


Compare AWT and Swing.
Ans:

AWT Swing

The AWT Component classes are The Swing component classes are
provided by the java.awt package. provided by the javax.swing
package.

The Components used in AWT The Components used in Swing


are mainly dependent on the are not dependent on the
operating system. operating system. It is completely
scripted in Java.

The AWT is heavyweight since it The Swing is mostly lightweight


uses the resources of the since it doesn't need any
operating system. Operating system object for
processing. The Swing
Components are built on the top
of AWT.

The Appearance of AWT The Swing Components are


2 Components is mainly not configurable and mainly support 4 L4 3 2 1.4.1
configurable. It generally depends pluggable look and feel.
on the operating system's look
and feels.

The Java AWT provides a smaller Java Swing provides a greater


number of components in number of components than
comparison to Swing. AWT, such as list, scroll panes,
tables, color choosers, etc.

Java AWT stands for Abstract Java Swing is mainly referred to


Window Toolkit. as Java Foundation Classes (JFC).

Java AWT has 21 peers. There is Java Swing has only one peer in
one peer for each control and one the form of OS's window object,
peer for the dialogue. Peers are which provides the drawing
provided by the operating system surface used to draw the Swing's
in the form of widgets widgets (label, button, entry
themselves. fields, etc.) developed directly by
Java Swing Package.

Java AWT many features that are Swing components provide the
completely developed by the higher-level inbuilt functions for
developer. It serves as a thin layer the developer that facilitates the
of development on the top of the coder to write less code.
OS.
Java AWT needs a higher amount Java Swing needs less memory
of memory for the execution. space as compared to Java AWT.

Java AWT is slower than swing Java Swing is faster than the
in terms of performance. AWT.

Write a python cocde to print the even numbers, odd


numbers from the list of given numbers using
Imperative approach [ 2,5,8,23,14,37,47,18,20,36,29]
Ans:

num = [ 2,5,8,23,14,37,47,18,20,36,29]

odd =[]

even =[]
3 for i in num: 4 L2 4 2 2.4.2

if i%2==0:

even.append(i)

else:

odd.append(i)

print(odd)

print(even)

Differentiate TCP and UDP.


Ans:

TCP UDP

It stands for Transmission Control It stands for User Datagram


Protocol. Protocol.
4 4 L2 4 2 2.2.1
It is a connection-oriented It is a connectionless protocol,
protocol, which means that the which means that it sends the
connection needs to be established data without checking whether
before the data is transmitted over the system is ready to receive or
the network. not.

TCP is a reliable protocol as it UDP is an unreliable protocol


provides assurance for the delivery as it does not take the guarantee
of data packets. for the delivery of packets.
TCP is slower than UDP as it UDP is faster than TCP as it
performs error checking, flow does not guarantee the delivery
control, and provides assurance for of data packets.
the delivery of

The size of TCP is 20 bytes. The size of the UDP is 8 bytes.

TCP uses the three-way-handshake UDP does not wait for any
concept. In this concept, if the acknowledgment; it just sends
sender receives the ACK, then the the data.
sender will send the data. TCP also
has the ability to resend the lost
data.

It follows the flow control This protocol follows no such


mechanism in which too many mechanism.
packets cannot be sent to the
receiver at the same time.

TCP performs error checking by It does not perform any error


using a checksum. When the data checking, and also does not
is corrected, then the data is resend the lost data packets.
retransmitted to the receiver.

This protocol is mainly used where This protocol is used where fast
a secure and reliable communication is required and
communication process is does not care about the
required, like military services, reliability like VoIP, game
web browsing, and e-mail. streaming, video and music
streaming, etc.

What is Socket? Explain in details.


Ans:

A socket is a software abstraction for an input or output medium of


communication. Sockets allow communication between processes
that lie on the same machine, or on different machines working in
diverse environment and even across different continents.

A socket is the most vital and fundamental entity. Sockets are the
end-point of a two-way communication link. An endpoint is a
5 4 L2 4 1 2.4.1
combination of IP address and the port number. For Client-Server
communication,

Sockets are to be configured at the two ends to initiate a


connection,

Listen for incoming messages Send the responses at both


ends .Establishing a bidirectional communication.

Datagram Socket

A datagram is an independent, self-contained piece of information


sent over a network whose arrival, arrival time, and content are not
guaranteed. A datagram socket uses User Datagram Protocol
(UDP) to facilitate the sending of datagrams (self-contained pieces
of information) in an unreliable manner. Unreliable means that
information sent via datagrams isn't guaranteed to make it to its
destination.

Stream Socket:

A stream socket, or connected socket, is a socket through which


data can be transmitted continuously. A stream socket is more akin
to a live network, in which the communication link is continuously
active. A stream socket is a "connected" socket through which data
is transferred continuously.

sock_obj = socket.socket( socket_family, socket_type, protocol=0)

socket_family: - Defines family of protocols used as transport


mechanism.

Either AF_UNIX, or

AF_INET (IP version 4 or IPv4).

socket_type: Defines the types of communication between the two


end-points.

SOCK_STREAM (for connection-oriented protocols, e.g., TCP),


or

SOCK_DGRAM (for connectionless protocols e.g. UDP).

protocol: We typically leave this field or set this field to zero.

Example:

#Socket client example in python

import socket

#create an AF_INET, STREAM socket (TCP)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print 'Socket Created'

What is Automata? Give examples.


Ans:

Automata theory is the study of abstract computational devices

Abstract devices are (simplified) models of real computations


6 4 L1 5 1 2.1.2
Computations happen everywhere: On your laptop, on your cell
phone, in nature, … finite automata-
Devices with a finite amount of memory.
Used to model “small” computers. push-downautomata
Devices with infinite memory that can be accessed in a restricted w
ay. Used to model parsers, etc.
Turing Machines-Devices with infinite memory.

Used to model any computer.

A common way to talk about words, number, pairs of words, etc. is


by representing them as strings. To define strings, we start with an
alphabet

An alphabet is a finite set of symbols.

Σ1 = {a, b, c, d, …, z}: the set of letters in English

Σ2 = {0, 1, …, 9}: the set of (base 10) digits

Σ3 = {a, b, …, z, #}: the set of letters plus the special symbol #

Σ4 = {(, )}: the set of open and closed brackets

A string over alphabet Σ is a finite sequence of symbols in Σ.

The empty string will be denoted by ∈

abfbz is a string over Σ1 = {a, b, c, d, …, z}

9021 is a string over Σ2 = {0, 1, …, 9}

ab#bc is a string over Σ3 = {a, b, …, z, #}

))()(() is a string over Σ4 = {(, )}

Languages can be used to describe problems with “yes/no”


answers, for example:

L1 = The set of all strings over Σ1 that contain the substring


“SRM”

L2 = The set of all strings over Σ2 that are divisible by 7 = {7,


14, 21, …}

L3 = The set of all strings of the form s#s where s is any string
over {a, b, …, z}

L4 = The set of all strings over Σ4 where every ( can be


matched with a subsequent )

Find the out the geometry managers for the following


options and give its syntax:
a. I have a set of radio widgets and want place it next to
each other along horizontal axis.
7 b. I have a button widget which I want to place it on 4 L2 5 2 2.4.1
specify coordinates denoting the screen.
Ans:

Grid
rb1= tk. Radiobutton(root, text="Option 2", variable=var,
value=1)
rb1.grid(row=0,column =0) rb1.grid(row=0,column=1)
b1= tk.Button(root, text=”Submit”, Command= root.destroy)
b1.place(x=50,y=50)

Part - B
(3 x10 = 30 Marks)
Instructions: Answer all the Questions

(i) What is the difference between the paint() and


repaint() methods in a Java Applet?
1.4.1
Ans:

paint(): This method holds instructions to paint this


component. In Java Swing, we can change the
paintComponent() method instead of paint() method as paint 2.4.1
calls paintBorder(), paintComponent() and paintChildren() m
ethods. We cannot call this method directly instead we can
call repaint().
repaint(): This method cannot be overridden. It controls
the update() -> paint() cycle. We can call this method to get
a component to repaint itself. If we have done anything to
change the look of the component but not the size then we
can call this method.
(ii) Write a java program that implements a multi-thread 4 L1 3 2
application that has three threads. First thread generates
8 (a)
random integer every 1 second and if the value is even,
second thread computes the square of the number and
prints. If the value is odd, the third thread will print the
value of cube of the number. 6 L2 3 2

Ans:

import java.util.Random;
class Square extends Thread {
int x;
Square(int n) {
x = n;
}
public void run() {
int sqr = x * x;
System.out.println("Square of " + x + " = " + sqr);
}
}
class Cube extends Thread {
int x;
Cube(int n) {
x = n;
}
public void run() {
int cub = x * x * x;
System.out.println("Cube of " + x + " = " + cub);
}
}
class Rnumber extends Thread {
public void run() {
Random random = new Random();
for (int i = 0; i < 5; i++) {
int randomInteger = random.nextInt(10);
System.out.println("Random Integer generated : " +
randomInteger);
Square s = new Square(randomInteger);
s.start();
Cube c = new Cube(randomInteger);
c.start();
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
System.out.println(ex);
}
}
}
}
public class ThreadP {
public static void main(String[] args) {
Rnumber n = new Rnumber();
n.start();
}
}
OUTPUT:
Random Integer generated : 9
Square of 9 = 81
Cube of 9 = 729
Random Integer generated : 8
Square of 8 = 64
Cube of 8 = 512
Random Integer generated : 1
Square of 1 = 1
Cube of 1 = 1
Random Integer generated : 3
Square of 3 = 9
Cube of 3 = 27
Random Integer generated : 8
Square of 8 = 64
Cube of 8 = 512
(OR)

(i) Discuss the five steps for connecting JDBC. 1.4.1


Ans:

JDBC stands for Java Database Connectivity. JDBC is a Java API 4 L1 3 2


to connect and execute the query with the database. It is a part of
JavaSE (Java Standard Edition). JDBC API uses JDBC drivers to 2.4.2
8 (b)
connect with the database.

JDBC API to access tabular data stored in any relational database.


6 L3 3 2
By the help of JDBC API, we can save, update, delete and fetch
data from the database.

There are 6 basic steps to connect with JDBC.


Note: Explain 6 steps in details
(ii) Create two objects threadobj1 and threadobj2 for the
class UserThreadPriority. Set the name of threadobj1 as
“ThreadA” and threadobj2 as “ThreadB”. Get a String
and a Character from the user and assign into
UserThreadPriority class variable k and c respectively.
Call the start() method for the thread objects threadobj1
and threadobj2.
Ans:

import java.util.Scanner;
public class UserThreadPriority {
private String k;
private char c;
private Thread thread;
public UserThreadPriority(String k, char c) {
this.k = k;
this.c = c;
this.thread = new Thread(this);
}
public void run() {
System.out.println(&quot;Thread name: &quot; +
thread.getName());
System.out.println(&quot;String: &quot; + k);
System.out.println(&quot;Character: &quot; + c);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println(&quot;Enter a string: &quot;);
String k = scanner.nextLine();
System.out.println(&quot;Enter a character: &quot;);
char c = scanner.next().charAt(0);
// Create two objects of UserThreadPriority
UserThreadPriority threadobj1 = new UserThreadPriority(k,
c);
UserThreadPriority threadobj2 = new UserThreadPriority(k,
c);
// Set the name of threadobj1
threadobj1.thread.setName(&quot;ThreadA&quot;);
// Set the name of threadobj2
threadobj2.thread.setName(&quot;ThreadB&quot;);
// Start the two threads
threadobj1.thread.start();
threadobj2.thread.start();
}
}

(i) Explain Parallel Programming and illustrate


parallelism using a multithreaded application in python.
1.4.1
Ans:

Multitasking, in general, is the capability of performing


multiple tasks simultaneously. Multithreading refers to
concurrently executing multiple threads by rapidly 2.4.1
switching the control of the CPU between threads (called
context switching). 4 L2 4 2
9 (a) Python Global Interpreter Lock limits one thread to run at a
OR time even if the machine contains multiple processors.
There are two types of multitasking in an OS: 6 L3 4 2
Process-based
Thread-based
import threading
from threading import *
def calculate_square(num):
print("Calculate the square of a given number")
for n in num:
print(f'The Square of {n} is:', n*n)
def calculate_cube(num):
print("Calculate the cube of a given number")
for n in num:
print(f'The Cube of {n} is:', n*n*n)
lst = [2, 4, 6, 8, 10]
thread1 = threading.Thread(target=calculate_square,
args=(lst, ))
thread2 = threading.Thread(target=calculate_cube,
args=(lst, ))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
(ii) Create a TCP server that echoes back any message it
receives from a client. Develop a Python client to send
messages to the server and display the echoed response.
Ans:
TCP SERVER:
import socket
# Define the server address and port
server_address = ('localhost', 12345)
# Create a socket and bind it to the server address
server_socket = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
server_socket.bind(server_address)
# Listen for incoming connecXons
server_socket.listen(1) print("TCP
server is running...")
while True:
# Accept a connecXon
client_socket, client_address = server_socket.accept()
print(f"ConnecXon established with {client_address}")
try:
while True:
# Receive data from the client
data = client_socket.recv(1024)
if not data: break
# Echo the data back to the client
client_socket.sendall(data) except
ExcepXon as e: print(f"Error: {e}")
finally:
# Close the client socket
client_socket.close()
TCP CLIENT: import socket
# Define the server address and port
server_address = ('localhost', 12345)
# Create a socket
client_socket = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
try:
# Connect to the server
client_socket.connect(server_address)
while True:
message = input("Enter a message (or 'exit' to quit): ")
if message == 'exit': break
# Send the message to the server
client_socket.sendall(message.encode())
# Receive and display the echoed response
response = client_socket.recv(1024)
print(f"Server echoed: {response.decode()}")
except ExcepXon as e: print(f"Error: {e}")
finally:
# Close the socket
client_socket.close()

(OR)

(i) Illustrate in detail about functional programming


paradigm with examples.
1.4.1
Ans:

Functional programming is a programming paradigm in


which it is tried to bind each and everything in pure 2.4.2
mathematical functions. It is a declarative type of
programming style that focuses on what to solve rather than
how to solve.
Functional programming paradigm is based on lambda
calculus.
Instead of statements, functional programming makes use of
expressions. Unlike a statement, which is executed to assign
variables, evaluation of an expression produces a value.
Functional programming is a declarative paradigm because it 4 L2 4 2
relies on expressions and declarations rather than statements.
Unlike procedures that depend on a local or global state,
9 (b) value outputs in FP depend only on the arguments passed to
the function.
6 L3 4 2
Functional programming consists only of PURE functions.
Concepts:
Pure functions
Recursion
Referential transparency
Functions are First-Class and can be Higher-Order
Immutability
Note : Explain all the concepts.
(ii) Design a expense tracker that is used to keep track of the
user’s expenses. It has to give correct information to the
users on their expenses and help them spend better using
PySimpleGUI and PyData libraries.
Install the PySimpleGUI package
Create basic user interface elements with PySimpleGUI
Create applications, such as a PySimpleGUI image viewer
Integrate PySimpleGUI with Matplotlib
Use computer vision in PySimpleGUI
Package your PySimpleGUI application for Windows

 .Tkinter – To create the GUI.


 messagebox – To display a box containing information,
warning, or error or asking a question.
 Ttk.Treeview – To display a table in the GUI window.
 Tkcalender.DateEntry – To enter a date.
 SQLite – To connect the Python script to the SQL
database.
Only the Tkinter library comes pre-installed with Python, so
you need to run the following command in your terminal to
install them:
python -m pip install tkcalender sqlite
1. Importing the necessary modules and libraries
2. Connecting to the database and creating the GUI window
3. Creating the database and data manipulation functions
Importing the necessary modules and libraries:
import datetime
import sqlite3
from tkcalendar import DateEntry
from tkinter import *
import tkinter.messagebox as mb
import tkinter.ttk as ttk
Note: Follow the steps and write the any example.
(i) What is Symbolic Programming Paradigms? Explain. 2.4.1
4 L1 5 1
10(a) Ans:

Symbolic programming is a programming paradigm in 2.4.8


which the program can manipulate its own formulas and 6 L2 5 2
program components as if they were plain data.Through
symbolic programming, complex processes can be
developed that build other more intricate processes by
combining smaller units of logic or functionality.
Symbolic programs can effectively modify themselves and
appear to learn, which makes them better suited for
applications such as artificial intelligence expert
systems natural language processing and computer games.
Languages that support symbolic programming include
the Language LISP and Prolog
Sympy-Symbolic Mathematics in Python
SymPy is a Python library used to represent the symbolic
mathematics
SymPy is written entirely in Python and does not require any
external libraries.
To Install the sympy use command : pip install sympy
Sympy support to perform the mathematical operations such
as
Algebraic manipulations
Differentiation
Integration
Equation solving & Linear algebra
Mathematical Operations Using Sympy:
To Find the rational no :
The Rational class represents a rational number as a pair of
two Integers: the numerator and the denominator.
Rational(5, 2) represents 5/2.
Mathematical Operations Using Sympy:
Some special constant e,pi,oo (Infinity) considered as
symbol and evaluate the values. evalf evaluates the
expression to a floating-point number.
Calculus
limit() -method
Note: Explain in details above topics with example.
(ii) Construct a NFA and give the transmission table for
the following regular expression for the given language =
(a + ba)*bb (a + ab)*.
Ans:

To construct a Non-Deterministic Finite Automaton (NFA)


for the regular expression `(a + ba)*bb (a + ab)*`, we can
break down the expression into two parts: `(a + ba)*` and `(a
+ ab)*`.

Each part can be implemented as a separate NFA, and then


we can combine them. Let's create NFAs for each part and
then combine them:

1. NFA for `(a + ba)*`:

- State q0: Initial state


- State q1: Accepting state for `(a + ba)*`
- Transitions:
- q0 on 'a' goes to q0 (loop for 'a')
- q0 on 'b' goes to q1 (transition for 'ba')
- q1 on 'a' goes to q0 (loop for 'a')
- q1 on 'b' goes to q1 (stay for 'ba')

2. NFA for `(a + ab)*`:

- State q2: Initial state


- State q3: Accepting state for `(a + ab)*`
- Transitions:
- q2 on 'a' goes to q3 (transition for 'a')
- q2 on 'b' goes to q2 (loop for 'b')
- q3 on 'a' goes to q3 (stay for 'ab')
- q3 on 'b' goes to q3 (stay for 'ab')

Now, we can combine these two NFAs into a single NFA:

3. Combined NFA for `(a + ba)*bb (a + ab)*`:

- State q0: Initial state


- State q1: Accepting state for `(a + ba)*`
- State q2: Initial state for `(a + ab)*`
- State q3: Accepting state for `(a + ab)*`
- Transitions:
- q0 on 'a' goes to q0 (loop for `(a + ba)*`)
- q0 on 'b' goes to q1 (transition for `(a + ba)*`)
- q1 on 'b' goes to q1 (stay for `(a + ba)*`)
- q1 on 'a' goes to q0 (loop for `(a + ba)*`)
- q2 on 'a' goes to q3 (transition for `(a + ab)*`)
- q2 on 'b' goes to q2 (loop for `(a + ab)*`)
- q3 on 'a' goes to q3 (stay for `(a + ab)*`)
- q3 on 'b' goes to q3 (stay for `(a + ab)*`)

Transmission Table for the Combined NFA:


| State | 'a' | 'b' |
|-------|------|------|
| q0 | q0 | q1 |
| q1 | q0 | q1 |
| q2 | q3 | q2 |
| q3 | q3 | q3 |

This NFA recognizes strings that match the regular


expression `(a + ba)*bb (a + ab)*`. It can be used to
determine if a given string belongs to the specified language.

In python, we implement this as follows -

# Define the NFA transitions using a dictionary


nfa = {
0: {'a': {0}, 'b': {1}},
1: {'b': {1}},
2: {'a': {3}, 'b': {2}},
3: {'a': {3}},
}
# Define the set of accepting states
accepting_states = {1, 3}

# Function to simulate the NFA


def simulate_nfa(input_string):
current_states = {0}
for char in input_string:
next_states = set()
for state in current_states:
if char in nfa[state]:
next_states.update(nfa[state][char])
current_states = next_states

return any(state in current_states for state in


accepting_states)

# Test the NFA with some strings


test_strings = ["bb", "abb", "abab", "baa", "aabbaab"]
for string in test_strings:
if simulate_nfa(string):
print(f"'{string}' is in the language")
else:
print(f"'{string}' is not in the language")
(OR)

(i) What functions are available for solving equations in 4 L1 5 1 1.4.1


SymPy.
10(b)
Ans:

SymPy is a Python library for symbolic mathematics, and it


provides a wide range of functions and tools for solving 6 L3 5 3 2.1.2
equations symbolically.
Here are some of the key functions available for solving
equations in SymPy:

A. solve Function: The `solve` function is the primary tool


for solving equations in SymPy. It can solve equations and
systems of equations symbolically, including algebraic,
transcendental, and differential equations.

Example:
from sympy import symbols, Eq, solve
x, y = symbols('x y')
equation = Eq(x**2 + y, 5)
solutions = solve(equation, x)

(ii) Create the calendar using Tkinter by showing data


month and year with scroll down menu to fix the particular
data month and year and press the click button to show the
message of clicked date, month and year.
Ans:

rom tkinter import *

import calendar

from datetime import date

def printCalendar():

month = int(month_box.get())

year = int(year_box.get())

output_calendar = calendar.month(year, month)

calendar_field.delete(1.0, 'end')

calendar_field.insert('end', output_calendar)

def reset():

calendar_field.delete(1.0, 'end')

month_var.set(current_month)

year_var.set(current_year)

month_box.config(textvariable=month_var)

year_box.config(textvariable=year_var)

def close():

guiWindow.destroy()

header_frame = Frame(guiWindow)
entry_frame = Frame(guiWindow)

result_frame = Frame(guiWindow)

button_frame = Frame(guiWindow)

header_frame.pack(expand=True, fill="both")

entry_frame.pack(expand=True, fill="both")

result_frame.pack(expand=True, fill="both")

button_frame.pack(expand=True, fill="both")

header_label = Label(header_frame, text="CALENDAR")

header_label.pack(expand=True, fill="both")

month_label = Label(entry_frame, text="Month:")

year_label = Label(entry_frame, text="Year:",

font=("arial", "20", "bold"), fg="#000000")

month_label.place(x=30, y=0)

year_label.place(x=275, y=0)

month_var = IntVar(entry_frame)

year_var = IntVar(entry_frame)

current_month = date.today().month

current_year = date.today().year

month_var.set(current_month)

year_var.set(current_year)

month_box = Spinbox(entry_frame, from_=1, to=12, width="10",

textvariable=month_var, font=('arial','15'))

year_box = Spinbox(entry_frame, from_=0000, to=3000,


width="10",

textvariable=year_var,font=('arial','15'))

month_box.place(x=130, y=5)

year_box.place(x=360, y=5)

if __name__ == "__main__":

guiWindow = Tk()

guiWindow.title("GUI Calendar")

guiWindow.geometry('500x550')

guiWindow.resizable(0, 0)
*Program Indicators are available separately for Computer Science and Engineering in AICTE examination
reforms policy.

Course Outcome (CO) and Bloom’s level (BL) Coverage in Questions

Approved by the Audit Professor/Course Coordinator


Part A

1. Life Cycle of a Thred

1. NEW – a newly created thread that has not yet started the execution
2. RUNNABLE – either running or ready for execution but it’s waiting for resource
allocation

3. BLOCKED – waiting to acquire a monitor lock to enter or re-enter a synchronized


block/method

4. WAITING – waiting for some other thread to perform a particular action without any time
limit

5. TIMED_WAITING – waiting for some other thread to perform a specific action for a
specified period

6. TERMINATED – has completed its execution

2. a.

from sympy import *


from sympy.solvers.solveset import linsolve
x, y = symbols('x, y')
print(linsolve([x + 5 *y - 2, -3*x +6*y], (x, y)))

output

{(4/7, 2/7)}

b.Create two 3*3 matrices and perform matrix multiplication and addition.

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

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

result = [[0,0,0],
[0,0,0],
[0,0,0]]

# iterate through rows


for i in range(len(X)):
# iterate through columns
for j in range(len(X[0])):
result[i][j] = X[i][j] + Y[i][j]

for r in result:
print(r)

mul = [[sum(a * b for a, b in zip(A_row, B_col))


for B_col in zip(*B)]
for A_row in A]
for x in result:
print(r)

3. Code

def change_cases(s):
return str(s).upper(), str(s).lower()
chrars = {'a', 'b', 'E', 'f', 'a', 'i', 'o', 'U', 'a'}
print("Original Characters:\n",chrars)
result = map(change_cases, chrars)
print("\nAfter converting above characters in upper and lower cases\nand eliminating duplicate
letters:")
print(set(result))

Output:

4.

from sympy import *


from sympy.solvers.solveset import linsolve
x, y = symbols('x, y')
print(linsolve([x * 4 - 1, x], (x)))
print(linsolve([x+x * y/x], (x,y)))

5.

6.

7. Output:

def average_tuple(nums):
result = tuple(map(lambda x: sum(x) / float(len(x)), zip(*nums)))
return result
nums = ((10, 10, 10), (30, 45, 56), (81, 80, 39), (1, 2, 3))
print ("Original Tuple: ")
print(nums)
print("\nAverage value of the numbers of the said tuple of tuples:\n",average_tuple(nums))
nums = ((1, 1, -5), (30, -15, 56), (81, -60, -39), (-10, 2, 3))
print ("\nOriginal Tuple: ")
print(nums)
print("\nAverage value of the numbers of the said tuple of tuples:\n",average_tuple(nums))

Output:

Part B

8. a(i).

The Model-View-Controller (MVC) software design pattern is a method for separating


concerns within a software application. As the name implies, the MVC pattern has three
layers:

• The Model defines the business layer of the application,


• the Controller manages the flow of the application,

• the View defines the presentation layer of the application.

Model: Handles data and business logic. Represents the business layer of the application

View: Presents the data to the user whenever asked for. Defines the presentation of the application

Controller: Entertains user requests and fetch necessary resources. Manages the flow of the
application

Model
public class Student {
private String rollNo;
private String name;
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View

public class StudentView {


public void printStudentDetails(String studentName, String studentRollNo){
System.out.println("Student: ");
System.out.println("Name: " + studentName);
System.out.println("Roll No: " + studentRollNo);
}
}

Controller
Main program

8a ii

.
8 b ii. characteristics of functional programming

• First-class functions – accept another function as an argument or return a function


• Pure functions - they are functions without side effects

• Recursion - allows writing smaller algorithms and operating by looking only at the inputs to a
function

• Immutable variables - variables that cannot be changed

• Non-strict evaluation - allows having variables that have not yet been computed

• Statements - evaluable pieces of code that have a return value

Pattern matching - allows better type-checking and extracting elements from an object

9.a.i.

9.a.ii

1. Message Passing - the user makes calls to libraries to explicitly share information between
processors.
2. Data Parallel - data partitioning determines parallelism

3. Shared Memory - multiple processes sharing common memory space

4. Remote Memory Operation - set of processes in which a process can access the memory of
another process without its participation

5. Threads - a single process having multiple (concurrent) execution paths

6. Combined Models - composed of two or more of the above.

9.b.i

class Time:
def __init__(self, hours=0, minutes=0):
self.hours = hours
self.minutes = minutes

def addTime(self, other):


new_hours = self.hours + other.hours
new_minutes = self.minutes + other.minutes

if new_minutes >= 60:


new_hours += 1
new_minutes -= 60

return Time(new_hours, new_minutes)

def displayTime(self):
print(f"{self.hours}:{self.minutes}")

def displayMinutes(self):
print(f"{self.hours * 60 + self.minutes} minutes")

if __name__ == "__main__":
time1 = Time(2, 50)
time2 = Time(1, 20)

print("time1")
time1.displayTime()
print("time2")
time2.displayTime()

add = Time.addTime(time1, time2)


print("time1 + time2")
add.displayTime()
print("Total minutes:")
add.displayMinutes()

9.b.ii

Concurrent programming is programming with multiple tasks. The major issues of concurrent
programming are:

• Sharing computational resources between the tasks;


• Interaction of the tasks.

Objects shared by multiple tasks have to be safe for concurrent access. Such objects are called
protected. Tasks accessing such an object interact with each other indirectly through the object.

An access to the protected object can be:

• Lock-free, when the task accessing the object is not blocked for a considerable time;
• Blocking, otherwise.

Blocking objects can be used for task synchronization. To the examples of such objects belong:

• Events;
• Mutexes and semaphores;

• Waitable timers;

• Queues

10. a.i Server Program:

import socket
def server_program():
# get the hostname
host = socket.gethostname()
port = 5000 # initiate port no above 1024

server_socket = socket.socket() # get instance


# look closely. The bind() function takes tuple as argument
server_socket.bind((host, port)) # bind host address and port
together

# configure how many client the server can listen simultaneously


server_socket.listen(2)
conn, address = server_socket.accept() # accept new connection
print("Connection from: " + str(address))
while True:
# receive data stream. it won't accept data packet greater than
1024 bytes
data = conn.recv(1024).decode()
if not data:
# if data is not received break
break
print("from connected user: " + str(data))
data = input(' -> ')
conn.send(data.encode()) # send data to the client

conn.close() # close the connection

if __name__ == '__main__':
server_program()

Client Program:

import socket

def client_program():
host = socket.gethostname() # as both code is running on same pc
port = 5000 # socket server port number
client_socket = socket.socket() # instantiate
client_socket.connect((host, port)) # connect to the server

message = input(" -> ") # take input

while message.lower().strip() != 'bye':


client_socket.send(message.encode()) # send message
data = client_socket.recv(1024).decode() # receive response

print('Received from server: ' + data) # show in terminal

message = input(" -> ") # again take input

client_socket.close() # close the connection

if __name__ == '__main__':
client_program()

a.ii.

10. b. i.
from automata.fa.dfa import DFA
# DFA which matches all and in ‘bb’
dfa = DFA(
states={'q0', 'q1', 'q2'},
input_symbols={'a', 'b'},
transitions={
'q0': {'a': 'q0', 'b': 'q1'},
'q1': {'a': 'q0', 'b': 'q2'},
'q2': {'a': 'q0', 'b': 'q2'}
},
initial_state='q0',
final_states={'q1'}
)
dfa.read_input('abb') # answer is 'q1‘
dfa.read_input('ab') # answer is error
print(dfa.read_input_stepwise('ab'))
if dfa.accepts_input('abb'):
print('accepted')
else:
print('rejected')

b.ii. Diffrence between NFA and DFA

You might also like