public class CanadaTour {
private CircularArrayQueue<City> cityQueue;
private Map map;
private City startCity;
public CanadaTour (String fileName) {
map = new Map();
cityQueue = new CircularArrayQueue<City>();
loadData(fileName);
}
private void loadData (String file) {
MyFileReader reader = new MyFileReader(file);
reader.readString(); // First line of headers.
String cityName = null;
int locX = 0;
int locY = 0;
double earnings = 0;
int cityID = 0;
while (!reader.endOfFile()) {
cityName = reader.readString();
locX = reader.readInt();
locY = reader.readInt();
earnings = reader.readDouble();
cityID ++;
City city = new City(cityID, cityName, locX, locY, earnings);
if (cityID == 1) {
startCity = city;
}
cityQueue.enqueue(city);
map.addCity(city);
}
}
public City findNextCity (City currCity, double currMoney) {
double distance = 0;
City result = cityQueue.dequeue();
if (result != currCity || result.isMarkedInStack()
|| result.isMarkedOutOfStack()) //add other conditionals
distance = distBetweenCities(result, currCity);
cityQueue.enqueue(result);
double distance1;
for (int i = 1; i < cityQueue.getLength(); i ++) {
City result1 = cityQueue.dequeue();
if (result1 != currCity || result1.isMarkedInStack()
|| result1.isMarkedOutOfStack()) { //add other conditionals
distance1 = distBetweenCities(result1, currCity);
if (distance1 < distance) {
distance = distance1;
return result1;
}
cityQueue.enqueue(result1);
}
}
return result;
}
public double distBetweenCities (City city1, City city2) {
double result = Math.sqrt(Math.pow(city2.getX() - city1.getX(), 2) +
Math.pow(city2.getY() - city2.getY(), 2) * 1.0);
return result;
}
public double calcFlightCost (double distance) {
double flightCost;
if (distance < 100.0) {
flightCost = 127.00;
} else {
flightCost = (1.25 * distance) + 32.0;
}
return flightCost;
}
This is what I have thus far, but logically my answer seems wrong for the findNextCity method. and additionally, I don't even know how to approach the second part of the question (below).
I am supposed to go through each element in the cityQueue to determine which one is the
closest to the current city (from the first parameter) using the Euclidean distance
calculated in the next method (distBetweenCities). I must omit cities that already
marked in or out of the stack and the current city itself (otherwise a city will always be
the closest city to itself!). If the found city (with the smallest distance to current city) is
null, return null. Calculate the flight cost to this city and determine if it is affordable with
the band's current money. If so, return the city, but if it is not affordable then return null.
Without providing a complete solution, here are several pointers you might like to consider:
You seem to be dequeuing and enqueuing for the purpose of viewing the head of the queue. If your CircularArrayQueue implements Queue it should have a peek method that views the head without removing it.
The or operators in your filter condition should probably be and (&&) if I'm reading your requirements correctly
As you mention, your logic is pretty flaky in findNextCity it kinda seems to look for the first city that is smaller than the distance to the next city or something like that
You probably need something like:
City closestCity = null;
for (City testCity: cityQueue) {
if (testCity != currCity
&& !testCity.isMarkedInStack() && !testCity.isMarkedOutOfStack()
&& (closestCity == null || distance(currCity, closestCity) > distance(currCity, testCity))
closestCity == testCity;
}
Related
Is there a better way to write this constructor which has multiple if statements and multiple arguments? I'm a noob to programming so any leads would be helpful.
public Latency(final double full, final double cpuOne, final double cpuTwo, final double cpuThree, final double cpuFour) {
if (full > 10.0 || (full <= 0.0)) {
throw new IllegalArgumentException("Must check the values");
}
this.full = full;
if (cpuOne == 0 && cpuTwo == 0 && cpuThree == 0 && cpuFour == 0) {
throw new IllegalArgumentException("not all can be zero");
} else {
if (cpuOne == 0.5) {
this.cpuOne = full;
} else {
this.cpuOne = cpuOne;
}
if (cpuTwo == 0.5) {
this.cpuTwo = full;
} else {
this.cpuTwo = cpuTwo;
}
if (cpuThree == 0.5) {
this.cpuThree = full;
} else {
this.cpuThree = cpuThree;
}
if (cpuFour == 0.5) {
this.cpuFour = full;
} else {
this.cpuFour = cpuFour;
}
}
}
I think this code doesn't need much of context as it is pretty straight forward.
I found out that we can't use switch statements for type double. How to optimize this?
There are a number of possible ways of refactoring the code that you've written, and there are pros and cons of each one. Here are some ideas.
Idea One - use the conditional operator
You could replace the else block with code that looks like this. This is just effectively a shorter way of writing each of the inner if/else blocks. Many people find this kind of form more readable than a bunch of verbose if/else blocks, but it takes some time to get used to it.
this.cpuOne = cpuOne == 0.5 ? full : cpuOne;
this.cpuTwo = cpuTwo == 0.5 ? full : cpuTwo;
this.cpuThree = cpuThree == 0.5 ? full : cpuThree;
this.cpuFour = cpuFour == 0.5 ? full : cpuFour;
Idea Two - move common functionality to its own method
You could have a method something like this
private static double changeHalfToFull(double value, double full) {
if (value == 0.5) {
return full;
} else {
return value;
}
}
then call it within your constructor, something like this.
this.cpuOne = changeHalfToFull(cpuOne);
this.cpuTwo = changeHalfToFull(cpuTwo);
this.cpuThree = changeHalfToFull(cpuThree);
this.cpuFour = changeHalfToFull(cpuFour);
This has the advantage that the key logic is expressed only once, so it's less error prone than repeating code over and over.
Idea Three - use arrays
You could use an array of four elements in the field that stores these values. You could also use an array for the constructor parameter. This has a huge advantage - it indicates that the four CPU values are somehow all "the same". In other words, there's nothing special about cpuOne compared to cpuTwo, for example. That kind of messaging within your code has real value to someone trying to understand this.
public Latency(final double full, final double[] cpuValues) {
// validation conditions go here ...
this.cpuValues = new double[4];
for (int index = 0; index <= 3; index++) {
if (cpuValues[index] == 0.5) {
this.cpuValues[index] = full;
} else {
this.cpuValues[index] = cpuValues[index];
}
}
}
Or a combination
You could use some combination of all these ideas. For example, you might have something like this, which combines all three of the above ideas.
public Latency(final double full, final double[] cpuValues) {
// validation conditions go here ...
this.cpuValues = new double[4];
for (int index = 0; index <= 3; index++) {
this.cpuValues[index] = changeHalfToFull(cpuValues[index]);
}
}
private static double changeHalfToFull(double value, double full) {
return value == 0.5 ? full : value;
}
There are obviously other possibilities. There is no single correct answer to this question. You need to choose what you're comfortable with, and what makes sense in the larger context of your project.
DRY - Don't Repeat Yourself
Each if is essentially the same. Put it in a separate method and call the method once for each cpu* variable.
public class Latency {
private double full;
private double cpuOne;
private double cpuTwo;
private double cpuThree;
private double cpuFour;
public Latency(final double full,
final double cpuOne,
final double cpuTwo,
final double cpuThree,
final double cpuFour) {
if (full > 10.0 || (full <= 0.0)) {
throw new IllegalArgumentException("Must check the values");
}
this.full = full;
if (cpuOne == 0 && cpuTwo == 0 && cpuThree == 0 && cpuFour == 0) {
throw new IllegalArgumentException("not all can be zero");
}
else {
this.cpuOne = initCpu(cpuOne);
this.cpuTwo = initCpu(cpuTwo);
this.cpuThree = initCpu(cpuThree);
this.cpuFour = initCpu(cpuFour);
}
}
private double initCpu(double cpu) {
return cpu == 0.5 ? full : cpu;
}
public static void main(String[] arg) {
new Latency(9.99, 8.0, 7.0, 6.0, 0.5);
}
}
I'm trying to write a class called RailwayStation that will print an array of train (using two different classes I wrote called TIME1and Train. My problem is that I can't understand why the output is arranged in the wrong order.
I assume the problem is in the method inside the class called addTrain, which supposed to add a train trip if there exists an empty cell in the array, and if the trip that wishes to be added does not exists already in the array. another method I used (and might be the problem) is called removeTrain, which receives a parameter of a train trip and removes that from the array. My methods addTrain, removerTrain, and toStringis as follows:
public class RailwayStation {
// declrations of final variables
private final int MAX_TRAINS = 100;
private final int MIN_VAL = 0;
// declrations of instant variables
private Train[] _station;
private int _noOfTrs;
/**
* Empty construter which initialize the instant variables of the class such that the trips array will be in a maximal size
*/
public RailwayStation() {
_station = new Train[MAX_TRAINS];
_noOfTrs = MIN_VAL;
}
/**
* adds a train trip to the trips array
*
* #param f the train trip
* #Returns true if a train trip has been added to the trips array
*/
public boolean addTrain(Train f) {
int i, j;
// boolean found = false;
if (isTrainOnSomeStation(f)) {
return false;
}
else {
for (j = MIN_VAL; j < _station.length; j++) {
if (_station[j] == null) {
_station[j] = f;
_noOfTrs++;
return true;
}
}
return false;
}
}
// a private method that checks if #param f is null
private boolean isTrainOnSomeStation(Train f) {
if (f == null) {
return false;
}
for (int i = MIN_VAL; i < _station.length; i++) {
if (_station[i] != null && _station[i].equals(f)) {
return true;
}
}
return false;
}
/**
* removes a trip from the trips array
* #param f the train trip
* #returns true if the train trip has been removed
*/
public boolean removeTrain(Train f) {
int i, j;
boolean found = false;
for (j = MIN_VAL; j < _station.length && !found; j++) {
if (_station[j] != null) {
for (i = MIN_VAL; i < _noOfTrs && !found; i++)
if (_station[i].equals(f)) {
_station[i] = _station[_noOfTrs];
_station[_noOfTrs] = null;
found = true;
_noOfTrs--;
}
}
}
return found;
}
/** Returns a string which describes all train in the array as apperas in the arrray
* #Returns a string of trains as appears in the arrat
*/
public String toString(){
String str = "The trains today are:" +"\n";
if(_noOfTrs == MIN_VAL){
return "There are no trains today.";
}
else {
String capacity = "";
for (int i = 0; i < _station.length; i++) {
if (_station[i] != null) {
if (_station[i].isFull() == true) {
capacity = "Train is full";
}
else {
capacity = "Train is not full";
}
str += _station[i].toString() + "\n";
}
}
}
return str;
}
}
In order to call the method addTrain I'll be writing:
//Check constructor
RailwayStation rs = new RailwayStation();
//AddTrain
Train f1 = new Train("Haifa",12,0,210,250,250,55);
Train f2 = new Train("Jerusalem",10,50,210,250,250,40);
rs.addTrain(f1);
rs.addTrain(f2);
System.out.println(rs);
//RemoveTrain
rs.removeTrain(f1);
System.out.println(rs);
//First Train to Destination
Train f3 = new Train("Tel-Aviv",11,35,180,100,200,35);
rs.addTrain(f3);
Train f3a = new Train("Tel-Aviv",7,15,180,200,200,35);
rs.addTrain(f3a);
I'm expecting to get the output:
The trains today are:
Train to Jerusalem departs at 10:50. Train is full.
Train to Tel-Aviv departs at 11:35. Train is not full.
Train to Tel-Aviv departs at 07:15. Train is full.
but what I get is:
The trains today are:
Train to Tel-Aviv departs at 11:35. Train is not full.
Train to Jerusalem departs at 10:50. Train is full.
Train to Tel-Aviv departs at 07:15. Train is full.
I've tried to use the debugger in order to understand in what part the order gets wrong, but I can't locate the problem.
When you add the first trains your array is like so:
Train[0] = Haifa...
Train[1] = Jerusalem..
Train[2] = null
Train[3] = null
...
Then you remove Haifa:
Train[0] = null
Train[1] = Jerusalem..
Train[2] = null
Train[3] = null
...
Then you add the other trains:
Train[0] = Tel Aviv..
Train[1] = Jerusalem..
Train[2] = Tel Aviv..
Train[3] = null
...
Does that explain it?
The data structure you're trying to build here is a Stack - but the good news is that java already has one, so no need to do what you are trying to do:
Stack<Train> trains = new Stack<>();
Train f1 = new Train("Haifa",12,0,210,250,250,55);
Train f2 = new Train("Jerusalem",10,50,210,250,250,40);
trains.push(f1);
trains.push(f2);
//RemoveTrain
trains.remove(f1);
//First Train to Destination
Train f3 = new Train("Tel-Aviv",11,35,180,100,200,35);
trains.push(f3);
Train f3a = new Train("Tel-Aviv",7,15,180,200,200,35);
trains.push(f3a);
String str = "The trains today are:" +"\n";
for(Train train: trains) {
str = str + train + "\n";
}
System.out.println(str);
import java.util.*;
public class RoadTrip
{
ArrayList<GeoLocation> roadTrip = new ArrayList<GeoLocation>();
double cheat = 0;
// Create a GeoLocation and add it to the road trip
public void addStop(String name, double latitude, double longitude)
{
GeoLocation loc = new GeoLocation(name + " ", latitude, longitude);
roadTrip.add(loc);
}
// Get the total number of stops in the trip
public int getNumberOfStops()
{
return roadTrip.size();
}
// Get the total miles of the trip
public double getTripLength()
{
double totalDistance = 0;
for (int i = 1; i < roadTrip.size(); i++ )
{
GeoLocation here = roadTrip.get(i);
GeoLocation prev = roadTrip.get(i-1);
totalDistance = totalDistance + here.distanceFrom(prev);
}
return totalDistance;
}
// Return a formatted toString of the trip
public String toString()
{
int i = 0;
String retVal="";
for( Object test: roadTrip)
{
retVal = retVal + ( i + 1 ) + ". " + test + "\n";
i++;
}
return retVal;
}
}
When I return retVal, it returns the values
Powder Springs(-110.97168, -110.97168)
Argonne(-149.00134, -149.00134)
Zeba(-84.74096, -84.74096)
Hyampom(-53.2522, -53.2522)
North Fairfield(47.05816, 47.05816)
When it should return
Powder Springs (70.47312, -110.97168)
Argonne (-12.26804, -149.00134)
Zeba (-3.89922, -84.74096)
Hyampom (84.57072, -53.2522)
North Fairfield (73.14154, 47.05816)
The problem is that the latitude value is for some reason equal to the longitude value.
EDIT: Forgot I was messing with the code and removed the latitude part, put it back in; still gives the same result
Found the error. A person working on it with me changed some code in the geolocation and didn't inform me.
I am going to be honest and up front here. This is homework, but I have become desperate and am looking for anyone to assist me. I have been working on this off and on for over a month and have gone to my instructor multiple times. Basically this program needs to create and sort a linked list that has an int, string and double in each node. It needs to be able to sort by each data type as well as print in input order but once I figure one out I can transfer it to the other data types. Please, everything needs to be "hand made", please do not use any built in commands as I need to create everything as per my instructor's demands.
I attempted to make the linked list and then sort it, but I ran into a problem so I decided to try and sort the list as I create it.
For example: Input the first node, then input the next node in front/behind the first, then put the next where it needs to go... and so forth.
Here is my code (I only focus on the strings):
String repeat = "y";
list1 fChr = null;
list1 p = fChr;
list1 copy = null;
//list1 dCopy = null;
//list1 iCopy = null;
list1 fd = fChr;//front of the double list
list1 fi = fChr;//front of the integer list
list1 fStr = fChr;//front of the string list~
list1 pStr = fStr;
boolean inserted = false;
int iii = 0;
String sss = "";
double ddd = 0.0;
while(repeat.equals("y"))//while the user agrees to adding a new node
{
if(fChr == null)// if the front is empty
{
fChr = new list1();//create a new node by calling object and sets it as the front
p = fChr;
copy = fChr;
sss = fChr.GetS();
iii = fChr.GetI();
ddd = fChr.GetD();
copy.SetS(sss);
copy.SetI(iii);
copy.SetD(ddd);
System.out.println("(1)");
}
else
{
System.out.println("(2)");
if(p!=null)
{
System.out.println("p = "+ p.GetS());
if(p.next != null)
{
System.out.println("p.next = "+ p.next.GetS());
System.out.println("p.next.next = "+ p.next.next.GetS());
}
}
p = fChr;
while(p.next != null)//finds the end of the Linked list
{
System.out.println("(3)");
p = p.next;//moves the pointer p down the list
}
list1 NextNode = new list1();//
p.next = NextNode;
sss = NextNode.GetS();
iii = NextNode.GetI();
ddd = NextNode.GetD();
copy = NextNode;
String gg = "hi";//tests to see if the setter is actually changing the value inside copy(it is not, it prints b)
copy.SetS(gg);
copy.SetI(iii);
copy.SetD(ddd);
System.out.println(copy.GetS());
System.out.println("p = "+ p.GetS());
}
pStr = fStr;
//System.out.println(copy.GetS()+"*");
inserted = false;
if(fStr == null)
{
System.out.println("(4)");
fStr = copy;//fStr = fChr;
inserted = true;
//System.out.println("p.next.next = "+ p.next.next.GetS());
}
else if(copy.GetS().compareTo(fStr.GetS()) < 0)
{
System.out.println("(5)");
//System.out.println("1)p.next.next = "+ p.next.next.GetS());
copy.next = fStr;//ERROR ON THIS LINE
System.out.println("2)p.next.next = "+ p.next.next.GetS());
System.out.println("fChr.next: "+fChr.next.GetS());
fStr = copy;
System.out.println("3)p.next.next = "+ p.next.next.GetS());
inserted = true;
System.out.println("p = "+ p.GetS());
System.out.println("p.next = "+ p.next.GetS());
System.out.println("4)p.next.next = "+ p.next.next.GetS());
}
else if(fStr.next == null && fStr != null)
{
System.out.println("(6)");
fStr.next = copy;
inserted = true;
}
else
{
System.out.println("(7)");
pStr = fStr;
System.out.println("RIP (8)");
while(pStr.next != null && inserted == false)
{
System.out.println("(9)");
System.out.println("RIP");
if(copy.GetS().compareTo(pStr.next.GetS()) < 0)//if it goes between 2 nodes
{
System.out.println("(10)");
copy.next = pStr.next;
pStr.next = copy;
inserted = true;
}
else
{
System.out.println("(11)");
pStr = pStr.next;
}
if(pStr.next == null && inserted == false)// it goes at the end(not necessary bc of the (in order) part)
{
System.out.println("(12)");
pStr.next = copy;
}
}
}
repeat = JOptionPane.showInputDialog("Would you like to add a node [y/n]");
System.out.println("End of Loop");
}
System.out.println(fStr.GetS());
PrintMenu(fChr, fi, fd, fStr);// sends the user to the menu screen
}
From all of my print statements I have (what I think) found the problem. This code runs through twice and upon hitting "y" for the third time, prints "(3)" in an infinite loop. I have found that (say the input for the strings is "c" then "b") "p" is equal to "c", p.next is equal to "b" and p.next.next is equal to "c". So, p is in an infinite loop. I have no idea why it does this, I have a theory that it could be because the front(fChr) changes and then "p" points to it and is just kinda drug along. I also just realized that me trying to set "copy" equal to "NextNode" was unsuccessful and copy just holds the value inside p.next(which is NextNode). That seems correct, but when I try to put something else in, it doesn't work. I could be testing this incorrectly and in that case the setter is correct. Setting is one of the main problems that I seem to be having. I will try to answer as many questions as I can if anyone has any.
Also here is the object in case you would like to see it. Thank you for your time, any help will be appreciated. Please if possible try to keep it relatively simple this is a high school assignment and I am so close and am stumped on how to fix what is wrong. Also, you may have noticed, but I have to use private variables. I am not asking for someone to give me a program that works, I am just asking if you know why what is going wrong is happening and if you know how to fix it. Thank you from the bottom of my heart!
import javax.swing.JOptionPane;
public class list1
{
private int i;
private String s;
private double d;
private String ss = null;
private int ii = 0;
private double dd = 0.0;
list1 next = null;
public list1()
{
String str;
s=JOptionPane.showInputDialog("Enter a String");
String temp =JOptionPane.showInputDialog("Enter an Integer");
i = Integer.parseInt(temp);
String temp2 =JOptionPane.showInputDialog("Enter a Double");
d = Double.parseDouble(temp2);
}
public double GetD()
{
return d;
}
public String GetS()
{
return s;
}
public int GetI()
{
return i;
}
public void SetS(String x)
{
ss = x;
}
public void SetI(int y)
{
ii = y;
}
public void SetD(double z)
{
dd = z;
}
}
This portion of my program seems to be giving me a problem:
public static double[] getBonusAmt(boolean[] bonusEligibility, int[] numYrsFlown, double[] bonusAmt) {
bonusAmt = new double[bonusEligibility.length];
double bonus = 0;
for (boolean b : bonusEligibility) {
for (int i : numYrsFlown) {
if (i >= 9 && b == true) {
bonus = 2410.00;
}
else if (i < 9 && i >= 6 && b == true) {
bonus = 1206.00;
}
else if (i < 6 && i >= 2 && b == true) {
bonus = 515.00;
}
else if (i < 2 && b == true) {
bonus = 0.00;
}
}
}
return bonusAmt;
}
Input/Output:
Name: [joe, james]
Years flown: [2, 2]
Miles flown: [45, 43]
Average miles between pilots: 44
Bonus eligibility: [true, false]
Bonus amount: [0.00, 0.00]
Joe should be earning a bonus because his miles flown is greater than the average, but his amount is zero. The expected bonus amount for Joe should be 515.00 because one, he is eligible for a bonus and two, has only flown for 2 years.
Can anyone see why the bonus amount is always zero even if I enter another person that has flown more than the average?
Your method assigns values to the bonus variable but returns a bonusAmt variable, which is never assigned, so its values remain 0.0.
Your nested loops don't make much sense. It looks like you need a single regular for loop, assuming that the i'th index of bonusEligibility array corresponds with the i'th index of the numYrsFlown array.
public static double[] getBonusAmt(boolean[] bonusEligibility, int[] numYrsFlown) {
double[] bonusAmt = new double[bonusEligibility.length];
for (int i = 0; i < bonusEligibility.length; i++) {
if (numYrsFlown[i] >= 9 && bonusEligibility[i]) {
bonus = 2410.00;
}
else if (numYrsFlown[i] < 9 && numYrsFlown[i] >= 6 && bonusEligibility[i]) {
bonusAmt[i] = 1206.00;
}
else if (numYrsFlown[i] < 6 && numYrsFlown[i] >= 2 && bonusEligibility[i]) {
bonusAmt[i] = 515.00;
}
else if (numYrsFlown[i] < 2 && bonusEligibility[i]) {
bonusAmt[i] = 0.00;
}
}
return bonusAmt;
}
BTW, there's no point in passing the bonusAmt array as an argument to the method, since the method assigns to it a reference to a new array.
You forgot to set bonusAmt to the selected bonus value.
Here is a more object oriented way to do what you want. No need to accept this answer as Eran's solution explains your error perfectly ... This is just another way of doing it ...
public class MainApp {
public static void main(String[] args) {
AirMilesCustomer[] customers = new AirMilesCustomer[] {
new AirMilesCustomer("John", true, 2),
new AirMilesCustomer("Jane", true, 5),
new AirMilesCustomer("Sally", true, 7),
new AirMilesCustomer("Bill", false, 10),
new AirMilesCustomer("Stacy", true, 15)
};
for(AirMilesCustomer customer : customers) {
System.out.println(customer);
}
}
}
class AirMilesCustomer {
private String _name;
private boolean _bonusEligibility;
private int _numYrsFlown;
public AirMilesCustomer(String name, boolean bonusEligibility, int numYrsFlown) {
_name = name;
_bonusEligibility = bonusEligibility;
_numYrsFlown = numYrsFlown;
}
public String getName() {
return _name;
}
public boolean isBonusEligibility() {
return _bonusEligibility;
}
public int getNumYrsFlown() {
return _numYrsFlown;
}
public double getBonusAmount() {
double bonus = 0.00;
if (_numYrsFlown >= 9 && _bonusEligibility) {
bonus = 2410.00;
}
else if (_numYrsFlown < 9 && _numYrsFlown >= 6 && _bonusEligibility) {
bonus = 1206.00;
}
else if (_numYrsFlown < 6 && _numYrsFlown >= 2 && _bonusEligibility) {
bonus = 515.00;
}
else if (_numYrsFlown < 2 && _bonusEligibility) {
bonus = 0.00;
}
return bonus;
}
public String toString() {
return "[" + _name + "][" + _numYrsFlown + "][" + _bonusEligibility + "][" + getBonusAmount() + "]";
}
}