I have a loop that should stop executing only once both jobStatus(0) and jobStatus(1) returns 2
while(c.getStatus(0) != 2 && c.getStatus(1) != 2){
c.update();
}
System.out.println("Person id0: " + c.getStatus(0));
System.out.println("Person id1: " + c.getStatus(1));
Here is the update() method.
public void update() {
for(Map.Entry<Integer, Person> person : allPeople.entrySet()){ //check all jobs
Person person = person.getValue();
if(person.getStatus() != person.WORKING){
continue;
}
Date currentTime = new Date();
long startTime = person.getStartTime().getTime();
long requiredTime = person.getRequiredTime();
long finishTime = startTime + requiredTime;
if(finishTime <= currentTime.time()){
person.finished();
getMachineById(getAllocatedMachineId()).changeMachineStatus();
}
}
}
Output after loop ended:
Person id0: 2
Person id1: 1
Not sure why it's behaving the way it is, the long variables are correct (printing the variable reveals the current time increments correctly until it overtakes finish time - but then it exits the loop and doesn't continue for getStatus(1).
You got the condition wrong. It stops when one of c.getJobStatus(0) and c.getJobStatus(1) is two.
It should be:
while(c.getJobStatus(0) != 2 || c.getJobStatus(1) != 2){
c.updateJobs();
}
As long as one of them is not two, the loop should continue.
The loop entry condition is wrong.
You could have avoided the bug by translating what you want to do in code leading to a more natural:
while(!(c.getJobStatus(0) == 2 && c.getJobStatus(1) == 2)){ //while both are not 2
c.updateJobs();
}
Related
I'll preface by saying that this is a project for a class. The logic of the code all functions and, as it stands, currently outputs close to the correct solution (I stopped working on the output when I learned that I had used the wrong interface). The problem is, the requirements very explicitly state we must use comparator. Being new to Java, I used Comparable, not realizing there was an explicit difference. This is an algorithms class in Java, my background is in Python and there are definitely some differences that are going over my head - I'm sure that will be apparent in my code.
I've sort of come to understand the difference between the two, but if you asked me to ELI5, I don't think I could. Please help me understand how exactly to implement Comparator as opposed to Comparable. I get that I need a separate class but then I'm not exactly sure how that should be formatted and what to do with it once I have it.
I'm including below the code of the working solution that implements comparable. Any guidance would be extremely appreciated. TIA.
EDIT: Also, by all means, anything else in particular about my code that stands out as going against Java conventions, I'm happy to hear about.
import java.util.PriorityQueue;
import java.util.ArrayList;
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class ProcessScheduling {
public static class Process implements Comparable<Process> {
private Integer priority;
private int id;
private int arrivalTime;
private int duration;
public Process(int ID, Integer Priority, int Duration, int ArrivalTime) {
this.id = ID;
this.priority = Priority;
this.duration = Duration;
this.arrivalTime = ArrivalTime;
}
public Integer getPriority() {return priority;}
public int getId() {return id;}
public int getArrivalTime() {return arrivalTime;}
public int getDuration() {return duration;}
public void setPriority(Integer priority) {this.priority = priority;}
#Override
public String toString() {
return "Process ID = " + getId()
+ "\n\tPriority = " + getPriority()
+ "\n\tArrival = " + getArrivalTime()
+ "\n\tDuration = " + getDuration();
}
#Override
public int compareTo(Process P) {
if (this.getPriority() > P.getPriority()) {return 1;}
else if (this.getPriority() < P.getPriority()) {return -1;}
return 0;
}
}
public static void main(String[] args) {
// Create ArrayList D to store new processes
ArrayList<Process> D = new ArrayList<Process>();
// Read the input file
try {
File f = new File("process_scheduling_input.txt");
Scanner reader = new Scanner(f);
while (reader.hasNextLine()) {
// Create new Processes and add them to ArrayList D
String[] data = reader.nextLine().split(" ");
Process newProcess = new Process( Integer.valueOf(data[0]),
Integer.parseInt(data[1]),
Integer.parseInt(data[2]),
Integer.parseInt(data[3])
);
D.add(newProcess);
}
reader.close();
} catch (FileNotFoundException e) {
System.out.println("An error occured. File does not exist.");
e.printStackTrace();
}
// Print all processes
for (int i = 0; i < D.size(); i++) {
Process current = D.get(i);
System.out.print("Id = " + current.getId());
System.out.print(", priority = " + current.getPriority());
System.out.print(", duration = " + current.getDuration());
System.out.println(", arrival time = " + current.getArrivalTime());
}
// Instantiate priorityQueue and some parameters
int currentTime = 10;
boolean running = false;
int maxWaitTime = 30;
float totalWaitTime = 0;
int currentEndTime = 0;
Process current = null;
PriorityQueue<Process> Q = new PriorityQueue<Process>();
// Print maxWaitTime
System.out.println("\nMaximum wait time = " + maxWaitTime);
// While D still has a process in it
while (D.isEmpty() == false) {
// Check if current running process has finished
if (running == true && currentEndTime <= currentTime) {
// Print that Process finished
System.out.print("Process " + current.getId());
System.out.println(" finished at time " + currentTime + "\n");
// Update running flag
running = false;
// Update priority of Processes in Q that have been waiting longer than max wait time
System.out.println("Update priority:");
if (Q.isEmpty() == false) {
for (Process p : Q) {
int waitTime = currentTime - p.getArrivalTime();
if (waitTime >= maxWaitTime) {
Integer priority = p.getPriority();
int id = p.getId();
System.out.print("PID = " + id);
System.out.print(", wait time = " + waitTime);
System.out.println(", current priority = " + priority);
priority -= 1;
p.setPriority(priority);
System.out.print("PID = " + id);
System.out.println(", new priority = " + priority);
}
}
}
}
// Find process with earliest arrivalTime in D
Process earliest = D.get(0);
for (int i = 1; i < D.size(); i++) {
if (D.get(i).getArrivalTime() < earliest.getArrivalTime()) {
earliest = D.get(i);
}
}
// Check if arrivalTime of earliest is <= to currentTime
if (earliest.getArrivalTime() <= currentTime) {
// Add to Q and remove from D if yes
Q.add(earliest);
D.remove(earliest);
}
// Check if Q is not empty and running flag is false
if (Q.isEmpty() == false && running == false) {
// Remove process in Q with smallest priority
current = Q.poll();
int waitTime = currentTime - current.getArrivalTime();
totalWaitTime += waitTime;
currentEndTime = currentTime + current.getDuration();
// Process removed from priority queue, print info
System.out.print("\nProcess removed from queue is: id = " + current.getId());
System.out.print(", at time " + currentTime);
System.out.print(", wait time = " + waitTime);
System.out.println(" Total wait time = " + totalWaitTime);
System.out.println(current);
running = true;
}
if (D.isEmpty() == true) {
System.out.println("\nD becomes empty at time " + currentTime + "\n");
}
currentTime++;
}
// D is now empty, all processes are in Q
while (Q.isEmpty() == false) {
// Check if current running process has finished
if (running == true && currentEndTime >= currentTime) {
// Update running flag
running = false;
// Update priority of Processes in Q that have been waiting longer than max wait time
System.out.println("Update priority:");
if (Q.isEmpty() == false) {
for (Process p : Q) {
if (p.getArrivalTime() - currentTime >= maxWaitTime) {
p.priority = p.getPriority() - 1;
}
}
}
}
// If no Process running, start a new one
if (running == false){
current = Q.poll();
int waitTime = currentTime - current.getArrivalTime();
totalWaitTime += waitTime;
currentEndTime = currentTime + current.getDuration();
// Process removed from priority queue, print info
System.out.print("\nProcess removed from queue is: id = " + current.getId());
System.out.print(", at time " + currentTime);
System.out.print(", wait time = " + waitTime);
System.out.println(" Total wait time = " + totalWaitTime);
System.out.println(current);
running = true;
}
currentTime++;
currentTime++;
}
}
}
The biggest differences between Comparator and Comparable is that a Comparator can order objects of different classes. Comparable generally can only order the same type of objects.
So, I'd say you're well on your way, it's not as big a jump as you expected.
tl;dr
Comparator.comparing( Process :: getPriority )
Details
You said:
how exactly to implement Comparator as opposed to Comparable. I get that I need a separate class
Yes, that is the difference, a separate class.
Implementing Comparable is done by adding a method compareTo within the class of the objects being sorted. That means you are limited one single approach to sorting.
Implementing Comparator is done in a separate class. So we can more than one such Comparator implementation, for as many ways as we wish to sort our objects.
For example, a class Student representing people enrolled in a school might implement Comparable by adding a compareTo method that sorts by last name, and secondarily by first name. But in some contexts we might want to sort students by their grade level, and in other contexts by the date in which they first enrolled, and in yet other contexts we might sort by the distance between their home and the schoolhouse. For this other contexts we would write various classes implementing Comparator.
If you want to compare by a getPriority method that returns an int primitive, then your separate Comparator class might look like this.
class ProcessByPriorityComparator implements Comparator< Process > {
public int compare( Process p1 , Process p2 ){
if( p1.getPriority() == p2.getPriority() )
{
return 0;
}
else if ( p1.getPriority() > p1.getPriority() )
{
return 1;
}
else
{
return -1;
}
}
}
Or simplify:
class ProcessByPriorityComparator implements Comparator< Process > {
public int compare( Process p1 , Process p2 ){
return Integer.compare( p1.getPriority() , p2.getPriority() ) ;
}
}
Example usage:
Comparator< Process > processByPriorityComparator =
new ProcessByPriorityComparator() ;
Collections.sort( listOfProcesses , processByPriorityComparator ) ;
Or simply:
Collections.sort( listOfProcesses , new ProcessByPriorityComparator() ) ;
The lambda functional functional features in Java makes it quite easy to define a Comparator locally rather than formally defining a separate class.
Greatly helping to simplify this work are the static methods on Comparator such as comparing. So defining a Comparator can be as simple as using a method reference for an accessor “getter” method to sort by a particular property of the object.
This is quite appropriate in your particular case. We can use a method reference for the Process#getPriority method.
Comparator< Process > processByPriorityComparator =
Comparator.comparing( Process :: getPriority );
Collections.sort( listOfProcesses , processByPriorityComparator ) ;
Or, more simply, drop the named variable holding the comparator.
Collections.sort( listOfProcesses , Comparator.comparing( Process :: getPriority ) )
By the way, other issues with your code…
Do yourself a favor and move that huge main method out to its own class. Create a separate class named something like Main or App.
public class App {
public static void main( String[] args ) {
…
}
}
And I see no need for Process to be static nor be nested.
I suspect you feel some compulsion to have everything squeezed into a single class or file. Not so in Java. In Java you should generally have many classes, smaller and separate.
Eventually, as your app grows, organize the many classes by using packages and possible modules.
I have this homework assignment where i have to input a text file into my java program. the file is a "bed sensor", and tells you if the person is in a deep sleep, a restless sleep, or interrupted sleep(awake), with 0s, 1s, and 2s respectively. each line has a 0, 1, or 2 and there are 86,400 lines (one line for each second of the day).
I have figured out most of the assignment but one part i cannot figure out how to code.
My problem is i have to figure out when the person falls asleep and then output "Sleep time: (answer) hours after midnight".
i've been using counters and if statements and i would like to continue along this path if possible. i've attached my code.. and i feel like this should be pretty simple to figure out based on what i've already done... i just cannot wrap my head around it. i would appreciate any help or advice. thanks
public static void main(String[] args) {
try {
File sleepDataFile = new File("/Users/homeWork3/sleep_data.csv");
Scanner sleepData = new Scanner(sleepDataFile); // scans the data from the file into this java program
double totalSecondsCounter = 0, wakeCounter = 0, timeAwakeCounter = 0, timeAsleepCounter = 0, deepSleepCounter = 0, restlessSleepCounter = 0, interruptedSleepCounter = 0;
double wakeUpTime = 0, sleepTime = 0;
double sleepQuality = 0;
boolean inSleep = false;
while (sleepData.hasNextLine()) // this loop writes data to java as long as there is a next line
{
String data = sleepData.nextLine(); // converts the file data to strings
double val = Double.parseDouble(data); // changes string type to double type
totalSecondsCounter++;
if (inSleep == true) {
timeAsleepCounter++;
}
if (inSleep == false) {
timeAwakeCounter++;
}
if (val == 0) //deep sleep
{
deepSleepCounter++;
inSleep = true;
wakeCounter = 0;
}
if (val == 1) //restless sleep
{
restlessSleepCounter++;
inSleep = true;
wakeCounter = 0;
}
if (val == 2) // interrupted sleep / awake
{
wakeCounter++;
inSleep = false;
}
if (val == 2 && wakeCounter < 1800) {
interruptedSleepCounter++;
inSleep = true;
}
if (val == 2 && wakeCounter > 1800) {
inSleep = false;
}
if (wakeCounter == 1800) // 1800 seconds = 30 minutes. counter is set for 30 min of interrupted sleep.
{
wakeUpTime = totalSecondsCounter;
}
if (val != 2) {
}
}
sleepData.close();
System.out.println("Sleep Report for 24 hour period.");
System.out.println("----------------------------------------------------------");
System.out.println("Wake Time: \t\t\t\t" + wakeUpTime / 60 / 60 + "\t hours after midnight");
System.out.println("Sleep Time: \t\t\t\t" + sleepTime / 60 / 60 + "\t\t\t hours after midnight");
System.out.println("Duration of Deep Sleep: \t\t" + deepSleepCounter / 60 / 60 + "\t hours");
System.out.println("Duration of Restless Sleep: \t\t" + restlessSleepCounter / 60 / 60 + "\t hours");
System.out.println("Duration of Interrupted Sleep: \t\t" + interruptedSleepCounter / 60 / 60 + "\t hours");
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
I'll just give you a (comprehensive) hint, since this is a homework question.
My problem is i have to figure out when the person falls asleep and then output "Sleep time: (answer) hours after midnight".
First of all, you're going to want to initialize two variables before your while loop:
Some boolean flag variable hasFallenAsleepYet
Some double variable fallenAsleepTime
Like so:
boolean hasFallenAsleepYet = false;
double fallenAsleepTime;
Now, inside of your while loop, as you're iterating through sleepData, you're going to want to count the time taken until the person falls asleep, then stop counting.
if(!hasFallenAsleepYet) {
if(val == someInteger || val == someOtherInteger){ // some condition to tell if the person is asleep
hasFallenAsleepYet = true;
fallenAsleepTime = totalSecondsCounter;
}
}
I'll leave you to figure out what the numbers someInteger and someOtherInteger are, but you should be able to figure it out quickly. They key takeaway here is that you need to initialize some flag variable, so that you stop keeping track of fallenAsleepTime after a certain condition is met.
This is my code to update the Status:
String[] status = new String[] {"Version: 1.5.0", "https://discord.gg/arWEM2h", "Love Backxtar", "You want me!", "Type: ~help", "User Counter: %members"};
int next = 60;
public void onSecond() {
if(next%5 == 0) {
if(!hasStarted) {
hasStarted = true;
StatChannelCommand.onStartUp();
}
Random rand = new Random();
int i = rand.nextInt(status.length);
shardMan.getShards().forEach(jda -> {
String text = status[i].replaceAll("%members", "" + jda.getUsers().size());
jda.getPresence().setActivity(Activity.playing(text));
});
StatChannelCommand.checkStats();
if(next == 0) {
next = 60;
}
}
else {
next--;
}
}
But the String is running every second. I thought it was every 5 seconds. I did 60 sec % 5. What is wrong with this code?
When you enter the method onSecond() for the first time, the condition next%5 == 0 will be true. The variable next will not be updated, because this happens only in the else part. So, on next run of the method next will still be 60.
I have found that my method called checkForErrors takes around 80x longer to run on the first execution only, and I can't seem to figure out why.
D/guess: adhl
D/checkerror: checking for errors took 4760743ns // first run
D/validity: checking guess validity took 7141114ns
D/guess: agkl
D/checkerror: checking for errors took 61035ns // every other run takes around this long
D/validity: checking guess validity took 732422ns
I have looked through the code and I don't see anything that would take longer on the first run only so I'm stumped.
Button on click listener:
submitBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String Guess = guess_txt.getText().toString();
Log.d("guess", Guess);
if(checkGuessValidity(Guess)){ // <--
submitValidGuess(Guess);
int bulls = game.getBullsAndHits()[0];
int hits = game.getBullsAndHits()[1];
if(!game.gameWon) //if game is not won, submit the guess with bulls and hits
guessSubmittedListener.guessSubmitted(Guess, bulls, hits);
else //if game is won, call gameWon() method
gameEnd();
}
if((game.getCurrentTry() > game.getMaxTries()) && (!Guess.equals(game.getHiddenWord()))) gameEnd(); //if user is out of tries, call gameLost method
triesLeft.setText("Tries Left: " + (game.getMaxTries() - game.getCurrentTry() + 1)); //update tries left on main fragment
guess_txt.setText("");
}
});
checkGuessValidity:
public boolean checkGuessValidity(String Guess){
long start = System.nanoTime();
long start2 = System.nanoTime();
ErrorList Status = checkForErrors(Guess); // <--
long end2 = System.nanoTime();
Log.d("checkerror", "checking for errors took " + (end2 - start2) + "ns");
. . . more code . . .
checkForErrors:
public ErrorList checkForErrors(String Guess){
if(Guess.length() != game.getHiddenWordLength()) return ErrorList.Wrong_Length;
else if(!isValidInput(Guess)) return ErrorList.Invalid_Characters;
else if(!isIsogram(Guess)) return ErrorList.Not_Isogram;
else if(!isLowercase(Guess)) return ErrorList.Not_Lowercase;
else return ErrorList.OK;
}
isValidInput, isIsogram and isLowercase:
public boolean isIsogram(String Guess){
Map<Character, Boolean> map = new HashMap();
for(int i = 0; i < Guess.length(); i++){
if(map.get(Guess.charAt(i)) == null) //if the value for the key (character) is null (has not been changed since map initialization)
map.put(Guess.charAt(i), true); //then set it to true (indicating that it has been seen)
else { //else (if the value at the character HAS been changed since initialization, ie. it has been seen)
Log.d("Character repeated", "" + Guess.charAt(i));
return false; //return false
}
}
return true; //if loop completes no duplicates were found and guess is an isogram
}
public boolean isLowercase(String Guess){
if(Guess.equals(Guess.toLowerCase())) return true;
else return false;
}
public boolean isValidInput(String Guess){
char[] chars = Guess.toCharArray();
for(int i = 0; i < chars.length; i++){
if(!isLatinLetter(chars[i])) return false;
}
return true;
}
public static boolean isLatinLetter(char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
It doesn't seem like any of the methods should be impacted by when they are run, so I don't know why it takes extra long on the first execution. I'm still a beginner to programming so please excuse any poor formatting or horribly optimized code :p .
edit: CPU usage graph: https://prnt.sc/ftjokq
I want to end this Do While loop if the the pulls are 0 or the time is on 60 sek.
But if the pulls are at 0 the loop doesn't stop.
do{
try
{
Thread.sleep(1000);
sek++;
System.out.println(sek);
}
catch(Exception e)
{
System.out.println(e);
}
db = new BdsPostgres( );
db.select(Result.SET_1, "SELECT * FROM connection_overview WHERE leitung="+leitung+" AND status='pull' ");
db.naechsterDatensatz(Result.SET_1);
anzahlPulls = db.leseZeilen(Result.SET_1);
db.schliessen();
} while (anzahlPulls != 0 || sek != 60);
You want to use and instead of or , please note in while loop if the condition evaluates to true, it continues the loop, does not end it.
So actually your condition reads as - while either (anzahlPulls is not zero) or (sek is not 60) continue the loop. (that is when one of the condition is true continue the loop)
You actually want to use and - while both (anzajlPulls is not zero) and (sek is not 60) continue the loop. (that is break the loop when one of the conditions becomes false)
Example code -
do{
try
{
Thread.sleep(1000);
sek++;
System.out.println(sek);
}
catch(Exception e)
{
System.out.println(e);
}
db = new BdsPostgres( );
db.select(Result.SET_1, "SELECT * FROM connection_overview WHERE leitung="+leitung+" AND status='pull' ");
db.naechsterDatensatz(Result.SET_1);
anzahlPulls = db.leseZeilen(Result.SET_1);
db.schliessen();
}while (anzahlPulls != 0 && sek != 60);
You have got your logic wrong:
NOT ( A OR B ) = (NOT A) AND (NOT B)