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

COMPUTER PROGRAMMING PARADIGM (1)

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)
35 views

COMPUTER PROGRAMMING PARADIGM (1)

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/ 47

Indala College Of Engineering

Department of Information Technology


Course Name: Computer Programming Paradigms Lab
Course Code: ITL303

Year of Study: SE Semester: III

Course Outcomes
ITL303.1 Understand data abstraction and object orientation

ITL303.2 Design and implement declarative programs in functional and logic programming
languages
ITL303.3 Introduce the concepts of concurrent program execution.

ITL303.4 Understand run time program management.

ITL303.5 Understand how to implement a programming solution using different programming


paradigms.
ITL303.6 Learn to compare implementation in different programming paradigms.
INDEX

Sr.No. Name of the Experiment Page Date Signature


No.

1. Demonstrate concepts like - Encapsulation,


Inheritance, Initialization and Finalization,
Dynamic Binding.

2. Introduction to Haskell Programming Environment

3. Demonstarte and implement Haskell : Operators


and Types.

4. Demonstrate key concepts of functional


programming, including higher-order functions,
recursion, immutability, and type classes.

5. Prolog programs to understand declarative


programming concepts .

6. Thread management and synchronization using


C++ and Java.

7. Program to understand Exception handling


preferably in C++ and JAVA

8. Program to understand Garbage Collection


preferably in C++ and JAVA.

9. Implement multiple paradigms like procedural,


object oriented .

10. Implement multiple paradigms like functional,


logic.
EXPERIMENT NO .01
AIM : Demonstrate concepts like - Encapsulation, Inheritance, Initialization and Finalization,
Dynamic Binding.
THEORY : Object-oriented programming – As the name suggests uses objects in programming.
Object-oriented programming aims to implement real-world entities like inheritance, hiding,
polymorphism, etc. in programming. The main aim of OOP is to bind together the data and
the functions that operate on them so that no other part of the code can access this data
except that function.
There are some basic concepts that act as the building blocks of OOPs i.e.
1. Class
2. Objects
3. Encapsulation
4. Abstraction
5. Polymorphism
6. Inheritance
7. Dynamic Binding
8. Message Passing
Characteristics of an Object-Oriented Programming Language

Class
The building block of C++ that leads to Object-Oriented programming is a Class. It is a user-
defined data type, which holds its own data members and member functions, which can be
accessed and used by creating an instance of that class. A class is like a blueprint for an object.
For Example: Consider the Class of Cars. There may be many cars with different names and
brands but all of them will share some common properties like all of them will have 4 wheels,
Speed Limit, Mileage range, etc. So here, the Car is the class, and wheels, speed limits, and
mileage are their properties.
Object
An Object is an identifiable entity with some characteristics and behavior. An Object is an
instance of a Class. When a class is defined, no memory is allocated but when it is instantiated
(i.e. an object is created) memory is allocated.
Encapsulation
In normal terms, Encapsulation is defined as wrapping up data and information under a single
unit. In Object-Oriented Programming, Encapsulation is defined as binding together the data
and the functions that manipulate them. Consider a real-life example of encapsulation, in a
company, there are different sections like the accounts section, finance section, sales section,
etc.
Encapsulation also leads to data abstraction or data hiding. Using encapsulation also hides the
data. In the
Abstraction
Data abstraction is one of the most essential and important features of object-oriented
programming in C++. Abstraction means displaying only essential information and hiding the
details. Data abstraction refers to providing only essential information about the data to the
outside world, hiding the background details or implementation.
Polymorphism
The word polymorphism means having many forms. In simple words, we can define
polymorphism as the ability of a message to be displayed in more than one form. A person at
the same time can have different characteristics. A man at the same time is a father, a husband,
and an employee. So the same person possesses different behavior in different situations.
This is called polymorphism.
Inheritance
The capability of a class to derive properties and characteristics from another class is
called Inheritance. Inheritance is one of the most important features of Object-Oriented
Programming.
• Sub Class: The class that inherits properties from another class is called Sub class or Derived
Class.
• Super Class: The class whose properties are inherited by a sub-class is called Base Class or
Superclass.
Dynamic Binding
In dynamic binding, the code to be executed in response to the function call is decided at
runtime. C++ has virtual functions to support this. Because dynamic binding is flexible, it
avoids the drawbacks of static binding, which connected the function call and definition at
build time.
Message Passing
Objects communicate with one another by sending and receiving information. A message for
an object is a request for the execution of a procedure and therefore will invoke a function in
the receiving object that generates the desired results. Message passing involves specifying
the name of the object, the name of the function, and the information to be sent.

