Simulating hospital in Java (Priority Queue) - java

Im currently learning ADT's in school and for an assignment I have to simulate an ER in a hospital. I currently have my patient class as follows:
public class Patient implements Comparable<Patient>{
private String name;
private int condition;
public Patient( String n, int c ){
this.name = name;
this.condition = condition;
}
public String toString(){
return name;
}
public int boundary(int condition) {
if (condition > 17){
return 17;
}
else if (condition < 1) {
return 1;
}
return condition;
}
public int compareTo( Patient other ) {
if( this.condition < that.condition ) {
return -1;
}
else if( this.condition > that.condition ) {
return +1;
}
else {
return this.name.compareTo(that.name);
}
}
}
And I need to now make a class called ER()... One of many methods i have to implement have the conditions as follows:
public void addPatient(String name, int severity, Date time)
// Purpose: adds a person to the waiting list in the emergency
// room.
// Preconditions: name is not null
// severity is an integer in the range [1,17]
// time is the current time
// Postconditions: the person is added to the emergency room
// waiting list. The "priority" in the list is
// based on severity (1 being least important and
// 17 being most important) first and for patients
// with equal severity, based on time (FIFO).
My question is, where exactly would I create each patient (assign name and condition severity) and could someone help me with (please explain cuz i wanna learn, im not asking for direct code or answers) the prioritizing aspect and how to prioritize patients with same severity by time of arrival?
Thanks in advance for any help or input everyone!

Start with creating specific controller like FrontDeskController, and in this class create method e.g register/checkIn, checkOut. You will insert/remove all patients data here and collect all data in single Collection which you think its suitable for your case.
To prioritizing queue, if it possible separate the Collection you want to process, so you must sort with simple sort algorithm e.g quicksort and pass the sort data to another collection e.q Queue, Stack. i think this method good to be in ER Class.

Related

What is wrong with my comparable interface logic?

