I have to write a program that compares the running time of two different lists, one being array based and one being a linked list. I have to run it twenty times at twenty different lengths, so I made a for loop to do this for me, it is supposed to run twenty times, but only printed out one thing, and then it made my computer very slow, and it said the process was still running on my IDE for a while. Heres the code, ask if you need more but this should be sufficient. I wanna know why the for loop only prints one thing and after that it says still running.
public class Foo4 {
public static void main(String[] args) {
int max = Integer.MAX_VALUE;
int diff = max / 20;
int holder = 1;
long test1time;
long test2time;
StopWatch timer = new StopWatch();
int t;
for (t = 0; t < 20; t++) {
AList test1 = new AList();
Slist test2 = new Slist();
for (int j = 0; j < holder; j++) {
test1.addFirst("the");
test2.addFirst("thee");
}
timer.reset();
timer.start();
test1.getLast();
timer.stop();
test1time = timer.getElapsedTime();
timer.reset();
timer.start();
test2.getLast();
timer.stop();
test2time = timer.getElapsedTime();
System.out.println(test1time + " : " + test2time);
holder += diff;
}
}
}
int max = Integer.MAX_VALUE;
int diff = max / 20;
int holder = 1;
...
for (t = 0; t < 20; t++) {
AList test1 = new AList();
Slist test2 = new Slist();
for (int j = 0; j < holder; j++) {
test1.addFirst("the");
test2.addFirst("thee");
}
...
holder+=diff
}
You do realize that in your second iteration (when t == 1 you are adding over a 100 million Strings to your lists? This could take some time, not to mention that your program might hang/fail due to memory limits.
Okay i tried to run your code and i got the same output as said 0:0 every time. I dont know you are using which IDE. But I used eclipse and then I debugged your code. I set a breakpoint at line timer.reset() and then waited for some seconds and then moved to next line by pressing F6 and then moved to next step by having interval of 2 to 3 seconds for each F6 press. Then at the last it printed some value like: 2711 : 3559.
Now problem is that your code is executing so fast that it get start and end time same but when you debug it and check the value then it would show some result other than zero.
timer.reset();//set a breakpoint over here. When debugger comes on this line press F6
timer.start();//Wait for 3 seconds over here and then press F6.
test1.getLast();//Now at each below line wait for 3 seconds and then press F6
timer.stop();
test1time = timer.getElapsedTime();
timer.reset();
timer.start();
test2.getLast();
timer.stop();
test2time = timer.getElapsedTime();
System.out.println(test1time + " : " + test2time);
holder += diff;
Related
My program is supposed to be passed 2 array-lists, arrivals and duration, and should return the number of events that can basically take place without overlap. However, a-lot of testcases are not being passed successfully. Below is shown an expected output:
arrivals = [1,3,3,5,7]
duration = [2,2,1,2,1]
The first person arrives at 1, presents for 2 hours, then leaves. 2 people arrive at 3 but only one is allowed to present for 2 or 1 hours. The next person arrives at 5, presents for 2 hours. The final person arrives at 7, and presents for 1 hour. The answer output should be 4 as 4 people are able to present. Below is my current program:
class Result {
public static int maxEvents(List<Integer> arrival,List<Integer> duration) {
int counter = 0;
if (arrival.size() == 0) {
counter = 0;
} else {
for (int i = 0; i < arrival.size() - 1; i++) {
if (arrival.get(i) + duration.get(i) <= arrival.get(i + 1)) {
counter++;
} else if (arrival.get(i).equals(arrival.get(i + 1))) {
counter++;
i++;
} else if (arrival.get(arrival.size()-1).equals(arrival.get(i))) {
counter++;
}
}
}
return counter;
}
}
This program works for test cases such as:
arrival = [1,1,1,1,4]
duration = [10,3,4,6,2]
Output: 2
But fails for cases such as below:
arrival = [1,3,5]
duration = [2,2,2]
Expected:3
Mine:2
or:
arrival = [1]
duration = [5]
Expected = 1
Mine = 0
I can't seem to be able to see what the issue could be.
A user in the comments submitted his logic on the problem and below is the implantation:
class Result {
public static int maxEvents(List<Integer> arrival,List<Integer> duration) {
int counter = 0;
if (arrival.size() == 0) {
return 0;
} else {
counter = 1;
ArrayList <Integer> timeseq = new ArrayList<Integer>();
for (int i = 0;i< arrival.size(); i++) {
timeseq.add(arrival.get(i));
timeseq.add(arrival.get(i)+duration.get(i));
}
for (int j =1; j<= timeseq.size()-2; j+=2) {
if(timeseq.get(j) <= timeseq.get(j+1)) {
counter++;
}
}
return counter;
}
}
}
This code fails the test case
arrival = (1,1,1,1,4) duration = (10,3,6,4.2)
Expected = 2
Mine = 1
Maybe you are confusing .size() with .length(). These are different methods and they have different returns. Considering #Nexevis answer, maybe remove the "-1" since you're calling for the size of the array.
I would normally do it differently. Below is a brief about the logic I would implement. Note that its a pseudo code:
if arrival size = 0, return 0;
else counter = 1
timesequencearray = [] <- Array to hold time sequence. Should be double the size of arrival array
//Prepare an array which contains the time sequence based on the events
for(i=0 to arrival.size()){
timesequencearray.push(arrival.get(i));
timesequencearray.push(arrival.get(i)+distance.get(i));
}
for (i=1 to timesequencearray.size()-2; i= i+2){
if(timesequencearray[i]<=timesequencearray[i+1]:
counter++;
}
return counter;
Below is the working of the code. Say your input is
[1,2,3]
[1,1,2]
timesequencearray will be [1,2,2,3,3,5] and we will check if "2" on the index 1 is less than or equal to "2" on index 2 (this means no overlap). So increase the counter. Counter is kept "1" in the beginning to imply that the last arrival is never overlapping. Lets take your failed case:
arrival = [1,3,5]
duration = [2,2,2]
timesequencearray - [1,3,3,5,5,7]
3<=3 -> counter = 2
5<=5 -> counter = 3
Return counter = 3
Another one:
arrival = [1]
duration = [5]
timesequencearray = [1,6]
No loop is executed. Counter = 1 is returned as the size of arrival is greater than zero.
I have been trying to write a code trace for this program. after many attempts on paper I thought I understood it but now I have stumbled again.
In the for loop i=counter ,because i=0 and the counter=0 so since it has to be less than counter how is this code even running?
I have included my incomplete code trace below.
The aim of the program is to print 50 unique random numbers between 1 and 999, in 10 rows of 5. The program works perfectly.I just want to figure out how its working with the help of a code trace. I know this might be a simple problem to you, but I am struggling with it. Could you please help me, thank you.
import java.util.Random;
public class Random50 {
public static void main(String[] args) {
int numbersNeeded = 50;
int[] randomNumbers = new int[numbersNeeded];
int counter = 0;
Random randomGenerator = new Random();
int max = 999;
int min = 1;
while (counter < numbersNeeded) {
int generated = min + randomGenerator.nextInt(max);
boolean found = false;
for (int i = 0; i < counter && !found; i++) {
if (randomNumbers[i] == generated) {
found = true;
}
}
if (!found) {
randomNumbers[counter++] = generated;
}
}
for (int i = 0; i < counter; i++) {
System.out.printf("%03d ",randomNumbers[i] );
if (i > 0 && (i+1) % 5 == 0) {
System.out.println("");
}
}
}
}
This line is the reason why:
randomNumbers[counter++] = generated;
By using counter++, you're using the ++ postfix increment operator, which evaluates to the value of counter, but then increments it by 1 after the evaluation. The equivalent code without use of this operator would look something like this:
randomNumbers[counter] = generated;
counter = counter + 1;
So on the first iteration where this line is executed, randomNumbers[0] is updated, but then counter gets set to 1 (because 0 + 1 = 1). On the second iteration, randomNumbers[1] is updated, then counter gets updated to 2 (because 1 + 1 = 2)...and so forth.
You can find more information about arithmetic operators here: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op1.html
I'm trying to write a very simple OS simulator and I am stuck getting my round robin algorithm to work. Basically what i am trying to do is create a circular linked list that stores the burst values of the process. Right now I am getting a null pointer exception. It has been awhile since I've used a linked list so bear with my code:
public static void RR3(int numProcess, int[] cpuBurst, int[] arrivalTime){
int quantum = 3,time = 0, temp;
int completionTime = 0;
LinkedList <Integer>process = new LinkedList();
for (int i = 0; i < numProcess; i++) {
process.add(i, cpuBurst[i]);
}
while (process.isEmpty() != true){
for (int j = 0; j < quantum; j++) {
System.out.println(process.getFirst());
if(process.peek() == 0 ){
completionTime = completionTime + time;
process.remove();
}
else{
temp = process.pop();
process.push(temp - 1);
time++;
}
}
process.addLast(process.getFirst());
process.removeFirst();
}
double act = (double) completionTime/numProcess;
System.out.println("-----------------RR3-----------------");
System.out.println(" Act = " + act + "ms");
}
Am I using linked list right? Any help is appreciated.
edit:
I put in System.out.println(process.getFirst()); after the first for loop to get some sort of stack trace and this is my output:
6
5
4
4
3
2
10
9
8
7
6
5
3
2
1
7
6
5
Exception in thread "main" java.util.NoSuchElementException
4
3
2
1
4
3
1
at java.util.LinkedList.getFirst(LinkedList.java:242)
2
1
at OsSimulator.RR3(OsSimulator.java:61)
at OsSimulator.main(OsSimulator.java:79)
Java Result: 1
my burst time i entered were 6,4,10,7 so it looks like it is on the right track but i get the error with this line
process.addLast(process.getFirst());
and now its a no such element exception.
I don't have access to eclipse to check this at the moment, but are you sure you aren't trying to call process.getFirst() after the last element is removed from the list inside of the for loop?
I would suggest putting a breakpoint before that line and then running the code in debug mode to verify.
It means what it says. There is no first element, so the process list is empty.
This must be occurring because processing the quanta in the j loop has made the list empty.
If you add trace code to print out the whole list during each iteration rather than just the first element, it will become pretty obvious what's happening.
Debugging is always about making yourself see what is really going on instead of guessing at an opaque puzzle. The main tool you have to visualize what's really going on (when your brain fails you) is the machine itself. Add trace code or become expert with a debugger. The discipline is to force yourself to see truth.
Before calling process.getFirst() make sure List is not empty
public static void RR3(int numProcess, int[] cpuBurst, int[] arrivalTime) {
int quantum = 3, time = 0, temp;
int completionTime = 0;
LinkedList<Integer> process = new LinkedList<Integer>();
for (int i = 0; i < numProcess; i++) {
process.add(i, cpuBurst[i]);
}
while (process.isEmpty() != true) {
for (int j = 0; j < quantum; j++) {
if (process.size() == 0)
break;
System.out.println("Process: " + process.getFirst());
if (process.peek() == 0) {
completionTime = completionTime + time;
process.remove();
} else {
temp = process.pop();
process.push(temp - 1);
time++;
}
}
if (process.size() == 0)
break;
process.addLast(process.getFirst());
process.removeFirst();
}
double act = (double) completionTime / numProcess;
System.out.println("-----------------RR3-----------------");
System.out.println(" Act = " + act + "ms");
}
trying to add an item at random time intervals.
I was thinking I need to start when i is equal to arriveTime, once that is met I need to create a new random arrival and add i (otherwise it will not happen again as i is already past arrival. So I add another if, once that is met create new arrival time and add i again. pseudocode seems to make sense, code not so much, any help is appreciated.
ArrayList<Integer> q = new ArrayList<Integer>();
Random r = new Random();
int arrivals = 0;
for (int i = 1; i <= 720; i++) {
int arrive = r.nextInt(4)+1;
if (i == arrive) {
q.add(i);
arrivals ++;
arrive = r.nextInt(4)+1+i;
}
else if (i == arrive) {
q.add(i);
arrivals ++;
arrive = r.nextInt(4)+1+i;
}
}
sorry, arriveTime should be just arrive. ArriveTime does not exist.
edit: To expand from comments. 'i' represents time and I dont want to add a random integer to the list. Rather add the same object at random intervals of 'i'. I was adding the value of 'i' to the list to see at what times the algorithm was adding an item because it didnt seem to be working. Results vary, but it seems to be always single digits that get added to list. Also made updates to code.
Your algorithm is lacking a pause - ie a call to Thread.sleep(), otherwise it will spin.
I'd be trying to keep it simple, matching your code to the problem: ie wait a random time between adding to the queue, simply:
ArrayList<Integer> q = new ArrayList<Integer>();
Random r = new Random();
for (int i = 1; i <= 720; i++) { // loop as many times as you want
Thread.sleep(r.nextLong() % 1000); // wait a random time up to 1 second
q.add(r.nextInt()); // add a random number to the queue
}
You can adjust the numbers to suit your requirements.
you should be comparing time to 1-4 in your if statements, then adding that value to i (as i is representative of time) Something like this
ArrayList<Integer> q = new ArrayList<Integer>();
Random r = new Random();
int arrivals = 0;
for (int i = 1; i < 100 ; i++) { //loop as many times as you want.
int time = r.nextInt(4)+1; //choose a random time of arrival, 1-4
//now compare time to your random time intervals (1-4, not i
//if it matches add that value to i
if (time == 1) {
//add your object to the list
i += 1;
}
else if (time == 2) {
//add your object to the list
i += 2;
}
else if (time == 3) {
//add your object to the list
i += 3;
}
else if (time == 4) {
//add your object to the list
i += 4;
}
}
The code as posted doesn't make much sense.
It depends on an undeclared variable.
The statements that update arrive have no effect ... because it it local to the loop.
Assume i have the following code, there are three for loop to do something. Would it run fast if i change the most outer for loop to while loop? thanks~~
int length = 200;
int test = 0;
int[] input = new int[10];
for(int i = 1; i <= length; i++) {
for (int j = 0; j <=length - i; j++) {
for (int k = 0; k < length - 1; k++) {
test = test + input[j + k];
}
}
}
No, changing the type of loop wouldn't matter.
The only thing that can make it faster would be to have less nesting of loops, and looping over less values.
The only difference between a for loop and a while loop is the syntax for defining them. There is no performance difference at all.
int i = 0;
while (i < 20){
// do stuff
i++;
}
Is the same as:
for (int i = 0; i < 20; i++){
// do Stuff
}
(Actually the for-loop is a little better because the i will be out of scope after the loop while the i will stick around in the while loop case.)
A for loop is just a syntactically prettier way of looping.
This kind of micro-optimization is pointless.
A while-loop won’t be faster.
The loop structure is not your bottleneck.
Optimize your algorithm first.
Better yet, don’t optimize first. Only optimize after you have found out that you really have a bottleneck in your algorithm that is not I/O-dependant.
Someone suggested to test while vs for loops, so I created some code to test whether while loops or for loops were faster; on average, over 100,000 tests, while loop was faster ~95% of the time. I may have coded it incorrectly, I'm quite new to coding, also considering if I only ran 10,000 loops they ended up being quite even in run duration.
edit I didn't shift all the array values when I went to test for more trials. Fixed it so that it's easier to change how many trials you run.
import java.util.Arrays;
class WhilevsForLoops {
public static void main(String[] args) {
final int trials = 100; //change number of trials
final int trialsrun = trials - 1;
boolean[] fscount = new boolean[trials]; //faster / slower boolean
int p = 0; // while counter variable for for/while timers
while (p <= trialsrun) {
long[] forloop = new long[trials];
long[] whileloop = new long[trials];
long systimeaverage;
long systimenow = System.nanoTime();
long systimethen = System.nanoTime();
System.out.println("For loop time array : ");
for (int counter=0;counter <= trialsrun; counter++) {
systimenow = System.nanoTime();
System.out.print(" #" + counter + " #");
systimethen = System.nanoTime();
systimeaverage = (systimethen - systimenow);
System.out.print( systimeaverage + "ns |");
forloop[counter] = systimeaverage;
}
int count = 0;
System.out.println(" ");
System.out.println("While loop time array: ");
while (count <= trialsrun) {
systimenow = System.nanoTime();
System.out.print(" #" + count + " #");
systimethen = System.nanoTime();
systimeaverage = (systimethen - systimenow);
System.out.print( systimeaverage + "ns |");
whileloop[count] = systimeaverage;
count++;
}
System.out.println("===============================================");
int sum = 0;
for (int i = 0; i <= trialsrun; i++) {
sum += forloop[i];
}
System.out.println("for loop time average: " + (sum / trials) + "ns");
int sum1 = 0;
for (int i = 0; i <= trialsrun; i++) {
sum1 += whileloop[i];
}
System.out.println("while loop time average: " + (sum1 / trials) + "ns");
int longer = 0;
int shorter = 0;
int gap = 0;
sum = sum / trials;
sum1 = sum1 / trials;
if (sum1 > sum) {
longer = sum1;
shorter = sum;
}
else {
longer = sum;
shorter = sum1;
}
String longa;
if (sum1 > sum) {
longa = "~while loop~";
}
else {
longa = "~for loop~";
}
gap = longer - shorter;
System.out.println("The " + longa + " is the slower loop by: " + gap + "ns");
if (sum1 > sum) {
fscount[p] = true; }
else {
fscount[p] = false;
}
p++;
}
int forloopfc=0;
int whileloopfc=0;
System.out.println(Arrays.toString(fscount));
for(int k=0; k <= trialsrun; k++) {
if (fscount[k] == true) {
forloopfc++; }
else {
whileloopfc++;}
}
System.out.println("--------------------------------------------------");
System.out.println("The FOR loop was faster: " + forloopfc + " times.");
System.out.println("The WHILE loop was faster: " + whileloopfc + " times.");
}
}
you cant optimize it by changing it to while.
you can just increment speed very very very very little by changing the line
for (int k = 0; k < length - 1; k++) {
by
for (int k = 0; k < lengthMinusOne; k++) {
where lengthMinusOne is calculated before
this subtraction is just calculating almost (200x201/2) x (200-1) times and it is very little number for computer :)
here's a helpful link to an article on the matter
according to it, the While and For are almost twice as faster but both are the same.
BUT this article was written in 2009 and so i tried it on my machine and here are the results:
using java 1.7: the Iterator was about 20%-30% faster than For and While (which were still the same)
using java 1.6: the Iterator was about 5% faster than For and While (which were still the same)
so i guess the best thing is to just time it on your own version and machine and conclude from that
Even if the hypothesis of the while loop being faster than the for loop were true (and it's not), the loops you'd had to change/optimize wouldn't be the outer ones but the inner ones, because those are executed more times.
The difference between for and while is semantic :
In a while loop, you will loop as long as the condition is true, which can vary a lot, because you might, in your loop, modify variables using in evluating the while condition.
Usually, in a for loop, you loop N time. This N can be variable, but doesn't move until the end of your N loop, as usually developpers doesn't modify variables evaluated in the loop condition.
It is a way to help other to understand your code. You are not obliged not to modify for loop variables, but it is a common (and good) practice.
No, you're still looping the exact same number of times. Wouldn't matter at all.
Look at your algorithm! Do you know beforehand which values from your array are added more than one time?
If you know that you could reduce the number of loops and that would result in better performance.
There would be no performance difference. Try it out!
The JVM and further, the compiler, would make both loops into something like
label:
;code inside your for loop.
LOOP label
It would only matter if you are using multi-thread or multiple processor programming. Then it would also depends on how you assign the loops to the various processors/threads.
No, it's not going to make a big difference, the only thing is that if your nesting loops you might want to consider switching up for example for organizational purposes, you may want to use while loop in the outer and have for statements inside it. This wouldn't affect the performance but it would just make your code look cleaner/organized
You can calculate it yourself.
int length = 200;
int test = 0;
int[] input = new int[10];
long startTime = new Date().getTime();
for(int i = 1; i <= length; i++) {
for (int j = 0; j <=length - i; j++) {
for (int k = 0; k < length - 1; k++) {
test = test + input[j + k];
}
}
}
long endTime = new Date().getTime();
long difference = endTime - startTime;
System.out.println("For - Elapsed time in milliseconds: " + difference);
test = 0;
input = new int[10];
int i = 0, j = 0, k = 0;
startTime = new Date().getTime();
while(i < length) {
while(j <= length - i ) {
while(k < length - 1) {
test = test + input[j + k];
k++;
}
j++;
}
i++;
}
endTime = new Date().getTime();
difference = endTime - startTime;
System.out.println("While - Elapsed time in milliseconds: " + difference);
The for loop and while loop both are iteration statements, but both have their distinct feature.
Syntax
While Loop
//setup counter variable
int counter = 0;
while ( condition) {
//instructions
//update counter variable
counter++; //--> counter = counter + 1;
}
For Loop
for (initialization; condition; iteration){
//body of for loop
}
The for loop does have all its declaration (initialization, condition, iteration) at the top of the body of the loop. Adversely, in a while loop only initialization and condition are at the top of the body of the loop and iteration may be written anywhere in the body of the loop.
Key Differences Between for and while loop
In the for loop, initialization, condition checking, and increment or decrement of iteration variable are done explicitly in the syntax of a loop only. As against, in the While loop, we can only initialize and check conditions in the syntax of the loop.
When we are aware of the number of iterations that have to occur in the execution of a loop, then we use for loop. On the other hand, if we are not aware of the number of iteration that has to occur in a loop, then we use a while loop.
If you fail to put the condition statement in the for loop, it will lead to an infinite iteration of a loop. In contrast, if you fail to put a condition statement in the while loop it will lead to a compilation error.
The initialization statement in the syntax of the for loop executes only once at the start of the loop. Conversely, if the while loop is carrying an initialization statement in its syntax, then the initialization statement in the while loop will execute each time the loop iterates.
The iteration statement in the for loop will execute after the body for loop executes. On the contrary, the iteration statement can be written anywhere in the body of the while loop so, there can be some statements that execute after the execution of the iteration statement in the body of the `while loop.
Based on this: https://jsperf.com/loops-analyze (not created by me) the while loop is 22% slower than a for loop in general. At least in Javascript it is.