CODE:
ENCAPSULATION
CODE:
// Program to calculate the area of a rectangle
#include <iostream>
using namespace std;

class Rectangle {

public:
// Variables required for area calculation
int length;
int breadth;

// Constructor to initialize variables


Rectangle(int len, int brth) : length(len), breadth(brth) {}

// Function to calculate area


int getArea() {
return length * breadth;
}
};
int main() {
// Create object of Rectangle class
Rectangle rect(8, 6);

// Call getArea() function


cout << "Area = " << rect.getArea();

return 0;
}
OUTPUT:

DYNAMIC INTILIZATION
CODE:

// C++ program for dynamic allocation


#include <iostream>
using namespace std;
class geeks {
int* ptr;

public:
// Default constructor
geeks()
{
// Dynamically initializing ptr
// using new
ptr = new int;
*ptr = 10;
}

// Function to display the value


// of ptr
void display()
{
cout << *ptr << endl;
}
};

// Driver Code
int main()
{
geeks obj1;

// Function Call
obj1.display();

return 0;
}

OUTPUT:

C++ supports five types of inheritance:


• Single inheritance
• Multiple inheritance
• Hierarchical inheritance
• Multilevel inheritance
• Hybrid inheritance

Single inheritance
CODE :

#include <iostream>
using namespace std;
class Account {
public:
float salary = 60000; };
class Programmer: public Account {
public:
float bonus = 5000; };
int main(void) {
Programmer p1;
cout<<"Salary: "<<p1.salary<<endl;
cout<<"Bonus: "<<p1.bonus<<endl;
return 0; }
C++ Multilevel Inheritance

Multilevel inheritance is a process of deriving a class from another derived class.

CODE:
#include <iostream>
using namespace std;
class Animal {
public:
void eat() {
cout<<"Eating..."<<endl;
}
};
class Dog: public Animal
{
public:
void bark(){
cout<<"Barking..."<<endl;
}
};
class BabyDog: public Dog
{
public:
void weep() {
cout<<"Weeping...";
}
};
int main(void) {
BabyDog d1;
d1.eat();
d1.bark();
d1.weep();
return 0;
}
OUTPUT:

C++ Multiple Inheritance

Multiple inheritance is the process of deriving a new class that inherits the attributes from
two or more classes.

CODE:
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
void get_a(int n)
{
a = n;
}
};

class B
{
protected:
int b;
public:
void get_b(int n)
{
b = n;
}
};
class C : public A,public B
{
public:
void display()
{
std::cout << "The value of a is : " <<a<< std::endl;
std::cout << "The value of b is : " <<b<< std::endl;
cout<<"Addition of a and b is : "<<a+b;
} };
int main()
{
C c;
c.get_a(10);
c.get_b(20);
c.display();
return 0;
}
OUTPUT:
C++ Hybrid Inheritance

Hybrid inheritance is a combination of more than one type of inheritance.

CODE:
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
void get_a()
{
std::cout << "Enter the value of 'a' : " << std::endl;
cin>>a;
}
};

class B : public A
{
protected:
int b;
public:
void get_b()
{
std::cout << "Enter the value of 'b' : " << std::endl;
cin>>b;
}
};
class C
{
protected:
int c;
public:
void get_c()
{
std::cout << "Enter the value of c is : " << std::endl;
cin>>c;
}
};

class D : public B, public C


{
protected:
int d;
public:
void mul()
{
get_a();
get_b();
get_c();
std::cout << "Multiplication of a,b,c is : " <<a*b*c<< std::endl;
}
};
int main()
{
D d;
d.mul();
return 0;
}
OUTPUT :

C++ Hierarchical Inheritance

Hierarchical inheritance is defined as the process of deriving more than one class from a base
class.