So the question is as follows
A unique id is assigned to each student entering the queue. The queue serves the students based on the following criteria (priority criteria):
The student having the highest Cumulative Grade Point Average (CGPA) is served first.
Any students having the same CGPA will be served by name in ascending case-sensitive alphabetical order.
Any students having the same CGPA and name will be served in ascending order of the id
My code
class Priorities{
public List<Students> getStudents(List<String> events) {
PriorityQueue<Students> pq = new PriorityQueue<Students>();
for ( String s : events) {
if ( s.contains("ENTER")) {
String [] arr = s.split(" ");
int id = Integer.parseInt(arr[3]);
String name = arr[1];
Double cgpa = Double.parseDouble(arr[2]);
pq.add(new Students(id, name, cgpa));
}
else
pq.poll();
}
List<Students> studentList = new ArrayList<Students>(pq);
return studentList;
}
}
class Students implements Comparable<Students>{
int id;
String name;
double cgpa;
public Students(int id, String name, double cgpa) {
this.id = id;
this.name = name;
this.cgpa = cgpa;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getCgpa() {
return cgpa;
}
public void setCgpa(double cgpa) {
this.cgpa = cgpa;
}
// -1 return left, 1 return right
public int compareTo(Students other) {
if ( this.equals(other))
return 0;
else if ( this.getCgpa() > other.getCgpa())
return -1;
else if ( this.getCgpa() < other.getCgpa())
return 1;
else if ( this.getCgpa() == other.getCgpa() && this.getName().compareTo(other.getName()) == 0)
return Integer.compare(this.getId(), other.getId());
else
return this.getName().compareTo(other.getName());
}
}
Sample input
12
ENTER John 3.75 50
ENTER Mark 3.8 24
ENTER Shafaet 3.7 35
SERVED
SERVED
ENTER Samiha 3.85 36
SERVED
ENTER Ashley 3.9 42
ENTER Maria 3.6 46
ENTER Anik 3.95 49
ENTER Dan 3.95 50
SERVED
Sample output
Dan
Ashley
Shafaet
Maria
I'm getting the following
Dan
Ashley
Maria
Shafaet
Edit: Using
List<Students> studentList = new ArrayList<Students>();
while(!pq.isEmpty())
{
studentList.add(pq.poll());
}
instead of List studentList = new ArrayList(pq); helps with copying the exact order of the PQ to the list.
The general structure of a comparator should be: compare a field; if the field values differ, return; if they are the same, proceed to the next field.
In this case, it could look something like:
int cmp;
cmp = Double.compare(other.getCgpa(), this.getCgpa());
if (cmp != 0) return cmp;
cmp = this.getName().compareTo(other.getName());
if (cmp != 0) return cmp;
cmp = Integer.compare(this.getId(), other.getId());
if (cmp != 0) return cmp;
return 0;
(The last if and return could be collapsed to just return cmp;; but I think it's easier to extend later if you do it as above, because you can then just insert another cmp/if.)
The issue is that PriorityQueue's ordering semantic are not guaranteed in its iterator (on top of that, note that PriorityQueue is not a List !)
Quoting from the java doc (emphasis mine) :
This class and its iterator implement all of the
optional methods of the Collection and
Iterator interfaces. The Iterator provided in method
iterator() is not guaranteed to traverse the elements of
the priority queue in any particular order. If you need ordered
traversal, consider using Arrays.sort(pq.toArray()).
Which means you will not get your comparator's ordering unless you use the queue semantics (e.g. add, poll, remove, offer... and the likes).
And looking at implementations, calling new ArrayList<Students>(pq); (or PriorityQueue#toString() for that matter) is implemented using an iterator, so it does not respect the priority.
The takeaway here :
Using PriorityQueue is OK in the case of queue semantics only, not iteration / random access
Combining both List and "live" sorting is not provided by a standard Java class that I know of (see also). (You can sort a list using a comparator, but there is no list that is sorted each time you add an element). There are such collections, though, using Set semantics, see TreeSet, you'll find them on the linked answers. Be warned that Set semantics are different (they maintain unicity of their elements, the meaning of unicity being somewhat tricky to get. For example, HashSet unicity is defined by hashCode/equals, but TreeSet's is defined by a comparator's).
That being said, Andy's implementation of the comparator is by far more readable (and avoids repetitions).

Java-Selection sorting an array of objects by an int key and displaying in table

I am currently working on a project for school and am really struggling. I am supposed to selection sort a group of Student objects and then display them in selection sort order.
Create an array with the size of 10 and assign student details (Name, BroncoId, age and TotalMarks) to the array. Perform the selection sort to sort the students in descending order based on their total marks.
a. Steps:
i. Create the student list (use Random class in java to generate the age (15-25) and total (0-100))
ii. Print the Student List in a table format
iii. Perform selection sort based on the total marks of the students
The place I am stuck at currently is making the selection sort. I understand how to create the selection sort, but I can't seem to translate it for this implementation.
My selection sort code:
public static Student[] selectionSort(Student[] studentList)
{
for(int i = 0; i <studentList.length-1; i++)
{
int minIndex = studentList[i].getGrades();
int pos = i;
for(int j = i + 1; j < studentList.length-2; j++)
{
if(studentList[j].getGrades() > studentList[minIndex].getGrades())
{
minIndex = studentList[j].getGrades();
pos = j;
}
}
int temp = studentList[pos].getGrades();
studentList[pos] = studentList[i];
int k = studentList[i].getGrades();
k = temp;
}
return studentList;
}
When I run this code, the console returns:
I sought tutoring to hopefully fix this problem, but my tutor gave me a few nonfunctional suggestions. We were both stumped at the end of the session.
My code for printing:
public static void printStudentInfo(Student[] students)
{
System.out.println("Name: AGE: idNumber: Score:");
for(Student student: students)
{
if(student.getName().length() <= 49)
System.out.printf("%-50s %-5d %-10s %-4d\n", student.getName(), student.getAge(), student.getID(), student.getGrades() );
else
{
System.out.printf("%-50s %-5d %-10s %-4d\n", student.getName().substring(0,48), student.getAge(), student.getID(), student.getGrades() );
System.out.println();
int i = 0;
while(i <= student.getName().length())
{
System.out.printf("%-50s", student.getName().substring(49 +48*i, 97+48*i) );
System.out.println();
i++;
}
}
}
}
As more of an issue out of passion, I sought to make an interesting print method. My problem is, also that I don't really know how to parse and format a string of 155 characters for instance. What do I put in this while lop to accomplish this?
I want the program to output one object name line like:
49 characters
49 chars
…
What ever is left
It probably won't ever go past three lines, but hey, who says I can't give an example like that? What do I put in the header of the while loop to accomplish this?
PS:
Here is the Student class if you need it.
public class Student
{
private String name;
private int age;
private String idNumber;
private int gradePoints;
public Student(String name, int age, String idNumber, int gradePoints)
{
this.name = name;
this.age = age;
this.idNumber = idNumber;
this.gradePoints = gradePoints;
}
public void setName(String name)
{
this.name = name;
}
public void setAge(int age)
{
this.age = age;
}
public void setidNumber(String idNumber)
{
this.idNumber = idNumber;
}
public void setPoints(int gradePoints)
{
this.gradePoints = gradePoints;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String getID()
{
return idNumber;
}
public int getGrades()
{
return gradePoints;
}
Welcome to SO Matthew.
Rather than giving you a solution I thought it might be useful to give you a process for solving the problem yourself.
Good practice in software development is to break your problem down into very small components, make sure each of those work perfectly (through unit testing) and then build your solution from those components.
In line with that practice I suggest you do the following:
list each of the individual steps required to do a selection sort on paper.
Pick the simplest one (e.g. swapping two elements).
Write a unit test that would pass if your swap method worked
run the unit test and verify that it fails
write the simplest code you can to make that test pass
write a new test to cover a more complex scenario that isn't yet supported
keep going until you believe that method works perfectly
move onto the next method
once all the components are working perfectly write the method that calls them all using the same process (i.e. test first then code)
If you follow this process then you will end up with a system that you understand perfectly, works, is maintainable, and that you can refactor. It has another very significant benefit: it means when you come to SO with a question you'll be asking about a specific item that you don't know how to solve rather than a 'why doesn't my code work' question. Specific questions tend to get better and faster responses.
In your case, I would start with methods for swapping items (hint: your code for this doesn't work which you'll discover quickly when you write a unit test) and then move on to finding the smallest item in a sublist. Then a method that uses those two to put the smallest item at the start of a sublist. Finally a method that performs that method for all sublist progressively. Make sure each method is working perfectly, including checking validity of arguments, before you move on to putting them together.

Bubble sort Arraylist of objects

The aim of this method here is to bubble sort according to a person's ID
however in this area:
if (al.get(i).compareTo(al.get(i+1)) > 0 )
it states: cannot find symbol - method compareTo(java.lang.Object)
This is the class person (not very imp) / / / /
public class Person implements java.io.Serializable
{
String personID;
String name;
byte dayDOB;
byte monthDOB;
short yearDOB;
String telNum;
}
This is the sort method:
public static void sort(ArrayList al)
{
Person p;
String temp;
boolean flag = true;
System.out.println("Database will be sorted acc to ID ");
System.out.println();
while (flag = true)
{
flag = false;
for (int i=0;i<al.size()-1;i++)
{
p = (Person) al.get(i);
if (al.get(i).compareTo(al.get(i+1)) > 0 )
{
temp = al.get(i);
al.set(i,al.get(i+1) );
al.set(i+1, temp);
flag = true;
}
}
}
}
PS; I am a newbie when it comes to code and have been modifying this code for up to 7 hours already
Objects come with a built in compareTo() method, but it's best to override the default. See the java documentation for compareTo(). That should simplify your code quite a bit.
Your Person class will need to implement Comparable and include that in the class declaration. You can then write a compareTo() method something like this:
public int compareTo(Person b) {
return this.name.compareTo(b.getName());
}
A compareTo() method should return -1, 0, or 1. If you call a.compareTo(b) in your main class, compareTo() should return zero if the objects are sorted to the same place (i.e. equal), -1 if object a should be sorted before object b, or 1 if object a should be sorted after b.
You'll need to decide what constitutes the same person and how they should be sorted. Alphabetically based on name? Name and id? Whatever it is for your program.

Utilizing Comparable for 2 Sort Criteria when Sorting an Array of Objects

I've been working at this for a couple hours now and I feel (I hope) I'm right on the verge of figuring it out. This program reads in a bunch of values from an external file and places them in an array of objects which seems to be working just fine.
The Objects properties are:
Bank Account #
Customer Name
Bank Account Balance
1. I can output them in order of Account # (That's how their read in from the file, no sorting is necessary)
2. I've setup a method from implementing Comparable to sort by Bank Account Balance and it's working fine.
3. I need a second sort method, to sort by Customer Name.
- The problem I'm having with this is based on the research I've done and what I've tried I've come to the conclusion that the only way to make this work will be to build my own Comparable Objects (sorry if my terminology is skewed.) I've attempted this as well multiple times with both Java Doc and some similar questions on SE.
When all is said and done I'm going to throw some Listeners into my checkbox group to allow the user to toggle the different sort methods.
Here's the chunks i'm working on:
public class bankAccounts implements Comparable<bankAccounts> {
/* PRIVATE FIELDS HERE, FOLLOWED BY TYPICAL GET AND SET METHODS */
/*SORTS BY ACCOUNT BALANCE WORKING GREAT*/
public int compareTo(bankAccounts b) {
if (accountBalance < b.accountBalance)
{
return -1;
}
if (accountBalance > b.accountBalance) {
return 1;
}
return 0;
}
/* BEGIN SNIPPET OF MAIN CLASS */
/*METHOD I CALL FROM MAIN CLASS, SORTS BY BALANCE ^^ AS SEEN ABOVE */
Arrays.sort(retrievedAccounts);
for (int i=0; i<retrievedAccounts.length; i++) {
String resultFull = Integer.toString(retrievedAccounts[i].getAccountNumber()) + retrievedAccounts[i].getAccountLastName() + Double.toString(retrievedAccounts[i].getAccountBalance());
box.append(resultFull + "\n");
}
/* NORMAL METHOD WHICH OUTPUTS IN ORDER OF ACCOUNT NUMBER, NO SORTING HAPPENING HERE */
for(int x = 0; x < retrievedAccounts.length; ++x)
{
String resultFull=Integer.toString(retrievedAccounts[x].getAccountNumber()) + retrievedAccounts[x].getAccountLastName() + Double.toString(retrievedAccounts[x].getAccountBalance());
box.append("\n\n\n" + resultFull + "\n\n");
}
I'm hoping someone will have some insight towards a next step which might allow me to finish this up. If you have suggestions to take this a completely different direction I'm open to that as well.
This is an idea haven't tested.
Create a another private method to store compareType
public class bankAccounts implements Comparable<bankAccounts> {
private int compareType = 0; // 0 - compare by balance 1-compare by name
In your compare method
public int compareTo(bankAccounts b) {
if(this.compareType == 0){
if (accountBalance < b.accountBalance)
{
return -1;
}
if (accountBalance > b.accountBalance) {
return 1;
}
return 0;
}else{
return customerName.compareTo(b.customerName)
}
Use an implementation of Comparator<bankAccounts> that compares the names of your objects and pass that into the Arrays.sort() method.
Use an anonymous class like this:
Arrays.sort(retrievedAccounts, new Comparator<bankAccounts>() {
public int compare(bankAccounts a, bankAccounts b) {
return a.getName().compareTo(b.getName());
}
});
This code assumes you have a getter method on bankAccounts for customer name called getName()
You would do well to follow java naming conventions:
class names start with a capital letter
class names are singular, not plurals

How do you associate each Collection's item to another one's?

I have two Collection objects, I want to associate each object of these two in a readable way (HashMap, Object created on purpose, you choose).
I was thinking of two loops one nested into the other, but maybe it's a well known problem and has a commonly understandable solution...
What if the number of Collection objects raises above two?
EDIT after Joseph Daigle comment: The items of the Collection objects are all of the same type, they are rooms of hotels found to be bookable under certain conditions.
Collection<Room> roomsFromA = getRoomsFromA();
Collection<Room> roomsFromB = getRoomsFromB();
for(Room roomA : roomsFromA){
for(Room roomB : roomsFromB){
//add roomA and roomB to something, this is not important for what I need
//the important part is how you handle the part before
//especially if Collection objects number grows beyond two
}
}
EDIT 2: I'll try to explain better, sorry for the question being unclear.
Follows an example:
A user requests for a double and a single room.
The hotel has 3 double and 4 single rooms available.
I need to associate every "double room" to every "single room", this is because each Room has its own peculiarity say internet, a more pleasant view, and so on. So i need to give the user all the combinations to let him choose.
This is the simple case, in which only two Collection of Room objects are involved, how do you manage the problem when say both hotel and user can offer / request more Room types?
What you are trying to do here is to get all possible permutations of choosing X from a set of Y. This is a well known problem in discrete mathematics and I think it is just called Combinatorial Mathematics.
To solve your problem you need to create a super collection containing all your Room types. If this is an array or a List you can then use this example to calculate all possible ways of choosing X from the set of Y. The example will give you the indices from the list/array.
Do the collections line up exactly?
HashMap map = new HashMap();
for (int i=0; i<c1.Size(); i++) {
map.put(c1[i], c2[i]);
}
Well, since I don't know if you will need to search for both of them having only one, the HashMap won't work.
I would create a class that receives a Pair.. sort of:
private static class Pair<K, T> {
private K one;
private T two;
public Pair(K one, T two) {
this.one = one;
this.two = two;
}
/**
* #return the one
*/
public K getOne() {
return one;
}
/**
* #return the two
*/
public T getTwo() {
return two;
}
}
And create a List with them.
Your example implies that the return value from "roomsFromB" is a subcollection of the return value of "roomsFromA", so it'd be more natural to model it that way:
class Room {
public Collection<Room> getRoomsFromB { ...
}
which would then let you do :
//Collection rooms
for (Room a: rooms)
{
for(Room b a.getRoomsFromB){ ...
This is assuming that they're modeled hierarchically, of course. If they're not then this is inappropriate, but then the question you're asking, it seems to me, is really how to model the relationship between them, and you haven't yet made that explicit.
You might reconsider whether you need exactly this logic. You're introducing an O(n^2) operation, which can quickly get out of hand. (Technically O(mn), but I'm guessing m and n are roughly the same order.)
Is there another solution to your problem? Perhaps you could create a 'set' which includes all of A and all of B, and then each object in A and B could point to this set, instead?
I assume that:
Each element in collection 1 will
match a single element in
collection 2
The collections have the same
size
The collections can be ordered and
the order matches each element in
both collections
Order both collections (in the same
order) by the property that
identifies each object.
Iterate through both collections with a single loop, build a relation object and add it into a new collection.
See if this helps you:
public static class Room {
private int number;
private String name;
public Room(int number, String name) {
super();
this.number = number;
this.name = name;
}
public int getNumber() {
return number;
}
public String getName() {
return name;
}
}
public static class RoomRelation {
private Room a;
private Room b;
public RoomRelation(Room a, Room b) {
super();
this.a = a;
this.b = b;
}
public Room getA() {
return a;
}
public Room getB() {
return b;
}
#Override
public String toString() {
return a.getName() + "(" + a.getNumber() + ") " + b.getName() + "(" + b.getNumber() + ")";
}
}
public static void main(String[] args) {
List<Room> roomsFromA = new ArrayList<Room>();
List<Room> roomsFromB = new ArrayList<Room>();
roomsFromA.add(new Room(1,"Room A"));
roomsFromA.add(new Room(2,"Room A"));
roomsFromB.add(new Room(1,"Room B"));
roomsFromB.add(new Room(2,"Room B"));
Comparator<Room> c = new Comparator<Room>() {
#Override
public int compare(Room o1, Room o2) {
return o1.getNumber() - o2.getNumber();
} };
Collections.sort(roomsFromA, c);
Collections.sort(roomsFromB, c);
List<RoomRelation> relations = new ArrayList<RoomRelation>();
for (int i = 0; i < roomsFromA.size(); i++) {
relations.add(new RoomRelation(roomsFromA.get(i), roomsFromB.get(i)));
}
for (RoomRelation roomRelation : relations) {
System.out.println(roomRelation);
}
}
Your question is quite unclear. As I understand you want to list all combinations of rooms, minus duplicates. Here us some code to build up a 2d array of all the room combinations. For more kinds of room, put in another nested loop.
Collection<Room> roomsFromA = getRoomsFromA();
Collection<Room> roomsFromB = getRoomsFromB();
Room[][] combinations = new Room[roomsFromA .size()][roomsFromB .size()];
int a = 0;
int b = 0;
for(Room roomA : roomsFromA){
for(Room roomB : roomsFromB){
combinations [a][b] = [roomA][roomB]; //Build up array
b++;
}
a++;
}
return combinations;
It is a common problem. It's called a Cartesian product. If you have two collections like in your case, I would not hesitate to have two nested loops. Otherwise, see this question.

Categories