I am using a Max-Heap to store objects of type Song. A song has a title and a rating as shown in the Song class. I want the Song object to be compared by rating so that the highest rated songs are displayed first. If songs have the same rating then they should be compared by alphabetical order of title. What I have now is currently outputting it by highest rating, but incorrectly.
Heap:
public class Heap<T extends Comparable<T>> {
private ArrayList<T> heap;
public Heap(){
heap = new ArrayList<T>();
}
public int getPLoc(int i){
return (i - 1) / 2;
}
public int getLCLoc(int i){
return 2 * i + 1;
}
public int getRCLoc(int i){
return 2 * i + 2;
}
public T getNodeAt(int i) {
if(heap.get(i) == null) {
System.out.println("Item does not exist.");
return null;
}else {
return heap.get(i);
}
}
public void addNode(T n) {
heap.add(null);
int index = heap.size() - 1;
while(index > 0 && (getNodeAt(getPLoc(index)).compareTo(n)) < 0) { //Is this correct?
heap.set(index, getNodeAt(getPLoc(index)));
index = getPLoc(index);
}
heap.set(index, n);
}
Song:
public class Song implements Comparable<Song> {
private String title;
private String rating;
public Song(String t, String r) {
title = t;
rating = r;
}
public String getTitle(){
return title;
}
public String getRating(){
return rating;
}
// Need help here adding it to also compare by alphabetical title if songs have same ratings.
public int compareTo(Song s) {
return rating.compareTo(s.getRating());
}
The compareTo() method returns an int with the following values:
negative If thisObject < anotherObject
zero If thisObject == anotherObject
positive If thisObject > anotherObject
Check for value zero, meaning rating is same, then go for title comparison.
Sample Code , can be tweaked
public int compareTo(Song s) {
int val = rating.compareTo(s.getRating());
if(val == 0){
val = title.compareTo(s.getTitle());
}
return val;
}
Solution is to compare the name of the songs if their Rank is equal (and compareTo therefore returns 0) and return the result of the Second compare
Related
When calculating the rank, the number of consecutive Trails of the same type will have increasingly higher rankings. For example, one Trail of type "ice" has a ranking of 4. If there is another ice Trail immediately following it, that second one will have a ranking of 8 (2 *4). If there is a third ice Trail in that sequence, it will have a ranking of 12 (3 * 4).The overall rank of the slope is the sum of all its trails' rankings and this value must be assigned to the instance variable called ranking.
Trail is an array type. So, an example is [3, 3, 3, 3] so the overall rank should be 30. I am trying to create a recursive algorithm.
public int calculateRank () {
for (int i = 0; i < count; i++) {
if (trail[i].equals(0)) {
ranking = 0;
} else if (trail[i + 1] == trail[i]) {
ranking = calculateRank() * trail[i];
}
ranking += ranking;
}
return ranking;
}
Trail class
public class Trail {
private String ID;
private String type;
private int rank;
public Trail (String ID, String type) {
this.ID = ID;
this.type = type;
if (type == "ice") {
rank = 4;
} else if (type == "trees") {
rank = 3;
} else if (type == "rocks") {
rank = 2;
} else if (type == "slalom") {
rank = 1;
} else {
rank = 0;
}
}
public int getRank () {
return rank;
}
public void setRank (int newRank) {
this.rank = newRank;
}
public String getType () {
return type;
}
public void setType (String newType) {
this.type = newType;
}
public String getID () {
return ID;
}
public void setID (String newID) {
this.ID = newID;
}
public String toString () {
String s = "";
s += this.rank;
return s;
}
}
This is what I had written however a. I don't fully understand the code I wrote and b. It results in a compilation error.
I have been given the following main method and must write the code for the ObjectList class. I am supposed to infer the necessary functions of the ObjectList class and write the class myself, however I am unsure exactly what I need to do to fulfill this function. Any help understanding this is greatly appreciated. This is the code I was given:
ObjectList ol = new ObjectList(3);
String s = "Im Happy";
Dog d = new Dog();
DVD v = new DVD();
Integer i = 1234;
System.out.println(ol.add(s));
System.out.println(ol.add(d));
System.out.println(ol.add(v));
System.out.println(ol.add(i));
ol.remove(0);
System.out.println(ol.add(i));
System.out.println("Is the list full? "+ isFull());
System.out.println("Is the list empty? "+ isEmpty());
System.out.println("Total number of objects in the list: " + getTotal());
Object g = ol.getObject(1);
g.bark();
It's quite simple just need to create a list of Object types using ArrayList or LinkedList in the ObjectList class and implement the function as follows
public class ObjectList{
private ArrayList<Object> objects;
public ObjectList(int size)
{
objects = new ArrayList<Object>(size);
}
public String add (Object object)
{
objects.add(object);
//anything you would like to return I'm just returning a string
return "Object Added";
}
public void remove (int index)
{
objects.remove(index);
}
public boolean isEmpty()
{
return objects.isEmpty();
}
public int getTotal()
{
return objects.size();
}
public Object getObject(int index)
{
return objects.get(index);
}
}
The isFull()is not needed since ArrayListsize can change dynamically. You can use a simple array instead of ArrayList and then implement the isFull() function.
Also when getting an object using the get getObject() function, you need to cast it to the correct type before using there function. In your code g.bark() won't work because Object doesn't have a bark function
Object g = ol.getObject(1);
//This can give a runtime error if g is not a Dog
//Use try catch when casting
Dog d = (Dog)g;
d.bark();
EDIT
This is how you would implement isFull() and other functions if using arrays instead of ArrayList but for the sake of simplicity use the ArrayList version
public class ObjectList{
private Object[] objects;
private int size = 0;
private int currentIndex = 0;
public ObjectList(int size)
{
this.size = size;
objects = new Object[size];
}
private boolean isFull() {
if(currentIndex == size)
return true;
else
return false;
}
public String add (java.lang.Object object)
{
if ( ! isFull() ) {
objects[currentIndex] = object;
currentIndex++;
return "Object added";
}
return "List full : object not added";
}
public void remove (int index)
{
if( !isEmpty() ) {
//shifting all the object to the left of deleted object 1 index to the left to fill the empty space
for (int i = index; i < size - 1; i++) {
objects[i] = objects[i + 1];
}
currentIndex--;
}
}
public boolean isEmpty()
{
if(currentIndex == 0)
return true;
else
return false;
}
public int getTotal()
{
return currentIndex;
}
public java.lang.Object getObject(int index)
{
if(index < currentIndex)
return objects[index];
else
return null;
}
}
What it seems you want to achieve is "expand" the functionality of an ArrayList and create a custom list of objects. What you could do is to create a class extending the ArrayList and define/override any other methods you want.
public class ObjectList extends ArrayList<Object> {
//constructor with initial capacity
private int length;
public ObjectList(int size){
super(size);
this.length= size;
}
public Object getObject(int index){
return this.get(index);
}
}
Now you have the add and remove functions inherited from the ArrayList class and the getObject method.
Concerning the isFull method, you can check if the size of your ObjectList class is equal to the size it was instantiated with
if(this.size() == this.length){
return true
}
return false;
And getTotal
public int getTotal(){
return this.size();
}
Edit. thank you.
I have an array of 'normal' vehicles and 'large' vehicles. I have an assignment requiring me to divide them up to contribute to a far larger app.
One array for the large vehicles, one for the normal vehicles containing all the info for each element. ArrayLists are not permitted as my instructor is teaching us fundamentals.
Sample of the array
27723 4/09/61 large 7337
28507 22-02-1983 large 7055
28558 1/05/70 normal 3518
//On button press
//recieve single item from array from main and test it
//array in main will be looped for all elements.
public String loadVehicle(Vehicle v) {
String res = Constants.OK;
boolean normBool = false;
boolean largeBool = false;
//if both arrays are full , stop the method call in the main form
if (normBool && largeBool){return Constants.ERROR;}
//if vehicle size is normal, fill the normal veh array
if(v.getSize().equals(Constants.NORMAL_SIZE))
{
for(int i = 0; i<normalVehicles.length; i++)
{
//if norm veh array element is null, add the appropriate value to it
if(normalVehicles[i] == null){normalVehicles[i] = v;}
else{normBool = true;}
}
}
//if veh size is large put it in the large veh array
else if(v.getSize().equals(Constants.LARGE_SIZE))
{
for(int iL = 0; iL<largeVehicles.length; iL++)
{
if(largeVehicles[iL] == null){largeVehicles[iL] = v;}
else{largeBool = true;}
}
}
return res;
}//end method
Seems you cannot use builtin LinkedList class too, then do this:
Add the following code in your Vehicle class:
class Vehicle(){
//YOUR OTHER PIECES OF CODES ...
private static Vehicle firstLargeVehicle;
private Vehicle nextLargeVehicle;
private int index;
public void setIndex(int index){
this.index = index;
if(index == 0) Vehicle.firstLargeVehicle = this;
}
public int getIndex(){
return index;
}
public void setNextLargeVehicle(Vehicle nextLargeVehicle){
this.nextLargeVehicle = nextLargeVehicle;
}
public Vehicle getNextLargeVehicle(){
return nextLargeVehicle;
}
public addLargeVehicle(Vehicle newVehicle){
this.nextLargeVehicle = newVehicle;
newVehicle.setIndex(index + 1);
}
public getListSize(){
Vehicle lastOne = this;
while (lastOne.getNextLargeVehicle() != null){
lastOne = lastOne.getNextLargeVehicle();
}
return lastOne.getIndex() + 1;
}
public static Vehicle[] largeVehiclesToArray(){
Vehicle[] result = new Vehicle[firstLargeVehicle.getListSize()]();
Vehicle pointer = firstLargeVehicle;
for (int counter = 0; pointer != null; counter ++){
result[counter] = pointer;
pointer = pointer.getNextLargeVehicle();
}
return result;
}
}
And in your main loop, do something like the following code:
Vehicle vehicle = null;
for(Vehicle newVehicle : allVehicles) {
if (newVehicle.isLarge()){
if (vehicle == null) {
vehicle = newVehicle;
vehicle.setIndex(0);
}else{
vehicle.addLargeVehicle(newVehicle));
}
}
}
Vehicle[] largeVehicles = Vehicle.largeVehiclesToArray();
And the same story goes for normal vehicles.
Any question ?
You can write your loops like this:
for(int i = 0; i < normalVehicles.length; i++)
{
if(normalVehicles[i] == null)
{
normalVehicles[i] = v;
break;
}
}
// if last slot isn't null then it's full
normBool = normalVehicles[normalVehicles.length-1] != null;
What is the correct way to use the compareTo inside for loop? I'd like to sort the Course objects in ascending order inside the array. I'm worried about the correct syntax for compareTo inside a loop in my insert() method.
if((array[i].courseNumber.compareTo(object.courseNumber)) <= 0) - is giving me error.
public class Courses implements Comparable{
private String title;
private int courseNumber;
private Courses[] array;
private int size;
public Courses(String title, int courseNumber){
this.title = title;
this.courseNumber = courseNumber;
this.array = new Courses[10];
this.size = 0;
}
public void insert(String title, int courseNumber){
Courses object = new Courses(title, courseNumber);
if(size == 0){
array[0] = object;
}
else{
int i;
for(i = 0; i < size; i++){
if((array[i].courseNumber.compareTo(object.courseNumber)) <= 0)
//do STUFF
}
}
}
#Override
public int compareTo(Object o) {
if(o instanceof Courses){
Courses obj1 = (Courses)o;
return this.courseNumber - obj1.courseNumber;
}
return -1;
}
}
if((array[i].courseNumber.compareTo(object.courseNumber)) <= 0)
Is giving you an error because courseNumber is a primitive (not an object), so there is no compareTo method defined on it.
If you would like to use that syntax to compare integers, you can use the static Integer.compare method.
if(Integer.compare(array[i].courseNumber, object.courseNumber) <= 0)
If you want to use your defined compareTo method then do
if(array[i].compareTo(object) <= 0))
Hint : You are not passing the object as parameter.
How does this compare two objects ?
for(i = 0; i < size; i++){
if((array[i].courseNumber.compareTo(object.courseNumber)) <= 0)
//do STUFF
}
You should look at Arrays.sort(Object[]) which will take care about ordering it using the Comparable interface.
Heres the method where I try to add everything. What im trying to do is add up a series of coins, which are named penny,dime...etc. And i gave all of them a value within the enum. But how do I access each of the coins within the array, then add up their values?
public double totalValue(Coin[] coins)
{
double sum = 0;
//computes and returns the monetary value of all the coins in the jar
for(int i = 0; i < coins.length; i++)
{
double coinValue = coins[i].CoinName.getCoinValue();
sum = sum + coins[i];
System.out.println(sum);
}
return sum; //change this!
}
and here is where the values for the enum are defined.
public enum CoinName
{
PENNY(.01), NICKEL(.05), DIME(.10), QUARTER(.25), FIFTY_CENT(.50), DOLLAR(1.0);
private double value;
private double coinValue;
private CoinName(double value)
{
this.coinValue = value;
}
public double getCoinValue()
{
return coinValue;
}
}
///// I have just added my coin class.
import java.util.Random;
public class Coin
{
public static long SEED = System.currentTimeMillis();
public static Random RANDOM = new Random(SEED);
//private instance variables denomination, year, and sideUp: year is an int, denomination is of type CoinName and sideUp is of type CoinSide
private CoinName denomination;
private CoinSide sideUp;
private int year;
public Coin(CoinName denomination,int year)
{
this.denomination = denomination;
this.year = year;
int side = Coin.RANDOM.nextInt(2);
if (side == 0)
{
sideUp = CoinSide.HEADS;
}
else
sideUp = CoinSide.TAILS;
}
//Accessors for denomination, year and sideUp
public CoinName setDenomination()
{
int i = 0;
i = Coin.RANDOM.nextInt(6);
if (i == 0)
{
denomination = CoinName.PENNY;
}
if (i == 1)
{
denomination = CoinName.NICKEL;
}
if (i == 2)
{
denomination = CoinName.DIME;
}
if (i == 3)
{
denomination = CoinName.QUARTER;
}
if (i == 4)
{
denomination = CoinName.FIFTY_CENT;
}
if (i == 5)
{
denomination = CoinName.DOLLAR;
}
return denomination;
}
public CoinName getDenomination()
{
return denomination;
}
public void setSideUp(CoinSide sideUp)
{
sideUp = sideUp;
}
public CoinSide getSideUp()
{
return sideUp;
}
public void setYear(int year)
{
year = RANDOM.nextInt(2013-1873) + 1873;
}
public int getYear()
{
return year;
}
//the standard toString method that prints out a coin in the format “PENNY/1990/HEADS”
public String toString()
{
return denomination + "/" + year + "/" + sideUp;
}
//the standard equals method that checks if two Coin objects are equal – they are equal if the denominations are identical
public boolean equals(Object obj)
{
if (obj instanceof Coin){
Coin d = (Coin)obj;
if (this.getDenomination()==d.getDenomination())
return true;
else
return false;
}
return false;
}
public void toss()
{
//flip the coin
//Use the object RANDOM to generate random numbers
int side = Coin.RANDOM.nextInt(2);
if (side == 0)
{
sideUp = CoinSide.HEADS;
}
else
sideUp = CoinSide.TAILS;
}
}
A Coin has a denomination, which holds the value of the coin. With how you have defined things, to sum the values of an array of coins you have to first get the denomination and then extract the value from it:
for(int i = 0; i < coins.length; i++)
{
CoinName denomination = coins[i].getDenomination();
sum = sum + denomination.getCoinValue();
System.out.println(sum);
}
Note that for this to work the array of coins must be full, with no null values, and each coin must have a denomination.
Assuming that your Coin class has a CoinName property which of type CoinName then you need to change the line
sum = sum + coins[i];
to use the coinValue you get the line before. So change to
sum = sum + coinValue;
or typically this would be
sum += coinValue;
You also have in your Enum two doubles which, one of which is not needed, remove the value