CODE:
#include <iostream>
using namespace std;
class Shape // Declaration of base class.
{
public:
int a;
int b;
void get_data(int n,int m)
{
a= n;
b = m;
}
};
class Rectangle : public Shape // inheriting Shape class
{
public:
int rect_area()
{
int result = a*b;
return result;
}
};
class Triangle : public Shape // inheriting Shape class
{
public:
int triangle_area()
{
float result = 0.5*a*b;
return result;
}
};
int main()
{
Rectangle r;
Triangle t;
int length,breadth,base,height;
std::cout << "Enter the length and breadth of a rectangle: " << std::endl;
cin>>length>>breadth;
r.get_data(length,breadth);
int m = r.rect_area();
std::cout << "Area of the rectangle is : " <<m<< std::endl;
std::cout << "Enter the base and height of the triangle: " << std::endl;
cin>>base>>height;
t.get_data(base,height);
float n = t.triangle_area();
std::cout <<"Area of the triangle is : " << n<<std::endl;
return 0;
}

Output:
EXPERIMENT NO .02

AIM : Introduction to Haskell Programming Environment

THEORY :Haskell is a statically typed, purely functional programming language known for its strong
type system, lazy evaluation, and expressive syntax. Setting up the Haskell programming environment
is the first step to start coding in Haskell. This tutorial will guide you through the installation and basic
usage of Haskell.

1. Installing Haskell

The most common way to install Haskell is by using the Haskell Platform or GHCup. Here's how to get
started with both methods:

Option A: Using GHCup

1. Download GHCup:

o Open your terminal (Command Prompt on Windows, Terminal on macOS/Linux).

o Run the following command to install GHCup:

curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh

2. This script will guide you through the installation process.

3. Install GHC and Cabal:

o Once GHCup is installed, you can install GHC (Glasgow Haskell Compiler) and Cabal
(the build system and package manager) with:

code

ghcup install ghc

ghcup install cabal

4. Set Environment Variables:

o Follow the instructions provided by GHCup to set your environment variables.

5. Verify Installation:

o Check that GHC and Cabal are installed correctly:

Code

ghc --version

cabal –version
2. Setting Up a Simple Haskell Project

1. Create a New Project Directory:

o In your terminal, create a new directory for your Haskell project:

code

mkdir my-haskell-project

cd my-haskell-project

2. Initialize a New Cabal Project:

o Run the following command to create a new Cabal project:


code

cabal init

3. Follow the prompts to set up your project.

4. Write a Simple Haskell Program:

o Create a new file named Main.hs in your project directory:

code

-- Main.hs

module Main where

main :: IO ()

main = putStrLn "Hello, Haskell!"

5. Build the Project:

o In your terminal, run:

code

cabal build

6. Run the Program:

o To run your Haskell program, use:

code

cabal run

7. You should see the output: Hello, Haskell!


4. Conclusion

You have now set up your Haskell programming environment and created a simple project. With
GHCi, you can interactively test your Haskell code, while Cabal helps you manage your projects. Start
exploring Haskell's features, and happy coding!
EXPERIMENT NO .03
AIM : Demonstarte and implement Haskell : Operators and Types

Theory :
This exercise will introduce you to Haskell’s basic operators and types. You will explore arithmetic
operators, comparison operators, logical operators, and type declarations. Let’s get started!

1. Arithmetic Operators

In Haskell, you can perform basic arithmetic operations like addition, subtraction, multiplication, and
division.

Exercise: Basic Arithmetic

1. Open GHCi by typing ghci in your terminal.

2. Try the following expressions:

code

5+3 -- Addition

10 - 4 -- Subtraction

6*7 -- Multiplication

15 / 3 -- Division

7 `mod` 3 -- Modulus

2. Comparison Operators

Haskell provides several operators for comparing values.

Exercise: Comparison Operators


1. In GHCi, try the following comparisons:

haskell

Copy code

5 < 10 -- Less than

10 > 5 -- Greater than

7 == 7 -- Equal to

5 /= 3 -- Not equal to

10 <= 10 -- Less than or equal to

3. Logical Operators

Logical operators combine boolean values.

Exercise: Logical Operators

1. Try the following expressions in GHCi:

code

True && False -- Logical AND

True || False -- Logical OR

not True -- Logical NOT

4. Working with Types

