Round robin scheduler using a linked list - java

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

Related

Some test cases satisfied while others not

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.

Averaging array values not coming out as expected, gives out of place value instead of correct one

I'm writing a program for a class at school, and when the independents couldn't help, I turn to you...
I encounter my issue when I attempt to find the average - the variables either don't add correctly or they don't divide correctly. For example, an input of [4], [2], [4], [2], will give me 7.0, when it should be 3.0. Similarly, [2], [2], [4], [4], will give 2.0.
As far as I'm aware, the rest of the code functions exactly as it should. I'm including only what should effect it, but I can post the rest if required.
public class ArrayFunctions
{
String elementNumber =
JOptionPane.showInputDialog("How many elements do you want?");
int number = Integer.parseInt(elementNumber);
//assigns how many elements are in the array, based on user input
int[] min_array = new int[number];
int recalculate = 0;
public void arrayValues()
{
for (int i = 1; i < (number + 1); i++)
{
String elementInfo =
JOptionPane.showInputDialog("Input value for element " + i);
int element = Integer.parseInt(elementInfo);
//assigns values for elements, based on user input
min_array[(i - 1)] = element;
}
System.out.println('\u000C'); /*using BlueJ, this clears the console*/
for (int i = 1; i < (number + 1); i++)
{
System.out.println(min_array[(i - 1)]);
}
//prints the values of the elements in the array
}
...
public double avg()
{
for (int i = 1; i < (min_array.length); i++)
{
recalculate = (recalculate + min_array[(i - 1)]);
}
//should add together the values of all the elements
//this may be where it stops working as intended
double array_avg = (recalculate / min_array.length);
return array_avg;
//should divide the sum of all the elements by how many elements there are
//this is the other place where it might stop working.
}
Again, I can post more code if required. Sorry about bad/lacking comments and poor structure at times, I need to get this written, because I've a due date for this. :/
for (int i = 1; i < (min_array.length); i++)
{
recalculate = (recalculate + min_array[(i - 1)]);
}
This loop is going between index 0 (1 - 1) and index min_array.length - 2 due to your boolean condition in the for loop, stating that it should go while i is LESS than the array's length, and then also subtracting it by 1 in the code.
A possible solution would be to simply go until it's less than OR equal to the size, or simply start your loop at 0 and stop the (i - 1) stuff in the average calculation.
for (int i = 0; i < min_array.length; i++)
{
recalculate += min_array[i];
}
Also, on a side note, you're basically making that same mistake in the GUI stuff as well above; I've corrected it (as well as kept your methodology of using 1-based indexing for asking the user to fill in values, rather than 0-based indexing)
for (int i = 0; i < number; i++){
String elementInfo =
JOptionPane.showInputDialog("Input value for element " + (i + 1));
int element = Integer.parseInt(elementInfo);
min_array[i] = element;
}
System.out.println('\u000C'); /*using BlueJ, this clears the console*/
for (int i = 0; i < number; i++){
System.out.println(min_array[i]);
}
I see that you're going from index 0 to index array.length - 2, instead of -1. That's the problem. I hope this helps
public double avg()
{
for (int i = 0; i < (min_array.length); i++)
{
recalculate = (recalculate + min_array[i]);
}
//should add together the values of all the elements
//this may be where it stops working as intended
double array_avg = (recalculate / min_array.length);
return array_avg;
//should divide the sum of all the elements by how many elements there are
//this is the other place where it might stop working.
}
Also always start a for loop with i=0 for counting purposes

Array gets overwritten for no apparent reason

Problem
I have written a loop in which I fill an array with Sum objects. Everything works fine, but as soon as the loop gets to the next iteration it overwrites the first index of the array.
What have I tried
I tried to see if maybe my problem resides in a different piece of code (such as my Sum class). But could not find anything that would disturb the loop.
I tried to find other variables with the same name (even in other methods, since I was desperate) and see if I maybe changed my iterator somewhere else. I couldn't find anything related to that.
I tried looking around on the internet and SO to find something related to accidentally overwriting arrays but couldn't find anything either.
Code
public Task(Object[] parameters)
{
this.number_of_sums = Integer.parseInt((String)parameters[0]);
this.variables_per_sum = Integer.parseInt((String)parameters[1]);
this.sum_parameters = new Object[this.variables_per_sum];
this.sums = new Sum[this.number_of_sums];
int z = 0;
for(int i = 0; i < this.number_of_sums; i++)
{
int x = 0;
for(int j = (2 + z); j < ((this.variables_per_sum + 2) + z); j++)
{
this.sum_parameters[x] = parameters[j];
x++;
}
this.sums[i] = new Sum(this.sum_parameters);
System.out.println("Index 0: "+sums[0]); //1st iteration: 1 + 1 //2nd iteration: 2 - 1
System.out.println("Index 1: "+sums[1]); //1st iteration: null //2nd iteration: 2 - 1
z += this.variables_per_sum;
}
}
Expectations
I'm expecting the output of 1 + 1 and 2 - 1. I am however getting the following: 2 - 1 and 2 - 1 when I'm done.
If anyone spots anything I'm doing wrong or would like to see more information or code on my side please say so. Thanks in advance.
I'm going to assume the Sum class doesn't store its sum, but instead computes it from the array it was constructed with whenever it's needed.
It looks like all the Sum objects will share the same array -- you're passing the same reference every time you construct a Sum. Furthermore, every time you loop over j you overwrite the contents of that array.
So when everything is done, all the sums are the same.
You should be able to get around this by giving each Sum a different sum_parameters:
public Task(Object[] parameters)
{
this.number_of_sums = Integer.parseInt((String)parameters[0]);
this.variables_per_sum = Integer.parseInt((String)parameters[1]);
this.sums = new Sum[this.number_of_sums];
int z = 0;
for(int i = 0; i < this.number_of_sums; i++)
{
Object[] sum_parameters = new Object[this.variables_per_sum];
int x = 0;
for(int j = (2 + z); j < ((this.variables_per_sum + 2) + z); j++)
{
sum_parameters[x] = parameters[j];
x++;
}
this.sums[i] = new Sum(sum_parameters);
System.out.println("Index 0: "+sums[0]); //1st iteration: 1 + 1 //2nd iteration: 2 - 1
System.out.println("Index 1: "+sums[1]); //1st iteration: null //2nd iteration: 2 - 1
z += this.variables_per_sum;
}
}
Each one of your Sum objects is constructed with this.sum_parameters as a parameter:
this.sums[i] = new Sum(this.sum_parameters);
When sum_parameters is modified in each iteration of the outer loop, it changes internally in the objects constructed around references to it.
You should make an internal copy of sum_parameters in each Sum object.

Remove every 3rd element in arraylist

I am trying to loop through an arraylist and gradually remove an element every 3 indices. Once it gets to the end of the arraylist I want to reset the index back to the beginning, and then loop through the arraylist again, again removing an element every 3 indices until there is only one element left in the arraylist.
The listOfWords is an array with a length of 3 that was previously filled.
int listIndex = 0;
do
{
// just to display contents of arraylist
System.out.println(listOfPlayers);
for(int wordIndex = 0; wordIndex < listOfWords.length; wordIndex++
{
System.out.print("Player");
System.out.print(listOfPlayers.get(wordIndex));
System.out.println("");
listIndex = wordIndex;
}
listOfPlayers.remove(listOfPlayers.get(listIndex));
}
while(listOfPlayers.size() > 1);
I have tried to implement for several hours yet I am still having trouble. Here's what happens to the elements of the arraylist:
1, 2, 3, 4
1, 2, 4
1, 2
Then it throws an 'index out of bounds error' exception when it checks for the third element (which no longer exists). Once it reaches the last element I want it to wrap around to the first element and continue through the array. I also want it to start where it left off and not from the beginning once it removes an element from the arraylist.
Maybe I have just missed the boat, but is this what you were after?
import java.util.ArrayList;
import java.util.Random;
public class Test {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
Random r = new Random();
//Populate array with ten random elements
for(int i = 0 ; i < 4; i++){
numbers.add(r.nextInt());
}
while(numbers.size() > 1){
for(int i = 0; i < numbers.size();i++){
if(i%3 == 0){//Every 3rd element should be true
numbers.remove(i);
}
}
}
}
}
You could move every third element to a temporary list then use List#removeAll(Collection) to remove the items when you finish each loop...until the master list was empty...
Lets back up and look at the problem algorithmically.
Start at the first item and start counting.
Go to the next item and increment your count. If there is no next item, go to the beginning.
If the count is '3', delete that item and reset count. (Or modulo.)
If there is one item left in the list, stop.
Lets write pseudocode:
function (takes a list)
remember what index in that list we're at
remember whether this is the item we want to delete.
loop until the list is size 1
increment the item we're looking at.
increment the delete count we're on
should we delete?
if so, delete!
reset delete count
are we at the end of the list?
if so, reset our index
Looking at it this way, it's fairly easy to translate this immediately into code:
public void doIt(List<String> arrayList) {
int index = 0;
int count = 0;
while(arrayList.size() != 1) {
index = index + 1;
count = count + 1; //increment count
String word = arrayList.get(index);//get next item, and do stuff with it
if (count == 3) {
//note that the [Java API][1] allows you to remove by index
arrayList.remove(index - 1);//otherwise you'll get an off-by-one error
count = 0; //reset count
}
if (index = arrayList.size()) {
index = 0; //reset index
}
}
}
So, you can see the trick is to think step by step what you're doing, and then slowly translate that into code. I think you may have been caught up on fixing your initial attempt: never be afraid to throw code out.
Try the following code. It keeps on removing every nth element in List until one element is left.
List<Integer> array = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
int nth = 3;
int step = nth - 1;
int benchmark = 0;
while (array.size() > 1) {
benchmark += step;
benchmark = benchmark > array.size() - 1 ? benchmark % array.size() : benchmark;
System.out.println(benchmark);
array.remove(array.get(benchmark));
System.out.println(array);
}
You could use a counter int k that you keep incrementing by three, like k += 3. However, before you use that counter as an index to kick out any array element, check if you already went beyond and if so, subtract the length of this array from your counter k. Also make sure, to break out of your loop once you find out the array has only one element left.
int k = -1;
int sz = list.length;
while (sz > 1)
{
k += 3;
if (k >= sz)
{
k -= sz;
}
list.remove(k);
sz --;
}
This examples shows that you already know right away how often you will evict an element, i.e. sz - 1 times.
By the way, sz % 3 has only three possible results, 0, 1, 2. With a piece of paper and a cup of coffee you can find out what the surviving element will be depending on that, without running any loop at all!
You could try using an iterator. It's late irl so don't expect too much.
public removeThirdIndex( listOfWords ) {
Iterator iterator = listOfWords.iterator
while( iterator.hasNext() ){
iterator.next();
iterator.next();
iterator.next();
iterator.remove();
}
}
#Test
public void tester(){
// JUnit test > main
List listOfWords = ... // Add a collection data structure with "words"
while( listOfWords.size() < 3 ) {
removeThirdIndex( listOfWords ); // collections are mutable ;(
}
assertTrue( listOfWords.size() < 3 );
}
I would simply set the removed to null and then skip nulls in the inner loop.
boolean continue;
do {
continue = false;
for( int i = 2; i < list.length; i += 3 ){
while( list.item(i++) == null && i < list.length );
Sout("Player " + list.item(--i) );
continue = true;
}
} while (continue);
I'd choose this over unjustified shuffling of the array.
(The i++ and --i might seem ugly and may be rewritten nicely.)

java array traversal in circular manner

I have an array which have 1 2 3 4 5 values.
array a = [ 1 , 2, 3, 4, 5]
Now i want to traverse it in circular manner.
like i want to print 2 3 4 5 1 or 3 4 5 1 2 or 5 1 2 3 4 and so on.
any algorithm on this?
Edit: I want to print all the combination in circular manner. i don't want to state starting point at its initial phase.
int start = ...
for (int i = 0; i < a.length; i++) {
System.out.println(a[(start + i) % a.length]);
}
(If you want to iterate the array backwards from start, change start + i to start - i in the array subscript expression.)
I should note that this is probably not the most efficient way of expressing the loop ... in terms of execution speed. However, the difference is small, and most likely irrelevant.
A more relevant point is whether using % in this way gives more readable code. I think it does, but maybe that's because I've seen / used this particular idiom before.
How about the following:
int start = // start position, must be in bounds
int i = start;
do {
....
i++;
if(i == a.length) i = 0;
} while(i != start);
int st = n ; // n is the starting position from where you print
for(int i = st; i < a.length; i++)
{
-- print each array[i];
}
if(st != 0)
{
for(int i = 0 ; i < st ; i++)
{
--- print each array[i];
}
}
Basically you just need to loop through the array, and change the current index if necessary (like move it to the start of the array when it meets the end)
public static void main(String[] args) {
int[] array = new int[] { 1, 2, 3, 4, 5 };
System.out.println(printCircularly(array, 4));
}
private static String printCircularly(int[] array, int startIndex) {
StringBuilder sb = new StringBuilder();
int currentIndex = startIndex;
do {
sb.append(array[currentIndex++]);
if (currentIndex > array.length - 1) {
currentIndex = 0;
}
}
while (currentIndex != startIndex);
return sb.toString();
}
In addition to Stephen C's answer
int start = ...
for (int i = 0; i < a.length; i++) {
System.out.println(a[(start - i + a.length) % a.length]);
}
Use this for reverse loop from start index. It's a little unclear, but in some cases very useful. For example: UI components like carousel.
And there's no ArrayIndexOutOfBoundsException!!!
Instead of using a for loop with indexes, which is harder to read, you can use Iterables from Google Guava as follows :
List<Integer> myList = List.of(1,2,3);
Iterator<Integer> myListIterator = Iterables.cycle(myList).iterator();
then you will only have to use myListIterator.next(). example :
System.out.println(myListIterator.next());
System.out.println(myListIterator.next());
System.out.println(myListIterator.next());
System.out.println(myListIterator.next());
This will print : 1 2 3 1

Categories