Some test cases satisfied while others not - java

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.

Related

Mailman mailbox problem using 2d arrays and for loops

This program is supposed to create a boolean array with 150 "mailboxes". The first for loop is supposed to set them all to "closed" defined by false. The second for loop should start at the second mailbox, index[1] and open every even. The third and fourth for loops are supposed to start at the third mailbox index[2] and open every third then after reaching the 150th return to the fourth for loop and open every third. The final for loop is supposed to print out which for loops are closed. I haven't been able to get it to run past line 17.
public class CS2LAB1 {
public static void main(String[] args)
{
boolean[] mailboxes = new boolean[149];
/*this function sets all mailbox doors to closed*/
for(int i = 0; i <= mailboxes.length; i++)
{
mailboxes[i] = false;
}
/*This function uses a for loop to begin at mailbox 2 and open every even mailbox
*/
for(int count = 1; count <= mailboxes.length; count = count + 2)
{
mailboxes[count] = true;
}
/*This function starts at 3 and opens every 3rd mailbox, next it goes to 4 and opens every 3rd mailbox followed by the 4th then 5th then 6th */
for(int count2 = 2; count2<=mailboxes.length; count2++)
{
for(int count3 = count2; count3 <= mailboxes.length; count3 = count3 + count2)
{
if(mailboxes[count2] = true)
{ mailboxes[count2] = false;}
else{ mailboxes[count2] = true;}
}
}
/*This function outputs all the closed doors*/
for(int print =0; mailboxes.length>=print; print++)
if(mailboxes[print] = false)
{
System.out.println("Mailbox" + print++ + "is closed" );
}
}
}
Update: I went through and changed the boolean values so that closed is now equivalent to true and open is for false off the basis that any boolean array is already set to false. I did not get the correct output instead the program outputs all even mailboxes as opened
moreover I believe I've narrowed the problem down to the nested for loop. The if statements within are never used and I do not understand why. Any ideas?
for(int count2 = 2; count2<= 149; count2++)
{
for(int count3 = 2; count3 <= 149; count3 = count3 + 3)
{
if(mailboxes[count3] = false)
{ mailboxes[count3] = true;}
else{ mailboxes[count3] = false;}
}
}
Your first for loop is probably throwing an IndexOutOfBoundException. Array's in Java are 0-indexed meaning that they start at 0 and go all the way up until Array.length - 1. Therefore in order to traverse an entire array one would iterate from for(int i = 0; i < arr.length; i++).
Your for loop is traversing from for(int i = 0; i <= mailboxes.length; i++). Meaning the last value for index i is 149 when the arrays indexes go from [0, ..., 148].

Why is the for loop running even though the condition is false

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

Find largest sequence within an arraylist

Some Background
Last week I did a problem in my textbook where It told me to generate 20 random numbers and then put brackets around successive numbers that are equal
Consider the following which my program outputs
697342(33)(666)(44)69(66)1(88)
What I need to do
The next problem was to basically get the longest sequence of these words and put brackets around them. If you have
1122345(6666)
Basically you need to put brackets around four 6's , since they occur most often.
I've finished all other problems in the chapter I am studying ( Arrays and ArrayLists), however I can't seem to figure this one out.
Here is the solution that I have made for putting brackets around successive numbers:
class Seq
{
private ArrayList<Integer> nums;
private Random randNum;
public Seq()
{
nums = new ArrayList<Integer>();
randNum = new Random();
}
public void fillArrList()
{
for (int i = 0 ; i < 20 ; i++)
{
int thisRandNum = randNum.nextInt(9)+1;
nums.add(thisRandNum);
}
}
public String toString() {
StringBuilder result = new StringBuilder();
boolean inRun = false;
for (int i = 0; i < nums.size(); i++) {
if (i < nums.size() - 1 && nums.get(i).equals(nums.get(i + 1))) {
if (!inRun) {
result.append("(");
}
result.append(nums.get(i));
inRun = true;
} else {
result.append(nums.get(i));
if (inRun) {
result.append(")");
}
inRun = false;
}
}
return result.toString();
}
}
My Thoughts
Iterate through the whole list. Make a count variable, that keeps track of how many numbers are successive of each other. I.e 22 would have a count of 2. 444 a count of 3
Next make an oldCount, which compares the current count to the oldCount. We only want to keep going if our new count is greater than oldCount
After that we need a way to get the starting index of the largest count variable, as well as the end.
Is my way of thinking correct? Because I'm having trouble updating the oldCount and count variable while comparing them, since there values constantly change. I'm not looking for the code, but rather some valuable hints.
My count is resetting like this
int startIndex, endIndex = 0;
int count = 0;
int oldCount = 0;
for(int i = 0 ; i < nums.size(); i++)
{
if(nums.get(i) == nums.get(i+1) && count >= oldCount)
{
count++;
}
oldCount = count;
}
Only after walking all elements you will know the longest subsequence.
11222333333444555
11222(333333)444555
Hence only after the loop you can insert both brackets.
So you have to maintain a local optimum: start index plus length or last index of optimum.
And then for every sequence the start index of the current sequence.
As asked:
The optimal state (sequence) and the current state are two things. One cannot in advance say that any current state is the final optimal state.
public String toString() {
// Begin with as "best" solution the empty sequence.
int startBest = 0; // Starting index
int lengthBest = 0; // Length of sequence
// Determine sequences:
int startCurrent = 0; // Starting index of most current/last sequence
for (int i = 0; i < nums.size(); i++) {
// Can we add the current num to the current sequence?
if (i == startCurrent || nums.get(i).equals(nums.get(i - 1)))) {
// We can extend the current sequence with this i:
int lengthCurrent = i - startCurrent + 1;
if (lengthCurrent > lengthBest) { // Current length better?
// New optimum:
startBest = startCurrent;
lengthBest = lengthCurrent;
}
} else {
// A different num, start here.
// As we had already a real sequence (i != 0), no need for
// checking for a new optimum with length 1.
startCurrent = i;
}
}
// Now we found the best solution.
// Create the result:
StringBuilder result = new StringBuilder();
for (int i = 0; i < nums.size(); i++) {
result.append(nums.get(i));
}
// Insert the right ')' first as its index changes by 1 after inserting '('.
result.insert(startBest + lengthBest, ")");
result.insert(startBest, "(");
return result.toString();
}
The first problem is how to find the end of a sequence, and set the correct start of the sequence.
The problem with the original algorithm is that there is handled just one sequence (one subsequence start).
The way you have suggested could work. And then, if newcount is greater than oldcount, you'll want to store an additional number in another variable - the index of the where the longest sequence begins.
Then later, you can go and insert the ( at the position of that index.
i.e. if you have 11223456666.
The biggest sequence starts with the first number 6. That is at index 7, so store that 7 in a variable.
I think you need to iterate the entire list even though the current count is lower than the oldCount, what about e.g. 111224444?
Keep 4 variables while iterating the list: highestStartIndex, highestEndIndex, highestCount and currentCount. Iterate the entire list and use currentCount to count equal neighbouring numbers. Update the highest* variables when a completed currentCount is higher than highestCount. Lastly write the numbers out with paranthesis using the *Index variables.

What is wrong with this for loop and what it prints?

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;

Round robin scheduler using a linked list

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");
}

Categories