In Haskell, you can define and work with different types. Here are some of the basic types:

• Int: Integer numbers.


• Float: Floating-point numbers.

• Double: Double-precision floating-point numbers.

• Bool: Boolean values (True or False).

• Char: A single character.

Exercise: Type Declarations

1. Open a new file called Types.hs and write the following code:

-- Types.hs

myInt :: Int

myInt = 42

myFloat :: Float

myFloat = 3.14

myDouble :: Double

myDouble = 2.71828

myBool :: Bool

myBool = True

myChar :: Char

myChar = 'H'

2. Load the file in GHCi:

code

:load Types

3. Check the values and their types:

code

myInt

myFloat

myDouble

myBool

myChar

4. Question: Use the :t command to check the type of each variable. For example:

code

:t myInt

5. Creating Custom Functions

You can define your own functions using Haskell’s syntax.

Exercise: Defining Functions


1. In the same Types.hs file, add the following function:

code

add :: Int -> Int -> Int

add x y = x + y

multiply :: Float -> Float -> Float

multiply x y = x * y

2. Load the updated file in GHCi and test your functions:

code

add 5 10

multiply 2.5 4.0

3. Question: What are the results of add 5 10 and multiply 2.5 4.0?

6. Summary and Reflection

• Question: Write a brief summary of what you learned about operators and types in Haskell.

• Exercise: Create a function that takes a list of integers and returns their sum. Test your
function in GHCi.

Conclusion

You have now practiced using operators, types, and defining functions in Haskell. This exercise lays
the foundation for more advanced concepts in Haskell programming. If you have any questions or
need further clarification, feel free to ask! Happy coding!
EXPERIEMENT NO .04
AIM : Demonstrate key concepts of functional programming, including higher-order functions,
recursion, immutability, and type classes.

THEORY :

1. Fibonacci Sequence (Recursion)

This program calculates the Fibonacci sequence using a recursive function.

CODE:
-- Fibonacci.hs
fibonacci :: Int -> Int
fibonacci n
| n <= 0 = 0
| n == 1 = 1
| otherwise = fibonacci (n - 1) + fibonacci (n - 2)

main :: IO ()
main = do
let n = 10
putStrLn $ "Fibonacci of " ++ show n ++ " is " ++ show (fibonacci n)
OUTPUT:

2. Map Function (Higher-Order Functions)

This program demonstrates the use of a higher-order function by implementing a map function that
applies a function to each element in a list
Code

-- Map.hs

myMap :: (a -> b) -> [a] -> [b]

myMap _ [] = []

myMap f (x:xs) = f x : myMap f xs


main :: IO ()

main = do

let numbers = [1, 2, 3, 4, 5]

let doubled = myMap (*2) numbers

putStrLn $ "Original: " ++ show numbers

putStrLn $ "Doubled: " ++ show doubled

OUTPUT:

3. Filter Function (Higher-Order Functions)

This program implements a filter function to select elements from a list based on a predicate.

Code

-- Filter.hs

myFilter :: (a -> Bool) -> [a] -> [a]

myFilter _ [] = []

myFilter p (x:xs)

|px = x : myFilter p xs

| otherwise = myFilter p xs

main :: IO ()

main = do

let numbers = [1, 2, 3, 4, 5, 6]

let evenNumbers = myFilter even numbers


putStrLn $ "Original: " ++ show numbers

putStrLn $ "Even numbers: " ++ show evenNumbers


OUTPUT:

4. Factorial Function (Recursion and Pattern Matching)

This program calculates the factorial of a number using recursion and pattern matching.

Code

-- Factorial.hs

factorial :: Int -> Int

factorial 0 = 1

factorial n = n * factorial (n - 1)

main :: IO ()

main = do

let n = 5

putStrLn $ "Factorial of " ++ show n ++ " is " ++ show (factorial n)

OUTPUT:
5. Basic Calculator (Polymorphism and Type Classes)

This program demonstrates polymorphism using type classes to create a simple calculator.

Code

-- Calculator.hs

class Num a where

add :: a -> a -> a

subtract :: a -> a -> a

multiply :: a -> a -> a

divide :: a -> a -> a

instance Num Int where

add = (+)

subtract = (-)

multiply = (*)

divide = div

