I have a project that is to create an array aRoad with a distinct length. I need to shift elements through this array and delete the object in the end, when it reaches the element just behind aRoad[N].
Let's suppose:
I have a number of objects ("cars") N and an array ("road") with the length L (=4).
i = 0: car1 is at road[0].
i = 1: car1 is at road[1].
i = 2: car1 is at road[2], car2 spawns at road[0].
i = 3: car1 is at road[3], car2 is at road[1].
i = 4: car1 vanishes from the road, car2 is at road[2], car3 spawns at road[0].
My Car-class:
package traffic;
public class Vehicle {
private int bornTime;
private char destination;
public Vehicle(int bornTime, char destination){
this.bornTime = bornTime;
this.destination = destination;
}
public int returnTime() {
return bornTime;
}
public char returnDest() {
return destination;
}
public String toString() {
System.out.print(destination);
return null;
}
}
My problem is: as soon as an object is leaving the array I get an error because the Index is out of Range. I tried to cover this with an IF-condition and thanks to the first answer I was able to create the code update.
How do I get a system, like that to run in Java? My updated approach:
public static void main(String[] args) {
int time = 1;
char[] aRoad = new char[6]; // lane length
Vehicle[] carList = {new Vehicle(1, 'X'), new Vehicle(4, 'Y')};
while(time < 15){
for(Vehicle car : carList){
if (car != null ){
int pos = time - car.returnTime();
if (pos >= 0){
if (pos >= 1){
aRoad[pos-1] = 0;
}
if (pos == (aRoad.length)){
aRoad[pos-1] = 0;
car = null;
}
if (car != null){
aRoad[pos] = car.returnDest();
}
}
}
}
//PRINT ARRAY EACH ITERATION, SET time = time + 1
}
The output looks like:
[...]
time = 6: [ , , Y, , , X]
time = 7: [ , , , Y, , ]
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6
at traffic.Test1.main(Test1.java:19)
So my specific question is:
How do I prevent this exception without setting the X-object (-car) to null?
EDIT
Since the question was too unspecified I threw out all the useless information and tidied it up.
I will answer your most clear question, the answer to which should hopefully set you in the right direction.
but how do I actually create a lot of cars going down the road?
You may be getting stuck here because you haven't utilised your Vehicle object's borntime field. For each iteration of your while loop, a car's new position in the road should be be given by
current time - borntime
So if you have multiple cars and a while loop iterating over your time dimension
Vehicle car1 = new Vehicle(2, "X");
Vehicle car2 = new Vehicle(4, "Y");
...
int time = 2;
while(time < 10){
// calculate road positions
int car1Pos = time - car1.returnTime();
int car2Pos = time - car2.returnTime();
aRoad[car1Pos - 1] = 0;
aRoad[car1Pos] = car1.returnDest();
aRoad[car2Pos - 1] = 0;
aRoad[car2Pos] = car1.returnDest();
...
}
But whenever your code starts looking this repetitive its best to think in terms of more arrays and loops. Put the vehicles in a "Vehicle array" and loop over it to update each car's position in the array
Vehicle[] carList = {new Vehicle(2, "X"), new Vehicle(4, "Y")};
...
int time = 2;
while(time < 10){
for(Vehicle car : carList){
int pos = time - car.returnTime();
aRoad[pos-1] = 0;
aRoad[pos] = car.returnDest();
}
...
}
Once you have that working, the next step would be to dynamically add Vehicles to carList, perhaps every two seconds, and remove them from carList when they get to the end of the road. Using an ArrayList for your carList would be much easier for this part.
Note that I have not tested this code so their might be syntactic mistakes.
Related
My code involves me to calculate the amount of time required for a person in a certain position in a queue to buy burgers with the index of the burgers array showing an integer of the amount of burgers a person ordered. Each time a person at the head buys a burger they are taken to the tail and have one burger removed and 1 time value added. I have to find the amount of time it takes for the person at what position I inputted to find the time to buy all of their burgers.
Here is my code:
import java.util.Queue;
public class A4Q2 {
public int calcTimeReqToBuyBurgers(int[] burgers, int p)
{
Queue<Integer> q = new LinkedList<Integer>();
q.addAll(burgers);
int time = 0;
int i = 0;
numBurg = burgers[p];
while(numBurg > 0) {
int x = q.remove();
x--;
if(x != 0) {
q.add(x);
}
time +=1;
}
return time;
}
public static void main(String[] args) {
A4Q2 ex = new A4Q2();
}
}
I do not know where to go from here or if I am even doing this right. I know my question might look a little messy but I am still new to this website. Can someone help me?
You need not use queue for this, and also in your solution it seems that you are not reducing numBurg(which makes the queue run infinitely) and also you need to keep track of index of numBurg. Then I guess it would work. Below is my solution
int time = 0;
int p_value = burgers[p];
for(int i=0;i<burgers.length;i++){
if(burgers[p] > p_value) time+=p_value;
else time+=burgers[p];
if(i == p) p_value-=1;
}
return time;
Explanation: you need to reduce burgers[p] value from all the elements in array until you reach p but after that you can stop so the prior elements will have only p-1 reduced in them as we can stop after we reach p. and also if someone needs less burgers they will only participate until they reach 0. This would be O(n) with no extra space solution.
public int calcTimeReqToBuyBurgers(int[] burgers, int p)
{
Queue<Integer> q = new LinkedList<Integer>();
for (int burger : burgers){
q.add(burger);}
int time = 0;
int i = 0;
int numBurg = burgers[p];
while(numBurg > 0) {
int curr = q.remove();
if(curr == 1){time ++;}
if(curr > 1){
q.add(curr);
time ++;
}
if(curr == numBurg){
q.add(curr -- );
numBurg --;
time ++;
}
}
return time;
}
public static void main(String[] args) {
A4Q2 ex = new A4Q2 ();
int [] burgers= new int [] {3,2,4,1};
int time=ex.calcTimeReqToBuyBurgers(burgers,1);
System.out.println("time "+time);
}
So I have a program written so far that reads in a csv file of cities and distances in the following format:
Alaska Mileage Chart,Anchorage,Anderson,Cantwell,
Anchorage,0,284,210,
Anderson,284,0,74,
Cantwell,210,74,0,
So the algorithm works and outputs the cities in the order they should be visited following the shortest path using the nearest neighbor algorithm always starting with Anchorage as the city of origin or starting city.
Using this data, the example output for the algorithm is: 1,3,2. I have ran this with a 27 element chart and had good results as well. I am using this small one for writing and debugging purposes.
Ideally the output I am looking for is the Name of the City and a cumulative milage.
Right now I am having working on trying to get the cities into an array that I can print out. Help with both parts would be appreciated or help keeping in mind that is the end goal is appreciated as well.
My thought was that ultimately I may want to create an array of {string, int}
so my output would look something like this..
Anchorage 0
Cantwell 210
Anderson 284
I am able to set the first element of the array to 1, but can not get the 2nd and 3rd element of the new output array to correct
This is the code I am having a problem with:
public class TSPNearestNeighbor {
private int numberOfNodes;
private Stack<Integer> stack;
public TSPNearestNeighbor()
{
stack = new Stack<>();
}
public void tsp(int adjacencyMatrix[][])
{
numberOfNodes = adjacencyMatrix[1].length;
// System.out.print(numberOfNodes);
// System.out.print(Arrays.deepToString(adjacencyMatrix));
int[] visited = new int[numberOfNodes];
// System.out.print(Arrays.toString(visited));
visited[1] = 1;
// System.out.print(Arrays.toString(visited));
stack.push(1);
int element, dst = 0, i;
int min = Integer.MAX_VALUE;
boolean minFlag = false;
System.out.print(1 + "\n");
//System.arraycopy(arr_cities, 0, arr_final, 0, 1); // Copies Anchorage to Pos 1 always
//System.out.print(Arrays.deepToString(arr_final)+ "\n");
while (!stack.isEmpty())
{
element = stack.peek();
i = 1;
min = Integer.MAX_VALUE;
while (i <= numberOfNodes-1)
{
if (adjacencyMatrix[element][i] > 1 && visited[i] == 0)
{
if (min > adjacencyMatrix[element][i])
{
min = adjacencyMatrix[element][i];
dst = i;
minFlag = true;
}
}
i++;
}
if (minFlag)
{
visited[dst] = 1;
stack.push(dst);
System.out.print(dst + "\n");
minFlag = false;
continue;
}
stack.pop();
}
}
Given the existing structure you are using, you can output the cities in the path using:
public void printCities(Stack<Integer> path, int[][] distances, List<String> names) {
int cumulativeDistance = 0;
int previous = -1;
for (int city: path) {
if (previous != -1)
cumulativeDistance += distances[previous][city];
System.out.println(names.get(city) + " " + cumulativeDistance);
previous = city;
}
}
I'd like to answer your question slightly indirectly. You are making life hard for yourself by using arrays of objects. They make the code difficult to read and are hard to access. Things would become easier if you create a City class with appropriate methods to help you with the output.
For example:
class City {
private final String name;
private final Map<City,Integer> connections = new HashMap<>();
public static addConnection(City from, City to, int distance) {
from.connections.put(to, distance);
to.connections.put(from, distance);
}
public int getDistanceTo(City other) {
if (connections.containsKey(other))
return connections.get(other);
else
throw new IllegalArgumentException("Non connection error");
}
}
I've left out constructor, getters, setters for clarity.
Now outputting your path becomes quite a bit simpler:
public void outputPath(List<City> cities) {
int cumulativeDistance = 0;
City previous = null;
for (City current: cities) {
if (previous != null)
cumulativeDistance += previous.getDistanceTo(current);
System.out.println(current.getName + " " + cumulativeDistance);
previous = current;
}
}
I'm a noob in java and I can't seem to figure out how every time I add a new item to my ArrayList the previous ones become all the same as the new one. I did everything I learned from the posts here with the same issue but i still can't seem to figure out what's really wrong. I've been in this for a week now. Hopefully, someone would help.
Here's my code:
private void generation(String numberOfCase,int i, int j){
switch(numberOfCase){
case "N":
int tempN = 0;
if(i == 1)
tempN = 0;
if(i == 2)
tempN = 1;
forGenerating[i][j] = current[tempN][j];
forGenerating[tempN][j] = 0;
State tempNo = new State(forGenerating,current,1,howFar);
adding(tempNo);
//adding(forGenerating,current,1,howFar);
forGenerating[tempN][j] = forGenerating[i][j];
forGenerating[i][j] = 0;
break;
case "E":
int tempE = j+1;
forGenerating[i][j] = current[i][tempE];
forGenerating[i][tempE] = 0;
State tempEa = new State(forGenerating,current,1,howFar);
adding(tempEa);
//adding(forGenerating,current,1,howFar);
forGenerating[i][tempE] = forGenerating[i][j];
forGenerating[i][j] = 0;
break;
case "S":
int tempS = 0;
if(i == 0)
tempS = 1;
if(i == 1)
tempS = 2;
forGenerating[i][j] = current[tempS][j];
forGenerating[tempS][j] = 0;
State tempSo = new State(forGenerating,current,1,howFar);
adding(tempSo);
//adding(forGenerating,current,1,howFar);
forGenerating[tempS][j] = forGenerating[i][j];
forGenerating[i][j] = 0;
break;
case "W":
int tempW = j-1;
forGenerating[i][j] = current[i][tempW];
forGenerating[i][tempW] = 0;
State tempWe = new State(forGenerating,current,1,howFar);
adding(tempWe);
//adding(forGenerating,current,1,howFar);
forGenerating[i][tempW] = forGenerating[i][j];
forGenerating[i][j] = 0;
break;
}
}
private void adding(State temp){
State t = new State(temp);
if(closedList.equals(temp) == false){
forChecking.add(t);
iterator+=1;
}
}
I created an ArrayList of the class I've created for the states.
EDIT. Here's the class State. There are two constructors because I've been editing this code for a week now and doing all possible solutions I've read from the web.
import java.util.Arrays;
import java.util.Random;
public class State {
int[][] arr = new int[3][3];
int[][] parent = new int[3][3];
int g=0,f=0,h=0;
public State(int[][] arr, int[][] parent, int g, int h){
this.arr = Arrays.copyOf(arr, arr.length);
this.parent = Arrays.copyOf(parent, parent.length);
this.g = g;
this.h = h;
solveF();
}
public State(State temp){
this.arr = Arrays.copyOf(temp.arr, temp.arr.length);
this.parent = Arrays.copyOf(temp.parent, temp.parent.length);
this.g = temp.g;
this.h = temp.h;
solveF();
}
private void solveF(){
f = g+h;
}
}
Note that in Java, there is an actual object called ArrayList. Using that might simplify what you are trying to do, or at least making it easier to read as the methods of that class will have your code read like verbs.
The values are the same because you are storing the same array in the new State object. Consider one of the copy methods in the Array utilities. Later in your code you overwrite the value again, but since it's the same array object that was stored, they all look the same.
As to your code, it would be helpful to hear more of what you're trying to do. And maybe see some more surrounding code. However, some things that catch my eye:
The input variable numberOfCase is a string, which is confusing because one might think that should be a number.
While it is possible to switch on a string, consider making those inputs Enums.
In the adding() method, the code closedList.equals(temp) is comparing the objects. "closedList" sounds like a list or array, while "temp" is a State, so they will never be equal. Perhaps you meant to use !closedList.contains(temp)? (though be aware you'll need to Override .equals(Object o) in the State class)
It looks like your code is assuming a 2x2 matrix of values, and that i or j will always be 1 or 2, corresponding to the N,S,E,W string. For that type of case, I would suggest creating your own class with straight forward method names. Perhaps something like:
public class CompassGenerator{
//private fields
//returns previous Compass object, if required...
public Compass generateNorth(int howFar){...}
//Alternatively, pass in Compass object from which to generate
public Compass generateSouth(Compass prev, int howFar){...}
//etc...
}
I'm trying to compress an array of objects that will have empty items interspersed with complete items. I want to put all the full elements at the start in the same order they started with, and the empty elements on the end.
The object in question uses a String field, "name", and an int field, "weight". An empty version has "no name" and 0 respectively. So an array of the type the method needs to deal with will contain something like:
Fred | 4
Bob | 3
no name | 0
Gina | 9
no name | 0
Yuki | 7
After feeding through the method, the array should go Fred, Bob, Gina, Yuki, no name, no name.
My thought for step one was to just figure out which were full and which weren't, so I came up with this:
public void consolidate() {
boolean[] fullSlots = new boolean[spaces.length];
// pass 1: find empties
for (int i = 0; i < spaces.length; i++) {
fullSlots[i] = spaces[i].getName().equals("no name");
}
}
spaces is the array of objects, getName() retrieves the name field from the object.
I'm not sure where to go from here. Suggestions?
EDIT: Okay, here's what Infested came up with:
public void consolidate()
{
int numberOfEmpties = 0, spacesLength = spaces.length;
Chicken[] spaces2 = new Chicken[spacesLength];
for(int i = 0; i < spaces.length; i++)
{
spaces2[i] = new Chicken(spaces[i].getName(),
spaces[i].getWeight());
}
// pass 1: find empties
for (int i = 0, j = 0; i < spacesLength; i++)
{
if (spaces2[i].getName().equals("no name") == false)
{
spaces[j] = new Chicken(spaces2[i].getName(),
spaces2[i].getWeight());
j++;
}
else
{
numberOfEmpties++;
}
}
for (int i = spacesLength - 1; numberOfEmpties > 0 ; numberOfEmpties--, i--)
{
spaces[i] = new Chicken("no name", 0);
}
}
Tested and working.
Java's Arrays.sort is stable, meaning that the relative order of equal elements is not going to change.
This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort.
You can use this property of the sorting algorithm to sort all your elements with a simple comparator:
Arrays.sort(
spaces
, new Comparator() {
public int compare(Object o1, Object o2) {
MyClass a = (MyClass)o1;
MyClass b = (MyClass)o2;
boolean aIsEmpty = "no name".equals(a.getName());
boolean bIsEmpty = "no name".equals(b.getName());
if (aIsEmpty && !bIsEmpty) {
return 1;
}
if (!aIsEmpty && bIsEmpty) {
return -1;
}
return 0;
}
}
);
This will sort all items with non-empty names ahead of the items with empty names, leaving the relative order of both groups of objects unchanged within their respective group.
If your space constraints allow you to create a new array of MyClass, you can go for a simpler algorithm: go through the original array once, and make a count of non-empty items. Then create a new array, and make two indexes: idxNonEmpty = 0, and idxEmpty = NonEmptyCount+1. Then go through the original array one more time, writing non-empty objects to idxNonEmpty++, and empty objects to idxEmpty++.
ill assume its a method of the class:
public void consolidate()
{
int lengthOfSpaces = spaces.length , i, numberOfEmpties = 0;
Type[] spacesNumberTwo = new Type[lengthOfSpaces ];
// pass 1: find empties
for (i = 0; i < lengthOfSpaces ; i++)
{
if(spaces[i].getName().equals("no name") == false)
spacesNumberTwo[i] = new Type(spaces[i].getName(), spaces[i].getInt());
else
numberOfEmpties++;
}
for (i = lengthOfSpaces - 1; numberOfEmpties > 0 ; numberOfEmpties--, i--)
{
spacesNumberTwo[i] = new Type("no name", 0);
}
spaces = spacesNumberTwo
}
Right now I have my array sorting (which is better than getting an error) except it is sorting in the reverse than what I want it to sort in.
public static void sortDatabase(int numRecords, String[] sDeptArr,
int[] iCourseNumArr, int[] iEnrollmentArr)
{
System.out.println("\nSort the database. \n");
String sTemp = null;
int iTemp = 0;
int eTemp = 0;
String a, b = null;
for(int i=0; i<numRecords; i++)
{
int iPosMin = i+1;
for(int j=iPosMin; j<numRecords; j++)
{
a = sDeptArr[i];
b = sDeptArr[iPosMin];
if(a.compareTo(b) > 0)
{
sTemp= sDeptArr[j];
sDeptArr[j] = sDeptArr[iPosMin];
sDeptArr[iPosMin] = sTemp;
iTemp = iCourseNumArr[j];
iCourseNumArr[j] = iCourseNumArr[iPosMin];
iCourseNumArr[iPosMin] = iTemp;
eTemp = iEnrollmentArr[j];
iEnrollmentArr[j] = iEnrollmentArr[iPosMin];
iEnrollmentArr[iPosMin] = eTemp;
}
else if(sDeptArr[j].equals(sDeptArr[iPosMin]) && !(iCourseNumArr[j] < iCourseNumArr[iPosMin]))
{
sTemp= sDeptArr[i];
sDeptArr[i] = sDeptArr[iPosMin];
sDeptArr[iPosMin] = sTemp;
iTemp = iCourseNumArr[i];
iCourseNumArr[i] = iCourseNumArr[iPosMin];
iCourseNumArr[iPosMin] = iTemp;
eTemp = iEnrollmentArr[i];
iEnrollmentArr[i] = iEnrollmentArr[iPosMin];
iEnrollmentArr[iPosMin] = eTemp;
}
else continue;
}
}
}
Again, no array lists or array.sorts. I need just to reverse how this is sorting but I have no idea how.
just do a.compareTo(b) < 0 instead of the > 0
EDIT: I've figured out the problem. But since this is homework (thanks for being honest), I won't post my solution, but here are a few tips:
You are doing selection sort. The algorithm isn't as complicated as you made it. You only have to swap if the two elements you are checking are in the wrong order. I see you have 3 branches there, no need.
Take a look at when you are assigning a and b. Through the inner loop, where j is changing, a and b never change, because i and iPosMin stay the same. I hope that helps.
It's always good to break your algorithm down to discreet parts that you know works by extracting methods. You repeat the same swap code twice, but with different arguments for indices. Take that out and just make a:
-
// swaps the object at position i with position j in all arrays
private static void swap(String[] sDeptArr, int[] iCourseNumArr, int[] iEnrollmentArr, int i, int j)
Then you'll see you're code get a lot cleaner.
First I'd say you need to build a data structure to encapsulate the information in your program. So let's call it Course.
public class Course {
public String department;
public Integer courseNumber;
public Integer enrollment;
}
Why not use the built in sort capabilities of Java?
List<Course> someArray = new ArrayList<Course>();
...
Collections.sort( someArray, new Comparator<Course>() {
public int compare( Course c1, Course c2 ) {
int r = c1.compareTo( c2 );
if( r == 0 ) { /* the strings are the same sort by something else */
/* using Integer instead of int allows us
* to compare the two numbers as objects since Integer implement Comparable
*/
r = c1.courseNumber.compareTo( c2.courseNumber );
}
return r;
}
});
Hope that gets you an A on your homework. Oh and ditch the static Jr. Maybe one day your prof can go over why statics are poor form.
Hmm... I wonder what would happen of you altered the line that reads if(a.compareTo(b) > 0)?