Professional Documents
Culture Documents
LIST OF EXPERIMENTS
INTRODUCTION
Programming paradigms:
1. Functional programming (Scheme, Lisp, ML): Its origins are in the lambda
calculus.
2. Logic programming (Prolog): Its origins are in mathematical logic.
3. Imperative programming (ALGOL-60, Pascal, C): Its origins are in the
VonNeumann computer architecture.
For each computational paradigm we define its syntax and operational semantics and
implement a meta tool for its evaluation. We use it to solve typical problems, and study
essential properties.
Most subjects and techniques are taught using the scheme language: A small and
powerful language, designed for educational purposes.
− small – It has a very simple syntax, with few details. Can be taught in half an
hour.
− powerful – It combines, in an elegant way, the ideas of functional and
imperative programming. It can be easily used to demonstrate all programming
approaches.
PREFACE
This practical manual will be helpful for students of Computer Science & Engineering for
understanding the course from the point of view of applied aspects. Though all the efforts
have been made to make this manual error free, yet some errors might have crept in
inadvertently. Suggestions from the readers for the improvement of the manual are most
welcomed.
DO’s
DONT’S
1. Know the location of the fire extinguisher and the first aid box and how to use them in
case of an emergency.
4. Do not plug in external devices without scanning them for computer viruses.
Name
Roll No.
Section- Batch
Data Structures Using C/ Java Lab (RCS-355) Manual (CS, III SEM) Page 16
Department of Computer Science & Engineering
INDEX
Experiment Experiment Date of Date of Faculty
No. Name Conduction Submission Signature
Students are provided with the details of the experiment (Aim, pre-experimental questions,
procedure etc.) to be conducted in next lab and are expected to come prepared for each lab
class.
Faculty ensures that students have completed the in-lab programming assignment(s) before
the end of class. Given that the lab programs are meant to be formative in nature, students can
ask faculty for help before and during the lab class.
Students’ performance will be assessed in each lab based on the following Lab Assessment
Components:
Assessment Criteria-1: Performance (Max. marks = 5)
Assessment Criteria-2: VIVA (Max. marks = 5)
Assessment Criteria-3: Record (Max. marks = 5)
In each lab class, students will be awarded marks out of 5 under each component head,
making it total out of 15 marks.
Contents:
1. Review
o LISP
o PROLOG
o Introduction
o Properties
3. Introduction of ML
o Definition
o Functional Programming
4. Data Science
Review
o LISP
o PROLOG
Computer programming languages are used to communicate instructions to a computer. They are
based on certain syntactic and semantic rules, which define the meaning of each of the
programming language constructs.
Lisp: Lisp is the second-oldest high-level programming language in widespread use today. The
name Lisp is derived from ‘List Processing Language’. One of the important data structures that
Lisp supports is linked list. Lisp programs deal with source code as a data structure.
Pascal: It is a procedural programming language that was intended to use data structuring and
structured programming.
Perl: Perl is a high-level interpreted programming language that supports dynamic programming.
Ruby: The efforts for developing this language initiated in Japan in the 1990s. Similar to Perl, it
has a dynamic type system and an automatic memory management.
ML: Standard ML is popular among compiler writers and is a modular, functional programming
language. Alice is a dialect of Standard ML, which supports distributed computing, multithreading
and constraint programming. Caml is another dialect of ML and is a statically typed language that
supports automatic memory management. Ocaml is the implementation of Caml that is developed
as an open source project. JoCaml is a version of Ocaml based on join-calculus.
Procedural (imperative) programming implies specifying the steps that the programs should take
to reach to an intended state. A procedure is a group of statements that can be referenced through a
procedure call.
PHP: PHP is one of the very popularly used general purpose scripting languages. It is developed
for creating dynamic web pages and supports a command line interface capability.
Markup Languages: A markup language is an artificial language that uses annotations to text
that define how the text is to be displayed.
Logic programming is a type of programming paradigm which is largely based on formal logic.
Any program written in a logic programming language is a set of sentences in logical form,
expressing facts and rules about some problem domain.
Concurrent programming is a computer programming technique that provides for the execution of
operations concurrently — either within a single computer, or across a number of systems. In the
latter case, the term distributed computing is used.
o Introduction
o Properties
Abstraction: Data abstraction refers to, providing only essential information to the outside world
and hiding their background details, i.e., to represent the needed information in program without
presenting the details.
Encapsulation: Encapsulation is placing the data and the functions that work on that data in the
same place. While working with procedural languages, it is not always clear which functions
work on which variables but object-oriented programming provides you framework to place the
data and the relevant functions together in the same object.
Inheritance: One of the most useful aspects of object-oriented programming is code reusability.
As the name suggests Inheritance is the process of forming a new class from an existing class that
is from the existing class called as base class, new class is formed called as derived class.
This is a very important concept of object-oriented programming since this feature helps to
reduce the code size.
Polymorphism: The ability to use an operator or function in different ways in other words giving
different meaning or functions to the operators or functions is called polymorphism. Poly refers
to many. That is a single function or an operator functioning in many ways different upon the
usage is called polymorphism.
Overloading: The concept of overloading is also a branch of polymorphism. When the exiting
operator or function is made to operate on new data type, it is said to be overloaded.
o Definition
o Functional Programming
Standard Meta Language (SML) was originally designed for theorem proving
• High quality compilers, e.g. Standard ML of New Jersey and Moscow ML, based on a
formal semantics
• SML have now may applications far away from its origins Compilers, Artificial
Intelligence, Web-applications, . . .
ML:
1+2*3;
val it = 7 : int
so, integers, reals, booleans, and strings are the fundamental types in ML
1. Integers -- a string of digits (0-9), optionally preceded by a tilde (~) to indicate negative
1. \ is a special character, and means that the next character (or more) indicate
something special
2. \n is the newline character, basically just like hitting the Return key
4. \\ is the backslash -- since one \ is special, just type \\ to really mean backslash
5. \" is the double-quote -- a plain double-quote would mean the end of the string, to
have a double-quote actually be in the string, you use \"
\ as the last character on the line means the string continues on the following line
➢ ML is well known for its use of the Hindley-Milner type system that can automatically
assign the types of most expressions without explicit type annotations
• Scientific applications;
• Theorem provers;
➢ The ML programming language was developed in the 1970s by Robin Milner and his
colleagues at the University of Edinburgh during their work on the Logic for Computable
Functions (LCF) — an interactive automated theorem prover. LCF was implemented in
ML and introduced in 1972. ML's syntax was inspired by the ISWIM programming
language. ML is a strictly typed language.
➢ Standard ML of New Jersey (SML/NJ) derivative and compiler, since it is the first and
most popular compiler for the ML programming language.
Data Science
This aspect of data science is all about uncovering findings from data. Diving in at a granular
level to mine and understand complex behaviors, trends, and inferences. It's about surfacing
hidden insight that can help enable companies to make smarter business decisions. For example:
• Netflix data mines movie viewing patterns to understand what drives user interest, and
uses that to make decisions on which Netflix original series to produce.
• Target identifies what are major customer segments within it's base and the unique
shopping behaviors within those segments, which helps to guide messaging to different market
audiences.
• Proctor & Gamble utilizes time series models to more clearly understand future demand,
which help plan for production levels more optimally.
The classic example of a data product is a recommendation engine, which ingests user data, and
makes personalized recommendations based on that data. Here are some examples of data
products:
• Gmail's spam filter is data product – an algorithm behind the scenes processes incoming
mail and determines if a message is junk or not.
• Computer vision used for self-driving cars is also data product – machine learning
algorithms are able to recognize traffic lights, other cars on the road, pedestrians, etc.
Contents:
2. SML NJ
3. Installation Steps
4. Simple Program of ML
➢ The current release of SML/NJ is Version 110.81, announced on August 26, 2016.
Version 110.81 runs under Linux, Mac OS X (10.6 and later), and Windows (XP an later).
• The core of the SML/NJ system is an agressively optimizing compiler that produces
native machine code for most commonly used architectures: x86 (IA32), Sparc, MIPS,
IBM Power 1 (PowerPC), HPPA, and Alpha.
• SML/NJ runs under Windows 95 and NT as well as many flavors of Unix. Renewed
support for MacOS is planned for the next release.
• SML/NJ provides an interactive top level based on incremental compilation, but it can
produce stand-alone executables using the exportFn function.
• SML/NJ uses Matthias Blume's Compilation Manager, CM, to greatly simplify the
development of large software projects.
• A variety of general-purpose data structures, algorithms and utilities (such as finite sets
and maps, regular expressions, pretty-printing) are provided by the SML/NJ library.
• Support for manipulating "object languages" (e.g. logics, calculi, simple programming
languages, specification languages) is provided by a simple quote/anitquote mechanism.
a. Open
https://www.smlnj.org/dist/working/index.html
https://www.smlnj.org/dist/working/110.82/index.html
h. write cd bin
write ./sml
➢ cd Documents
➢ cd sml
➢ cd bin
➢ ./sml
Simple ML Program
Input data: Two integers are written in the input stream, separated by space(s):
Output data: The required output is one integer: the sum of A and B.
Example
input output
22 4
32 5
(*
* val split : string -> string list
* splits a string at it spaces
*)
val split = String.fields (fn #" " => true | _ => false)
(*
* val removeNl : string -> string
* removes the occurence of "\n" in a string
*)
val removeNl = String.translate (fn #"\n" => "" | c => implode [c])
(*
* val aplusb : unit -> int
* reads a line and gets the sum of the numbers
*)
fun aplusb () =
let
val input = removeNl (valOf (TextIO.inputLine TextIO.stdIn))
in
foldl op+ 0 (map (fn s => valOf (Int.fromString s)) (split input))
end
- aplusb();
123 456
2. Arithmetic/Integer
Get two integers from the user, and then (for those two integers), display their:
• Sum, difference, product, integer quotient, remainder, exponentiation (if the operator exists)
val () = let
val a = valOf (Int.fromString (valOf (TextIO.inputLine TextIO.stdIn)))
val b = valOf (Int.fromString (valOf (TextIO.inputLine TextIO.stdIn)))
in
print ("a + b = " ^ Int.toString (a + b) ^ "\n");
print ("a - b = " ^ Int.toString (a - b) ^ "\n");
print ("a * b = " ^ Int.toString (a * b) ^ "\n");
print ("a div b = " ^ Int.toString (a div b) ^ "\n"); (* truncates towards negative infinity *)
print ("a mod b = " ^ Int.toString (a mod b) ^ "\n"); (* same sign as second operand *)
print ("a quot b = " ^ Int.toString (Int.quot (a, b)) ^ "\n");(* truncates towards 0 *)
print ("a rem b = " ^ Int.toString (Int.rem (a, b)) ^ "\n"); (* same sign as first operand *)
print ("~a = " ^ Int.toString (~a) ^ "\n") (* unary negation, unusual notation
compared to other languages *)
end
3. Array length
let
val a = Array.fromList ["apple", "orange"]
in
Array.length a
end;
4. Combinations
Given non-negative integers m and n, generate all size m combinations of the integers
from 0 (zero) to n-1 in sorted order (each combination is sorted and the entire table is
sorted).
Example
3 comb 5 is:
013
014
023
024
034
123
124
134
234
• 2007-11-23 and
Create a function that returns the maximum value in a provided set of values,
where the number of values may not be known until run-time.
Comparisons are specific for each type. Here is a max function for a list of ints:
- max_of_ints [4,3,5,9,2,3];
val it = 9 : int
9. Loops/While
Print the value (with a newline) and divide it by two each time through the loop.
let
fun loop n =
if n > 0 then (
print (Int.toString n ^ "\n");
loop (n div 2)
) else ()
in
loop 1024
end
Contents:
Searching techniques
Searching is an operation or a technique that helps finds the place of a given element or value in
the list. Any search is said to be successful or unsuccessful depending upon whether the element
that is being searched is found or not. Some of the standard searching technique that is being
followed in the data structure is listed below:
• Binary Search
Linear search
Basics
This is the simplest method for searching. In this technique of searching, the element to be found
in searching the elements to be found is searched sequentially in the list. This method can be
performed on a sorted or an unsorted list (usually arrays). In case of a sorted list searching starts
from 0th element and continues until the element is found from the list or the element whose
value is greater than (assuming the list is sorted in ascending order), the value being searched is
reached.
Many programming languages provide convenient ways to look for a known value in a simple
list of strings or numbers.
But what if the elements of the list are themselves compound records/objects/data-structures, and
the search condition is more complex than a simple equality test?
Task: Write a function/method/etc. that can find the first element in a given list matching a given
condition.
It should be as generic and reusable as possible.
Then to demonstrate its functionality, create the data structure specified under #Data set, and
perform on it the searches specified under
Data set
The data structure to be used contains the names and populations (in millions) of the 10 largest
metropolitan areas in Africa, and looks as follows when represented in JSON:
[
{ "name": "Lagos", "population": 21.0 },
{ "name": "Cairo", "population": 15.2 },
{ "name": "Kinshasa-Brazzaville", "population": 11.3 },
{ "name": "Greater Johannesburg", "population": 7.55 },
{ "name": "Mogadishu", "population": 5.85 },
{ "name": "Khartoum-Omdurman", "population": 4.98 },
{ "name": "Dar Es Salaam", "population": 4.7 },
{ "name": "Alexandria", "population": 4.58 },
{ "name": "Abidjan", "population": 4.4 },
{ "name": "Casablanca", "population": 3.98 }
]
However, you shouldn't parse it from JSON, but rather represent it natively in your programming
language.
• The top-level data structure should be an ordered collection (i.e. a list, array, vector, or similar).
• Each element in this list should be an associative collection that maps from keys to values (i.e. a
struct, object, hash map, dictionary, or similar).
• Each of them has two entries: One string value with key "name", and one numeric value with key
"population".
• You may rely on the list being sorted by population count, as long as you explain this to readers.
Test cases
Find the (zero-based) index of the first city in the list whose name is "Dar Es
6
Salaam"
Find the name of the first city in this list whose population is less than 5 Khartoum-
million Omdurman
Find the population of the first city in this list whose name starts with the
4.58
letter "A"
Guidance
If your programming language supports higher-order programming, then the most elegant way to
implement the requested functionality in a generic and reusable way, might be to write a function
(maybe called "find_index" or similar), that takes two arguments:
If this is not the approach which would be most natural or idiomatic in your language, explain
why, and show what is.
val firstCityi = #1 (valOf (List.findi (fn (_, city) => #name(city) = "Dar Es Salaam") citys))
val firstBelow5M = #name (valOf (List.find (fn city => #population(city) < 5.0) citys))
val firstPopA = #population (valOf (List.find (fn city => String.substring (#name(city), 0, 1) =
"A") citys))
Output:
use "/home/sak/sml/programs/random.sml";
local
end
end
search (b, A)
Contents:
1. Binary search
o Basics
Basics
Binary search is a very fast and efficient searching technique. It requires the list to be in sorted order. In
this method, to search an element you can compare it with the present element at the center of the list. If it
matches, then the search is successful otherwise the list is divided into two halves: one from the 0 thelement
to the middle element which is the center element (first half) another from the center element to the last
element (which is the 2nd half) where all values are greater than the center element.
A linear search scans one item at a time, without jumping to any item .
2. Time taken to search elements keep increasing as the number of elements are increased.
A binary search however, cut down your search to half as soon as you find middle of a sorted list.
1. The middle element is looked to check if it is greater than or less than the value to be searched.
▪ Input data needs to be sorted in Binary Search and not in Linear Search
▪ Linear search does the sequential access whereas Binary search access data randomly.
▪ Time complexity of linear search -O(n) , Binary search has time complexity O(log n).
▪ Linear search performs equality comparisons and Binary search performs ordering comparisons
Linear Search to find the element “J” in a given sorted list from A-X
Binary Search to find the element “J” in a given sorted list from A-X
A binary search divides a range of values into halves, and continues to narrow down the field of
search until the unknown value is found. It is the classic example of a "divide and conquer"
algorithm.
As an analogy, consider the children's game "guess a number." The scorer has a secret number,
and will only tell the player if their guessed number is higher than, lower than, or equal to the
secret number. The player then uses this information to guess a new number.
As the player, an optimal strategy for the general case is to start by choosing the range's midpoint
as the guess, and then asking whether the guess was higher, lower, or equal to the secret number.
If the guess was too high, one would select the point exactly between the range midpoint and the
beginning of the range. If the original guess was too low, one would ask about the point exactly
between the range midpoint and the end of the range. This process repeats until one has reached
the secret number.
Task: Given the starting point of a range, the ending point of a range, and the "secret value", implement a
binary search through a sorted integer array for a certain number. Implementations can be recursive or
iterative (both if you can). Print out whether or not the number was in the array afterwards. If it was, print
the index also.
There are several binary search algorithms commonly seen. They differ by how they treat
multiple values equal to the given value, and whether they indicate whether the element was
found or not. For completeness we will present pseudocode for all of them.
All of the following code examples use an "inclusive" upper bound (i.e. high = N-1 initially).
Any of the examples can be converted into an equivalent example using "exclusive" upper
bound (i.e. high = N initially) by making the following simple changes (which simply
increase high by 1):
• (for iterative algorithm) change while (low <= high) to while (low < high)
Recursive
Usage:
Usage:
= open Array
= end;
sig
structure IntBSearch :
sig
structure A : <sig>
end
Contents:
1. Sorting
a. Basics
b. Need of Sorting
c. Sorting Technique
2. Insertion sort
a. Basics
c. Insertion sort in ML
An O(n2) sorting algorithm which moves elements one at a time into the correct position. The
algorithm consists of inserting one element at a time into the previously sorted part of the array,
moving higher ranked elements up as necessary. To start off, the first (or smallest, or any
arbitrary) element of the unsorted array is considered to be the sorted part.
Although insertion sort is an O(n2) algorithm, its simplicity, low overhead, good locality of
reference and efficiency make it a good choice in two cases:
(i) small n,
(ii) as the final finishing-off algorithm for O(n logn) algorithms such
as mergesort and quicksort.
function insertionSort(array A)
value := A[i]
j := i-1
j := j-1
done
A[j+1] = value
done
Program
EXPERIMENT NUMBER: 5
Principles of Programming languages Lab (RCS-553) Manual (CS, V SEM) Page 53
Objective: Program for bubble sort in ML
Contents:
1. Bubble sort
o Basics
o Bubble sort in ML
Sort an array of elements using the bubble sort algorithm. The elements must have a total order
and the index of the array can be of any discrete type. For languages where this is not possible,
sort an array of integers.
Because of its simplicity and ease of visualization, it is often taught in introductory computer
science courses.
Because of its abysmal O(n2) performance, it is not used often for large (or even medium-sized)
datasets.
The bubble sort works by passing sequentially over a list, comparing each value to the one
immediately after it. If the first value is greater than the second, their positions are switched.
Over a number of passes, at most equal to the number of elements in the list, all of the values
drift into their correct positions (large values "bubble" rapidly toward the end, pushing others
down around them). Because each pass finds the maximum item and puts it at the end, the
portion of the list to be sorted can be reduced at each pass. A boolean variable is used to track
whether any changes have been made in the current pass; when a pass completes without
changing anything, the algorithm exits.
repeat
decrement itemCount
hasChanged := true
Program
fun bubble_select [] = []
| bubble_select (a::b::xs) =
fun bubblesort [] = []
Contents:
1. Merge sort
o Basics
o Merge sort in ML
It is notable for having a worst case and average complexity of O(n*log(n)), and a best case
complexity of O(n) (for pre-sorted input).
The basic idea is to split the collection into smaller groups by halving it until the groups only
have one element or no elements (which are both entirely sorted groups).
Then merge the groups back together so that their elements are in order.
This is how the algorithm gets its divide and conquer description.
Task: Write a function to sort a collection of integers using the merge sort.
a merge function
if length(m) ≤ 1
return m
else
add x to left
add x to right
left = mergesort(left)
right = mergesort(right)
if last(left) ≤ first(right)
return left
return result
function merge(left,right)
if first(left) ≤ first(right)
else
right = rest(right)
if length(left) > 0
if length(right) > 0
return result
Program
Contents:
Quick sort
o Basics
o Quick sort in ML
o Compare Insertion Sort, Bubble Sort, Merge sort and Quick Sorting technique
The elements must have a strict weak order and the index of the array can be of any discrete
type.
2. Divide all other elements (except the pivot) into two partitions.
• All elements less than the pivot must be in the first partition.
• All elements greater than the pivot must be in the second partition.
4. Join the first sorted partition, the pivot, and the second sorted partition.
The best pivot creates partitions of equal length (or lengths differing by 1).
The worst pivot creates an empty partition (for example, if the pivot is the first or last
element of a sorted array).
The run-time of Quicksort ranges from O(n log n) with the best pivots, to O(n2) with the
worst pivots, where n is the number of elements in the array.
function quicksort(array)
if length(array) > 1
quicksort(less)
quicksort(greater)
A better quicksort algorithm works in place, by swapping elements within the array, to avoid
the memory allocation of more arrays.
Program
fun quicksort [] = []
| quicksort (x::xs) =
let
val (left, right) = List.partition (fn y => y<x) xs
in
quicksort left @ [x] @ quicksort right
end
fun quicksort [] = []
| quicksort (h::t) =
let
val (left, right) = par(t, h)
in
quicksort left @ [h] @ quicksort right
end;
Contents:
A dictionary (or map) in computer science is a data structure that maps keys to values such that given a key its
corresponding value can be efficiently retrieved.
Program
struct
exception NotFound
if n = name
then v
| isEmpty _ = false;
let
if n = name then
else
in
end;
let
if n = name
| rm checked [] = checked
in
end
end;
Contents:
Take two lists, each of which is unsorted, and merges the two together into one new
list which is in sorted (increasing) order, should return the new list.
We first sort both the given list separately. Then we simply merge two sorted list.
Program
| merge (nil, L) = L
Contents:
The Factorial Function of a positive integer, n, is defined as the product of the sequence:
Program:
fun factorial n =
if n <= 0 then 1
else n * factorial (n-1)
Contents:
F0 = 0
F1 = 1
Solutions can be iterative or recursive (though recursive solutions are generally considered too
slow and are mostly used as an exercise in recursion).
The sequence is sometimes extended into negative numbers by using a straightforward inverse of
the positive definition:
Program:
fun fib n =
let
fun fib' (0,a,b) = a
| fib' (n,a,b) = fib' (n-1,a+b,a)
in
fib' (n,0,1)
end
Objective: Program to Create and display the sequence of binary digits for a given non-
negative integer in ML.
Contents:
The results can be achieved using built-in radix functions within the language (if these are
available), or alternatively a user defined function can be used.
The output produced should consist just of the binary digits of each number followed by a
newline.
There should be no other whitespace, radix or sign markers in the produced output, and leading
zeros should not appear in the results.
Program:
References
3. Rachel Harrison, “Abstract Data Types in Standard ML”, John Wiley & Sons.
APPENDIX
AKTU SYLLABUS