calculate :: Int -> Int -> (Int -> Int -> Int) -> Int

calculate x y operation = operation x y

main :: IO ()

main = do

let a = 10
let b = 5

putStrLn $ "Addition: " ++ show (calculate a b add)

putStrLn $ "Subtraction: " ++ show (calculate a b subtract)

putStrLn $ "Multiplication: " ++ show (calculate a b multiply)

putStrLn $ "Division: " ++ show (calculate a b divide)

Conclusion

These five programs illustrate fundamental functional programming concepts in Haskell:

1. Recursion: Fibonacci and factorial examples show how to use recursion for calculations.

2. Higher-Order Functions: The map and filter functions demonstrate how to pass functions as
arguments.

3. Pattern Matching: Used in the factorial function for cleaner recursive definitions.

4. Polymorphism and Type Classes: The calculator example illustrates how Haskell handles
polymorphism through type classes.
EXPERIMENT NO : 05

AIM : Prolog programs to understand declarative programming concepts .

1. Family Relationships

CODE:
% Facts
parent(john, mary).
parent(john, bob).
parent(susan, mary).
parent(susan, bob).
parent(mary, alice).
parent(bob, charlie).

sibling(X, Y) :- parent(Z, X), parent(Z, Y), X \= Y.


grandparent(X, Y) :- parent(X, Z), parent(Z, Y).

QUERY

?- sibling(mary, bob).
?- grandparent(john, alice).

OUTPUT:
2. A Simple Knowledge Base
CODE

% Facts
animal(dog).
animal(cat).
animal(bird).

mammal(dog).
mammal(cat).

can_fly(bird).

% Rules
is_mammal(X) :- mammal(X).
can_animal_fly(X) :- can_fly(X).

Queries:
?- animal(X).
?- is_mammal(dog).
% ?- can_animal_fly(bird).
CODE

% Facts
add(X, Y, Result) :- Result is X + Y.
subtract(X, Y, Result) :- Result is X - Y.
multiply(X, Y, Result) :- Result is X * Y.
divide(X, Y, Result) :- Y \= 0, Result is X / Y.

QUERY:
add(2, 3, Result).
divide(10, 2, Result).
CODE:
% Maze representation
path(a, b).
path(b, c).
path(c, d).
path(d, e).
path(a, f).
path(f, e).

% Find a path
find_path(Start, End, Path) :-
travel(Start, End, [Start], Path).

travel(Start, End, Visited, [End|Visited]) :-


path(Start, End).
travel(Start, End, Visited, Path) :-
path(Start, Z),
Z \= End,
\+ member(Z, Visited),
travel(Z, End, [Z|Visited], Path).

Query:
find_path(a, e, Path).
EXPERIMENT NO .06

AIM : Thread management and synchronization using C++ and Java.

THEORY:

1.Thread Management:
In C++, the <thread> library introduced in C++11 provides a straightforward interface for creating and
managing threads. A thread is a basic unit of CPU utilization and represents a separate path of
execution.
• Creating Threads: A thread in C++ can be created by instantiating a std::thread object and
passing a callable (function or lambda) to it.
• Joining Threads: Once a thread finishes its execution, it can be joined using the join()
method. This ensures that the main thread waits for the spawned thread to complete.
• Detaching Threads: Threads can also be detached using the detach() method, which makes
them run independently from the main thread. However, this can lead to resource
management issues if not handled carefully.

• Threads: We create two threads (t1 and t2) that run the CounterThread class, which
in turn increments the shared counter.
• Synchronization: The synchronized keyword is used in the increment() method of
the Counter class to ensure that only one thread can access this method at a time.
• Thread Management: The start() method is used to start each thread, and join()
ensures that the main thread waits until both threads have finished executing.

2. Thread Synchronization in C++


In a multi-threaded environment, race conditions can occur when multiple threads try to access
shared resources simultaneously. Synchronization mechanisms, such as mutexes and locks, prevent
this by ensuring that only one thread accesses a critical section of code at a time.
• Mutex (std::mutex): A mutex is a lock that provides exclusive access to a shared resource.
Only one thread can own the mutex at a time, ensuring safe access to the resource.
• Locking Mechanisms:
o std::lock_guard automatically locks and unlocks the mutex, helping to prevent
deadlock situations.
o std::unique_lock provides more flexible locking mechanisms.

