patternjavaModerate
Animal shelter simulation using Queues
Viewed 0 times
simulationanimalusingshelterqueues
Problem
This is of one the interesting problems I've solved:
An animal shelter holds only dogs and cats, and operates on a strictly "first in, first out" basis. People must adopt either the "oldest" (based on arrival time) of all animals at the shelter, or they can select whether they would prefer a dog or a cat (and will receive the oldest animal of that type). They cannot select which specific animal they would like. Create the data structures to maintain this system and implement operations such as
My algorithm:
Implementation:
```
static class Node{
Node next;
T type;
String animalName;
int arrivalTime;
Node(String name){
this.animalName = name;
}
@Override
public String toString(){
return this.animalName;
}
}
static class Dog{
}
static class Cat{
}
static class Queue{
Node front, rear;
public void enq(Node toEnq){
if(rear==null){
rear = toEnq;
front = rear;
}else{
rear.next = toEnq;
rear = rear.next;
}
}
public Node deq(){
if(front==null){
System.out.println("Underflow!");
return new Node("Error");
}else{
Node frn = front;
front = front.next;
return frn;
}
}
public void printQ(){
Node temp = front;
if(this.isEmpty()){
System.out.println("No animals here");
return;
}
while(temp.next!=null){
System.out.print(temp.animalName +
An animal shelter holds only dogs and cats, and operates on a strictly "first in, first out" basis. People must adopt either the "oldest" (based on arrival time) of all animals at the shelter, or they can select whether they would prefer a dog or a cat (and will receive the oldest animal of that type). They cannot select which specific animal they would like. Create the data structures to maintain this system and implement operations such as
enqueue, dequeueAny, dequeueDog and dequeueCat.My algorithm:
- Maintain two
Queues,CatQand aDogQ.
- If the user wants a
Cat, dequeue from theCatQ, and if he wants aDog, dequeue fromDogQ.
- The problem gets trickier for
dequeueAny, since there are twoQueues and should be served on FIFO basis. While enqueuing, I'm inserting thearrivalTimetoo, so whichever animal has the lowestarrivalTimewill be dequeued first.
Implementation:
```
static class Node{
Node next;
T type;
String animalName;
int arrivalTime;
Node(String name){
this.animalName = name;
}
@Override
public String toString(){
return this.animalName;
}
}
static class Dog{
}
static class Cat{
}
static class Queue{
Node front, rear;
public void enq(Node toEnq){
if(rear==null){
rear = toEnq;
front = rear;
}else{
rear.next = toEnq;
rear = rear.next;
}
}
public Node deq(){
if(front==null){
System.out.println("Underflow!");
return new Node("Error");
}else{
Node frn = front;
front = front.next;
return frn;
}
}
public void printQ(){
Node temp = front;
if(this.isEmpty()){
System.out.println("No animals here");
return;
}
while(temp.next!=null){
System.out.print(temp.animalName +
Solution
Structure
So your structure is definitely a bit off. First of all, you made your
So first of all, lets move
As cats and dogs are both animals, lets also create an
Now our
This restructuring did break some other parts of your code, but not that many.
Adding new animals is now simpler, and your queue is actually reusable, you can add anything:
Misc
So your structure is definitely a bit off. First of all, you made your
Node generic, which is good, as it could theoretically work with any content - which is what you want from a queue. But then, you have fields which just don't belong there, such as animalName (and type, which is just not needed).So first of all, lets move
animalName outside of the node and into the animal classes, where it belongs. As cats and dogs are both animals, lets also create an
Animal class which both extend:static class Dog extends Animal {
public Dog(String name) {
super(name);
}
}
static class Cat extends Animal {
public Cat(String name) {
super(name);
}
}
static class Animal {
String animalName;
public Animal(String name) {
this.animalName = name;
}
@Override
public String toString() {
return this.animalName;
}
}Now our
Node class makes more sense (we'll remove arrivalTime later as well):static class Node{
Node next;
int arrivalTime;
T content;
Node(T content){
this.content = content;
}
@Override
public String toString(){
return this.content.toString();
}
}This restructuring did break some other parts of your code, but not that many.
enq now doesn't work like this, so change it to:public void enq(Node toEnq){
toEnq.arrivalTime = this.arrivalTime;
arrivalTime++;
if (toEnq.content instanceof Cat) {
catQ.enq(toEnq);
} else {
dogQ.enq(toEnq);
}
}Adding new animals is now simpler, and your queue is actually reusable, you can add anything:
myHouse.enq(new Node(new Cat("Bella")));Misc
- fields should be private as to not expose implementation details
- you could easily get rid of the arrival time by just having one queue, and if
deqAnyis called, return the first entry, ifdeqDogordeqCatis called peek until you find the correct animal, then return that. (This would worsen your performance in some corner-cases, see comments.) A better idea would be to movearrivalTimeintoAnimal, because it's a datapoint for animals, not for nodes. Ideally, you would also use some sort of time instead of a counter, because it makes more logical sense.
- don't shorten words in variable and method names, it makes code harder to read. Eg;
printQ, what's aQ?deq? etc
- your whitespace usage is a bit off (spaces and vertical whitespace)
- an error node is not a good idea, nor is printing in a queue. just throw an exception, that way the code using your queue can decide how to handle that case.
- your
AnimalHousedoesn't need to know about the implementation details of the queue. So remove thenodefields (which aren't used anyways), and instead of passing and returning nodes, pass and return the content instead and create the nodes inside of the queues.
Code Snippets
static class Dog extends Animal {
public Dog(String name) {
super(name);
}
}
static class Cat extends Animal {
public Cat(String name) {
super(name);
}
}
static class Animal {
String animalName;
public Animal(String name) {
this.animalName = name;
}
@Override
public String toString() {
return this.animalName;
}
}static class Node<T>{
Node<T> next;
int arrivalTime;
T content;
Node(T content){
this.content = content;
}
@Override
public String toString(){
return this.content.toString();
}
}public void enq(Node toEnq){
toEnq.arrivalTime = this.arrivalTime;
arrivalTime++;
if (toEnq.content instanceof Cat) {
catQ.enq(toEnq);
} else {
dogQ.enq(toEnq);
}
}myHouse.enq(new Node<Cat>(new Cat("Bella")));Context
StackExchange Code Review Q#116642, answer score: 11
Revisions (0)
No revisions yet.