Download Efficient Message Sending with Java and more Thesis Mathematics in PDF only on Docsity!
ASSIGNMENT 2 FRONT SHEET
Qualification BTEC Level 5 HND Diploma in Computing
Unit number and title Unit 19: Data Structures and Algorithms
Submission date 27/12/2022 Date Received 1st submission
Re-submission Date Date Received 2nd submission
Student Name Le Trung Tai Student ID GBD
Class GCD0905 Assessor name Pham Thanh Son
Student declaration
I certify that the assignment submission is entirely my own work and I fully understand the consequences of plagiarism. I understand that
making a false declaration is a form of malpractice.
Student’s signature Tai
Grading grid
P4 P5 P6 P7 M4 M5 D3 D
Summative Feedback: Resubmission Feedback:
Grade: Assessor Signature: Date:
Internal Verifier’s Comments:
IV Signature:
A. Implement ADT & algorithms
I. Description of application
Scenario
I have built a program that allows to transmit a message as a string of 250 characters from source to
destination. The program uses queue and stack to buffer during string transmission. Queue will read
each character in the source string put into the Queue. Repeat until the source string passes to the
Queue. Every time the Queue is full, read each element in the Queue in turn and move it to the Stack
until the Queue is empty. Repeat until all characters in the Queue have moved onto the Stack.
Continuing the application will read from the character in the Stack string to the destination string in
turn, and iterate until the Stack string is empty. The application will print out the destination String and
some information of the target string such as the number of characters, letters, and time to send the
message.
Flowchart of application:
Figure 1 Flowchart of application
First, the program asks the user to enter a message (source string). then check if the source string is valid
or not, if not, it will throw an error. The program then catches the errors that were thrown and displays
the reason for the error and asks the user to re-enter it. The error is thrown in a while loop until there
are no more errors from input data, the loop ends and the next step is taken. Next, the real time will be
assigned to a start variable and run start sendingMessage() method when the sending is completed. The
real time will now be assigned to the finish variable. Finally, if the number of characters sent through the
target string and the length of the first string match, the message is successfully sent and the information
of the message is displayed, otherwise, the message sent failed is displayed.
sendMessage method
public int count; public int letter = 1 ; public String destination = ""; public void sendMessage(String mess) { System. out .println("Length of the message: " + mess.length() + " character."); while (count < mess.length()) { while ( sender .size() < mess.length()) { if (count == mess.length()) { break; } sender .offer(mess.charAt(count)); if (mess.charAt(count) == ' ' || mess.charAt(count) == '\t' || mess.charAt(count) == '\n') letter++; count++; } while ( sender .size() != 0 ) { receiver .push( sender .poll()); } while ( receiver .size() != 0 ) { destination = receiver .pop() + destination; } } } }
Main
import java.util.*; public class Main { public static final String ANSI_RESET = "\033[0m"; public static final String GREEN_UNDERLINED = "\033[4;32m"; public static void main(String[] args) { Message message = new Message(); Scanner scanner = new Scanner(System. in ); System. out .print("Please input a message:"); String mess = scanner.nextLine(); boolean option = true; while (option) { try { if (mess.equals("")) { throw new IllegalStateException(); } else if (mess.length() > 250 ) { throw new IndexOutOfBoundsException(); } option = false; } catch (IllegalStateException e) { System. out .println("Message must not mull!!!!"); System. out .print("Please repeat input a message:"); mess = scanner.nextLine(); continue; } catch (IndexOutOfBoundsException e) {
System. out .println("This message is over 250 characters"); System. out .print("Please repeat input a message:"); mess = scanner.nextLine(); continue; } } //Use a programming language (Java) to write a program that can send a text messege (maximum 250 characters) from source to destination. // //Use a programming language (Java) to write a program that can send a text messege (maximum 250 characters) from source to destination. Use a programming language (Java) to write a program that can send a text messege (maximum 250 characters) from source to destination Use a programming language (Java) to write a program that can send a text messege (maximum 250 characters) from source to destination.. long start = System. currentTimeMillis (); message.sendMessage(mess); long finish = System. currentTimeMillis (); double time = finish - start; if (message.count == mess.length()) { System. out .println("The message is sent successfully."); System. out .println("The received message: " + GREEN_UNDERLINED + message.destination + ANSI_RESET ); System. out .println("The received message has " + GREEN_UNDERLINED + message.letter + ANSI_RESET + " letters."); System. out .println("The received message has " + GREEN_UNDERLINED + message.count + ANSI_RESET + " character."); System. out .println("Time : " + GREEN_UNDERLINED + time + ANSI_RESET + " ms"); } else System. out .println("The messege is not sent successfully."); } } II. ADT
- Implement
Implementation of the data structure
I used ADT Queues and Stacks to get each letter of the source string to send to the destination string.
Queues can hold large amounts of data that can be efficiently managed easily. Operations such as
insertion and deletion can be performed easily because it follows the first-in, first-out rule. Queues are
useful when a particular service is used by many consumers. Queues are fast for communication
between data processes. Queues can be used in the implementation of other data structures. A Stack
helps to manage the data in the ‘Last in First out’ method. When the variable is not used outside the
function in any program, the Stack can be used. It allows you to control and handle memory allocation
and deallocation. It helps to automatically clean up the objects.
} catch (IllegalStateException e) { Scanner scanner = new Scanner(System. in ); System. out .println("Message must not mull!!!!"); System. out .print("Please repeat input a message:"); mess = scanner.nextLine(); continue; } catch (IndexOutOfBoundsException e) { Scanner scanner = new Scanner(System. in ); System. out .println("This message is over 250 characters"); System. out .print("Please repeat input a message:"); mess = scanner.nextLine(); continue; } }
Enter null data
Enter the data over 250 characters:
The use of an external while loop ensures that the user always enters the correct input before the
message can be sent.
- Test Table 1 Test
Test case Input data
Expected
output
Actual output Result
Enter an
empty
data
Enter “” The
applicatio
n will
notify the
message
as empty
and ask
the user
to re-
Pas
s
enter it
Enter a
data less
than 250
characte
rs
Enter
“//Use a
programmi
ng language
(Java) to
write a
program
that can
send a text
message
(maximum
characters)
from source
to
destination.
The
applicatio
n will print
out the
received
message
and
informatio
n about
that
message
Pas
s
Enter a
data
over 250
characte
rs
Enter
“//Use a
programmi
ng language
(Java) to
write a
program
that can
send a text
messege
(maximum
characters)
from source
to
destination.
Use a
programmi
ng language
(Java) to
write a
program
that can
send a text
messege
(maximum
The
applicatio
n notices
that the
message
has
exceeded
the
specified
number of
characters
and asks
the user
to re-
enter it.
Pas
s
Enter the valid data
B. Analysis
I. Big O
We often hear the performance of an algorithm described using Big O Notation.
The study of the performance of algorithms – or algorithmic complexity – falls into the field of algorithm
analysis. Algorithm analysis answers the question of how many resources, such as disk space or time, an
algorithm consumes.
We'll be looking at time as a resource. Typically, the less time an algorithm takes to complete, the better.
Constant Time Algorithms – O(1)
How does this input size of an algorithm affect its running time? Key to understanding Big O is
understanding the rates at which things can grow. The rate in question here is time taken per input
size.
Consider this simple piece of code:
int n = 1000 ; System. out .println("Hey - your input is: " + n);
Clearly, it doesn't matter what n is, above. This piece of code takes a constant amount of time to run.
It's not dependent on the size of n.
Similarly:
int n = 1000 ; System. out .println("Hey - your input is: "+n); System. out .println("Hmm.. I'm doing more stuff with: "+n); System. out .println("And more: "+n);
The above example is also constant time. Even if it takes 3 times as long to run, it doesn't depend on
the size of the input, n. We denote constant time algorithms as follows: O(1). Note that O(2), O(3) or
even O(1000) would mean the same thing.
We don't care about exactly how long it takes to run, only that it takes constant time.
Logarithmic Time Algorithms – O(log n)
Constant time algorithms are (asymptotically) the quickest. Logarithmic time is the next quickest.
Unfortunately, they're a bit trickier to imagine.
One common example of a logarithmic time algorithm is the binary search algorithm. To see how to
implement binary search in Java, click here.
What is important here is that the running time grows in proportion to the logarithm of the input (in
this case, log to the base 2):
for (int i = 1 ; i < n; i = i * 2 ){ System. out .println("Hey - I'm busy looking at: " + i); }
If n is 8, the output will be the following:
n log n is the next class of algorithms. The running time grows in proportion to n log n of the input:
for (int i = 1 ; i <= n; i++){ for(int j = 1 ; j < n; j = j * 2 ) { System. out .println("Hey - I'm busy looking at: " + i + " and " + j); } }
For example, if the n is 8, then this algorithm will run 8 * log(8) = 8 * 3 = 24 times. Whether we have
strict inequality or not in the for loop is irrelevant for the sake of a Big O Notation.
Polynomial Time Algorithms – O(np)
Next up we've got polynomial time algorithms. These algorithms are even slower than n log n
algorithms.
The term polynomial is a general term which contains quadratic (n2), cubic (n3), quartic (n4), etc.
functions. What's important to know is that O(n2) is faster than O(n3) which is faster than O(n4), etc.
Let's have a look at a simple example of a quadratic time algorithm:
for (int i = 1 ; i <= n; i++) { for(int j = 1 ; j <= n; j++) { System. out .println("Hey - I'm busy looking at: " + i + " and " + j); } }
This algorithm will run 82 = 64 times. Note, if we were to nest another for loop, this would become
an O(n3) algorithm.
Exponential Time Algorithms – O(kn)
These algorithms grow in proportion to some factor exponentiated by the input size.
For example, O(2n) algorithms double with every additional input. So, if n = 2, these algorithms will
run four times; if n = 3, they will run eight times (kind of like the opposite of logarithmic time
algorithms).
O(3n) algorithms triple with every additional input, O(kn) algorithms will get k times bigger with
every additional input.
Let's have a look at a simple example of an O(2n) time algorithm:
for (int i = 1 ; i <= Math. pow ( 2 , n); i++){ System. out .println("Hey - I'm busy looking at: " + i); }
This algorithm will run 28 = 256 times.
Factorial Time Algorithms – O(n!)
In most cases, this is pretty much as bad as it'll get. This class of algorithms has a run time
proportional to the factorial of the input size.
A classic example of this is solving the traveling salesman problem using a brute-force approach to
solve it.
An explanation of the solution to the traveling salesman problem is beyond the scope of this article.
Instead, let's look at a simple O(n!) algorithm, as in the previous sections:
for (int i = 1 ; i <= factorial(n); i++){ System. out .println("Hey - I'm busy looking at: " + i); }
where factorial(n) simply calculates n!. If n is 8, this algorithm will run 8! = 40320 times.
II. Analyze performances
- Time Complexity
The time complexity of an algorithm quantifies the amount of time taken by an algorithm to run as a
function of the length of the input. Note that the time to run is a function of the length of the input and
not the actual execution time of the machine on which the algorithm is running on.
In order to calculate time complexity on an algorithm, it is assumed that a constant time c is taken to
execute one operation, and then the total operations for an input length on N are calculated. Consider
an example to understand the process of calculation: Suppose a problem is to find whether a pair (X, Y)
exists in an array, A of N elements whose sum is Z. The simplest idea is to consider every pair and check if
it satisfies the given condition or not.
- Space Complexity
The space complexity of an algorithm quantifies the amount of space taken by an algorithm to run as a
function of the length of the input. Consider an example: Suppose a problem to find the frequency of
array elements.
- Example
In my application, I have used java.lang.System.currentTimeMillis() method to calculate the sending time
of messages. from there I understand the complexity of the function I create and the time it takes for the
function to work.
Comparation:
Table 2 Compare time complexity
Test Characters Time
Test 1 136 6
Test 2 10 5
Test 3 1 5
Test 4 244 6
Conclusion of time complexity:
The longer the message length depend on my algorithms and program. More character in message,
the program spent more time to run loop then the time complexity is long.
References
There are no sources in the current document.