CODE:

class Counter {
private int count = 0;
// Synchronized method to increment the counter
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
class CounterThread extends Thread {
private Counter counter;

public CounterThread(Counter counter) {


this.counter = counter;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
}
}
public class ThreadSyncExample {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
// Creating two threads
Thread t1 = new CounterThread(counter);
Thread t2 = new CounterThread(counter);
// Start the threads
t1.start();
t2.start();

// Wait for both threads to finish


t1.join();
t2.join();

System.out.println("Final counter value: " + counter.getCount());


}
}
OUTPUT:
EXPERIMENT NO .07

AIM: Program to understand Exception handling preferably in C++ and JAVA

THEORY :
Exception handling is a mechanism to handle runtime errors, ensuring the program does not crash and
can recover from unforeseen conditions.
C++ Exception Handling
In C++, exception handling is done using the try-catch blocks. A throw statement is used to signal that
an exception has occurred.
Java Exception Handling
Java handles exceptions using the same try-catch blocks, but with the built-in class Exception. Java uses
checked and unchecked exceptions, requiring some exceptions to be explicitly declared or caught.
Syntactic Differences in Exception Handling:
• In C++, any object can be thrown as an exception, while in Java, exceptions must be derived
from Throwable (typically Exception).
• Java uses a more rigid structure with checked exceptions (forcing developers to handle certain
exceptions), while C++ doesn’t impose such rules.
• C++ exceptions are caught by reference (e.g., catch (const std::exception& e)), while Java
catches exceptions as objects (e.g., catch (ArithmeticException e)).
CODE:

#include <iostream>
#include <stdexcept> // For standard exceptions

void divide(int a, int b) {


if (b == 0) {
throw std::runtime_error("Division by zero error");
} else {
std::cout << "Result: " << a / b << std::endl;
}
}
int main() {
try {
divide(10, 2); // Valid division
divide(10, 0); // This will throw an exception
} catch (const std::exception &e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
}
return 0;
}
OUTPUT:

CODE:
public class Main {
public static void divide(int a, int b) throws ArithmeticException {
if (b == 0) {
throw new ArithmeticException("Division by zero error");
} else {
System.out.println("Result: " + (a / b));
}
}

public static void main(String[] args) {


try {
divide(10, 2); // Valid division
divide(10, 0); // This will throw an exception
} catch (ArithmeticException e) {
System.out.println("Caught exception: " + e.getMessage());
}
}
}

OUTPUT:
EXPERIMENT NO .08

AIM: Program to understand Garbage Collection preferably in C++ and JAVA

THEORY :

Garbage collection refers to the automatic management of memory, reclaiming memory that is no
longer in use. This happens differently in C++ and Java.
C++: Manual Memory Management
C++ does not have built-in garbage collection. Instead, memory management is manual, and
developers must use new and delete to allocate and free memory, respectively. Smart pointers (like
std::shared_ptr and std::unique_ptr) introduced in C++11 can help automate memory management
by providing reference counting and automatic destruction.
• Raw pointers (new and delete) require manual memory management.
• Smart pointers (std::shared_ptr, std::unique_ptr) allow automatic memory management
with scope-based destruction.
Java: Automatic Garbage Collection
In Java, the garbage collector automatically manages memory. You create objects using the new
keyword, and when an object is no longer referenced, the garbage collector reclaims the memory.

CODE:
#include <iostream>
#include <memory> // For smart pointers

class MyObject {
public:
MyObject() { std::cout << "Object created" << std::endl; }
~MyObject() { std::cout << "Object destroyed" << std::endl; }
};

int main() {
// Using raw pointers (manual memory management)
MyObject* obj = new MyObject();
delete obj; // Manual deletion

// Using smart pointers (automatic memory management)


std::shared_ptr<MyObject> smartObj = std::make_shared<MyObject>();
// No need to manually delete, it will be automatically destroyed

return 0;
}
OUTPUT:
CODE:

public class MyObject {


public MyObject() {
System.out.println("Object created");
}

protected void finalize() {


System.out.println("Object destroyed");
}

public static void main(String[] args) {


// Create object (no need for explicit memory management)
MyObject obj = new MyObject();
obj = null; // Eligible for garbage collection

// Suggest to run garbage collection (although not guaranteed)


System.gc();
}
}
OUTPUT:

CONCLUSION:
Both C++ and Java provide robust ways to handle exceptions and memory management, but their
approaches differ significantly.
• C++ gives more control to the programmer in terms of memory management (manual
allocation and deallocation) but requires more responsibility to avoid memory leaks and
dangling pointers.
• Java simplifies memory management through automatic garbage collection, making it easier
for developers to focus on application logic without worrying about memory deallocation.
EXP NO .09

AIM : Implement multiple paradigms like procedural, object oriented .

THEORY :

Problem 1: Factorial Calculation


This problem calculates the factorial of a given number. We'll implement it using procedural, object-
oriented, functional, and logic paradigms.

1.1 Procedural Implementation (C)

• In procedural programming, we define a function that directly operates on data (in


this case, the factorial function).
• The focus is on writing procedures (functions) that handle specific tasks.
CODE:
#include <stdio.h>

int factorial(int n) {
if (n == 0 || n == 1)
return 1;
else
return n * factorial(n - 1);
}

int main() {
int num = 5;
printf("Factorial of %d is %d\n", num, factorial(num));
return 0;
}

OUTPUT:

This problem checks whether a given number is prime or not, implemented in multiple paradigms
• In the procedural paradigm, the focus is on a step-by-step approach to solve the
problem.
• The is_prime function performs a specific task using loops and conditions.

CODE:
#include <stdio.h>

int is_prime(int n) {
if (n <= 1) return 0;
for (int i = 2; i <= n / 2; i++) {
if (n % i == 0)
return 0;
}
return 1;
}

int main() {
int num = 7;
if (is_prime(num))
printf("%d is a prime number\n", num);
else
printf("%d is not a prime number\n", num);
return 0;
}
OUTPUT:

1.2 Object-Oriented Implementation (C++)


• In object-oriented programming (OOP), the Factorial class encapsulates both data
and behavior.
• The focus is on objects (instances of the class) that interact to achieve the goal.
CODE:
#include <iostream>
using namespace std;
class Factorial {
public:
int calculate(int n) {
if (n == 0 || n == 1)
return 1;
else
return n * calculate(n - 1);
}
};
int main() {
Factorial fact;
int num = 5;
cout << "Factorial of " << num << " is " << fact.calculate(num) << endl;
return 0;
}

• H ere, the PrimeChecker class encapsulates the behavior of checking for prime
numbers.
• The object-oriented paradigm emphasizes reusability and modularity, making it
easier to extend or modify the PrimeChecker class.
CODE:
class PrimeChecker {
public boolean isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i <= n / 2; i++) {
if (n % i == 0)
return false;
}
return true;
}
}
public class Main {
public static void main(String[] args) {
PrimeChecker checker = new PrimeChecker();
int num = 7;
if (checker.isPrime(num))
System.out.println(num + " is a prime number");
else
System.out.println(num + " is not a prime number");
}
}
OUTPUT:
EXPERIMENT NO .10

AIM : Implement multiple paradigms like functional, logic.

THEORY:

• In functional programming, functions are treated as first-class citizens, and recursion


is often used (as in this case).
• There is no mutable state, and the code avoids side effects.
CODE:
def factorial(n):
return 1 if n == 0 else n * factorial(n - 1)

num = 5
print(f"Factorial of {num} is {factorial(num)}")

• Logic programming uses facts and rules to derive new facts.


• The focus is on defining relationships (in this case, the relationship between N and its
factorial F).
CODE:
factorial(0, 1).
factorial(N, F) :- N > 0, N1 is N - 1, factorial(N1, F1), F is N * F1.

Query:
factorial(5, Result).
• Functional programming in Haskell focuses on pure functions without mutable state.
• The isPrime function is concise and uses list comprehensions to check if the number
is divisible by any number between 2 and n-1.
CODE:
is_prime(2).
is_prime(N) :- N > 2, \+ has_factor(N, 2).

has_factor(N, F) :- N mod F =:= 0.


has_factor(N, F) :- F * F < N, F2 is F + 1, has_factor(N, F2).

Query: is_prime(7).

You might also like