Constructor is ignoring "for" loop(Java) - java

So I feel kind of stupid, because it looks like I'm missing something trivial and I've used loops before, but now we're at the stage in our class where we're using them a lot and I can't seem to find the problem after trying many different combinations, so here goes :
public class BusStop
{
private BusArrival[] _buses;
private int _noOfBuses;
final int MAX_ARRAY_SIZE = 1000;
//================================ CONSTRUCTORS ============================//
public BusStop(int size){ // THIS
_buses = new BusArrival[size]; // IS
// THE
for(int i=0; i< size; i++){ // PROBLEMATIC
if(_buses[i] != null){ // LOOP
_noOfBuses ++;
}
}
}
//=============================== METHODS =================================//
public int getNoOfBuses(){
return _noOfBuses;
}
public boolean add (int line, int pass, Time1 t){ // adds a BussArrival object to an empty array (if there's any).
for (int i=0; i < _buses.length; i++){
if(_buses[i] == null){
_buses[i] = new BusArrival(line, pass, t);
return true;
}
}
return false;
}
Here's a constructor of the BusArrival class, just so you have a general idea :
public BusArrival(int lineNum, int pass, Time1 t){
_lineNumber = lineNum;
_noOfPassengers = pass;
_arrivalTime = t;
}
And here's Time1 constructor from a saparate class, just for this to make sense :
public Time1(int h, int m, int s)
_hour = h;
_minute = m;
_second = s;
}
Here's my main method :
public class Test
{
public static void main (String [] args){
BusStop first = new BusStop(4);
Time1 one = new Time1(10,30,0);
Time1 two = new Time1(10,0,0);
first.add(1,2,one);
first.add(2,3,two);
System.out.println(first.getNoOfBuses());
}
}
Unfortunately the output is "0" when I do that.
Any help would be appreciated.
Thanks.

Here's the problem.
Number of buses is only assigned in the initializer, but in the initializer you aren't adding any buses. Hence you get 0 buses.
When you add a bus, you are not updating number of buses. So you get 0.
You should do _noOfBuses++; when you successfully added a bus. Also, take out that loop in the initializer. When you initialized an array all the entries are null, so the loop is useless :)
Edit:
You seem to be confused about the order of execution of your code.
In your main function, you are first initializing a BusStop. This means he initializer code is ran (which includes the loop in your initializer).
Then you added the two buses. However, note that the loop is already executed, it won't be executed again, because the initializer is only run once.
Therefore, your loop is never going to increment _noOfBuses

You need to increase the number of busses every time that you add a new one.

public BusStop(int size){ // THIS
_buses = new BusArrival[size]; // IS
// THE
for(int i=0; i< size; i++){ // PROBLEMATIC
if(_buses[i] != null){ // LOOP
_noOfBuses ++;
}
}
}
In the above code the array _buses just gets created with all the items pointing to null. In your for-loop you are using if statement to check if there is any non-null value (which in this case does not exist because there are no items in the array). so your _noOfBuses ++; is not reachable.

First Add another constructor with no arguments to your BusArrival class. Just like this.
public BusArrival() {}
Second Modify the BusStop constructor to the following
public BusStop(int size){
_buses = new BusArrival[size];
for(int i=0; i<_buses.length; i++) {
_buses[i] = new BusArrival();
_noOfBuses ++;
}
}

Related

How to start back at beginning of arraylist in a while loop?

I'm trying to solve a puzzle that goes like this: 100 people stand in a circle. The first person kills the person next to him and hands the gun to the next person. Which person is left at the end?
This is what I have so far, but when I run it, it shows an out of bounds exception. I realized that when I write people.remove(i+1), the program runs to the end of the arraylist and has no way to start back at the beginning to continue the pattern. How do I do this?
Thanks for any help!
private void btnEnterActionPerformed(java.awt.event.ActionEvent evt) {
int input = Integer.parseInt(txtInput.getText());
ArrayList <Integer> people = new ArrayList <> ();
for (int i = 0; i < input; i++) {
people.add(i);
}
while (people.size() != 0) {
int i = 1;
people.remove(i+1);
i++;
}
for (int i = 0; i < people.size(); i++) {
lblOutput.setText(" " + people.get(i));
}
The reason you get an out of bound exception is that you check the size to be non-zero, but the call of remove(i+1) with i set to 1 means removing from the third spot in the list, which may not be there. Only the initial element at index zero is guaranteed to be there.
Also note that i++ has no effect, because i is reset back to 1 at the top of the loop's body.
With the condition of people.size() != 0 the only guaranteed thing is that you would be able to remove at index zero. However, this is rather inefficient, because all elements past that index need to be copied. This makes removal an O(n2), which could be slow when the list is really long.
Generally, though, the idiomatic way of managing removals from a list is using ListIterator<T> for removal of zero to a few items, or copying into a separate list and replacing the original list with the new one when you need to remove a significant portion of the list.
As I understand the problem, you need to remove every second person from the list until only one person remains.
The basic problem with your current implementation, is, first, you don't do any range checking (how do you know an element actually exists at i+1) and secondly, you loop until the list is empty, which isn't what you really want.
The basic requirement could use compounding loops, the outer loop checks the size of the list and keeps looping while the size of the List is greater then 1, the second loop processes the list, removing every other person from the list. Note, I don't reset the hasGun flag in the outer loop, this means that on each iteration of the inner loop, the gun continues to pass to the next survivor.
ArrayList<Integer> people = new ArrayList<>();
for (int i = 0; i < 10; i++) {
people.add(i);
}
boolean hasGun = true;
while (people.size() > 1) {
Iterator<Integer> iterator = people.iterator();
while (iterator.hasNext()) {
System.out.print("> " + iterator.next());
if (!hasGun) {
// You get shot...
iterator.remove();
System.out.println(" got shot");
} else {
System.out.println(" shoots");
}
hasGun = !hasGun;
}
}
for (Integer person : people) {
System.out.println(person);
}
This example also makes uses the List's Iterator, this over comes, in part, the issue of the array out of bounds, but you could also use a for-next loop and the hasGun flag as well.
To circulate through your array with indexing, use the remainder operator:
int actual = 0;
while (people.size() != 1) {
people.remove( (actual+1) % people.size() );
actual = (actual+1) % people.size();
}
I just think an ArrayList is not the best data structure for this problem. I find a LinkedList would be more fit. Actually, I found a very easy recursive solution using one. Have a look at this code:
public class Main {
public static int kill(LinkedList<Integer> people) {
assert people.size() > 0;
System.out.println("people: " + people);
if (people.size() < 3)
return people.getFirst();
else {
System.out.println("kill: " + people.remove(1));
people.addLast(people.removeFirst());
return kill(people);
}
}
public static void main(String[] args) {
LinkedList<Integer> people = new LinkedList<>();
for (int i = 0; i <=100; i++) {
people.add(i);
}
int survivor = kill(people);
System.out.println("Last survivor: " + survivor);
}
}
I just remove (kill?) the second member on the list and send the first one back to the end of the list. This process can be repeated until there are 2 people left, in which case you can guess the last survivor will be the first one in the list cause he will kill the second person.
If I had to resolve this problem, I would create my own Person class with a next property pointing to the next person.
Person class:
public class Person {
private int id;
private Person next;
public Person(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public Person getNext() {
return this.next;
}
public void setNext(Person next) {
this.next = next;
}
public void killNext() {
this.next = this.next.next;
}
}
Once that is in place, it's trivial to setup a circular set of linked persons. The algorithm then simply becomes looping each person by following the next property, killing the next person on each iteration. And the loop exits when the next property points to himself, indicating that there is no one left.
Algorithm:
public static void main(String[] args) {
// Setup 100 persons in a linked circle.
Person startingPerson = new Person(1);
Person currentPerson = startingPerson;
for (int i = 2; i <= 100; i++) {
currentPerson.setNext(new Person(i));
currentPerson = currentPerson.getNext();
}
currentPerson.setNext(startingPerson);
// Loop around until a single person is left.
currentPerson = startingPerson;
while (currentPerson != currentPerson.getNext()) {
currentPerson.killNext();
currentPerson = currentPerson.getNext();
}
System.out.println("Surviving person: " + currentPerson.getId());
}
Output:
Surviving person: 73

Some issue with an enhanced for loop-SimpleDotCom

This is a modified example from the book, Head First Java. It's a kind of Battleship game where a 3 element array is being used as the battleship. The user has to guess these 3 locations. Currently, I've hard-coded the values of the ship location to 2,3,4. When the user guesses the correct location "Hit" is printed. If not then "Miss" is printed. If a user guesses all 3 locations then "Kill" is printed. But I have a problem. Currently if the user enters the same location multiple times, it still gives a hit. I tried to fix this by changing the value of a variable that has already been hit (int cell) to "-1". But for some reason this didn't fix it too. Please tell me what I am doing wrong.
public class Game {
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] location = {2,3,4};
SimpleDotCom firstGame = new SimpleDotCom();
firstGame.setLocation(location);
firstGame.checkYourself("2");
firstGame.checkYourself("2");
//firstGame.checkYourself("2");
}
}
public class SimpleDotCom {
int [] loc = null;
int numOfHits = 0;
void setLocation (int [] cellLocation){
loc = cellLocation;
}
void checkYourself(String userGuess){
int guess = Integer.parseInt(userGuess);
String result = "Miss";
for(int cell:loc){
if (guess == cell){
result = "Hit";
numOfHits++;
cell = -1;
break;
}
if (numOfHits==loc.length){
result = "Kill";
}
}
System.out.print("Result: " + result);
System.out.println(" ** Num of Hits: " + numOfHits);
}
}
When you loop over loc, you get an int cell for each location. The problem is that that variable doesn't have any connection to the array, it's only a copy. If you change it, nothing's going to happen to the original array. I suggest looping over loc with a traditional for(;;) and using the current array index within the loop's logic to set the right "cells" to -1.
because you are assigning -1 to local variable. not updating in array actually
for(int cell:loc){ // cell is local copy of element in array is you have array of primitive int
if (guess == cell){
result = "Hit";
numOfHits++;
cell = -1;
break;
}
if (numOfHits==loc.length){
result = "Kill";
}
}
You can use traditional for loop for this or use List which has methods for adding removing elements.
You need to update the array at the correct index, not simply change the value of the cell variable, which only references the array element at the current iteration state.
You should probably use a traditionnal for loop for that, since you cannot get the index for free from an enhanced for loop.
for (int i = 0; i < loc.length; i++) {
//code...
loc[i] = -1; //instead of cell = -1;
}

I have to return a value from a function that is called multiple times and I am unable to do that

I am stuck.
The following function is supposed to return currVm, an integer. But if I make a return I will break the loop and next time when this function is called,the same process will begin again.
What shall I do, so that I continue from where I left off ? I tried making static variables but I that didn't help me.
#Override
public int getNextAvailableVm() {
Set<String> dataCenters = confMap.keySet();
for (String dataCenter : dataCenters) {
LinkedList<DepConfAttr> list = confMap.get(dataCenter);
Collections.sort(list, new MemoryComparator());
int size = list.size() - 1;
int count = 0;
while(size >= 0) {
DepConfAttr dca = (DepConfAttr)list.get(count);
int currVm = dca.getVmCount();
int c = 0;
while(c <= currVm) {
allocatedVm(currVm);
c++;
return currVm;
}
count++;
size--;
}
}
return 0;
}
The for-each loop assigns a new data center that acts as a key for the confMap.The list that I get as a value, is sorted.Then a loop is run till it escapes its size.Inside this while loop, another while loop is run from where a function named allocatedVm of the inherited class is called. A parameter named currVm is passed to it.
This is the variable that I need to return. What shall I do to return this variable ? I have to start from I left off. I mean the next call should appear to be the next step, whatever it was, while executing the loop.
Add List<Integer> object to your class, and change your method as follows:
private Iterator<Integer> availableVms = null;
#Override
public int getNextAvailableVm() {
if (availableVms != null) {
if (availableVms.hasNext()) {
return availableVms.next();
}
return 0;
}
List<Integer> tmp = new ArrayList<Integer>();
Set<String> dataCenters = confMap.keySet();
for (String dataCenter : dataCenters) {
LinkedList<DepConfAttr> list = confMap.get(dataCenter);
Collections.sort(list, new MemoryComparator());
int size = list.size() - 1;
int count = 0;
while(size >= 0) {
DepConfAttr dca = (DepConfAttr)list.get(count);
int currVm = dca.getVmCount();
int c = 0;
while(c <= currVm) {
allocatedVm(currVm);
c++;
tmp.add(currVm);
}
count++;
size--;
}
}
availableVms = tmp.iterator();
return availableVms.hasNext() ? availableVms.next() : 0;
}
The idea is to pre-generate the entire list, and store its iterator for future use. Before entering the method you check if the availableVms iterator has been prepared. If it has been prepared, grab the next item off of it if it's available; otherwise, return zero.
If the list has not been prepared yet, run your algorithm, and add the results to a temporary list tmp. Once the list is ready, grab its iterator, and use it for subsequent invocations.

How can I convert existing procedural code to use classes?

I'm trying to learn Java and basically my approach has been to take the procedural style I learned with python, and apply it to Java. So I never use classes and just put everything in a single class with many methods(which I just use as python functions). I think I've hit a problem, and need to bite the bullet and use classes, but I'm having trouble wrapping my head around how to do it.
To simplify my problem(ignore the poor design- it's just to illustrate the point), I have a program that takes a list and within a for loop does some math on each item(in this case adds 1 to the value of the list). I only want it to do work on 2 items on the list and then stop(in this example it's the first 2 items but in my real program it could be anywhere in the list). Here's the working code that is similar to how I'm already doing it:
No Classes:
public class LearningClasses {
public static void main(String[] args) {
int[] list = new int[]{1,2,3,4,5,6,7,8,9,10};
int[] data_list = new int[list.length];
for (int current_location = 0; current_location<list.length;current_location++) {
for (int i =0; i<100; i++){
if (check_size(data_list) == false ) {
break;
}
data_list[current_location] = (list[current_location]+1);
}
}
//its done now lets print the results
for (Integer item : data_list) {
System.out.println(item);
}
}
private static boolean check_size(int[] data_list) {
// TODO Auto-generated method stub
int count = 0;
for (int item : data_list) {
if (item != 0) {
count++;
if (count>=2) {
break;
}
}
}
if (count>=2) {
return false;
} else {
return true;
}
}
}
The problem with this code is although it works it's inefficient because it calculates the count on every iteration of the second for loop. In my program I cannot put anything above the first for loop but I can put anything below it, so I thought instead of doing the count every time maybe I could use a class to somehow maintain state and just increment the number as oppose to recalculating every time.
With classes:
public class LearningClassesCounter {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] list = new int[]{1,2,3,4,5,6,7,8,9,10};
int[] data_list = new int[list.length];
for (int current_location = 0; current_location<list.length;current_location++) {
//can only put commands in here. Nothing above.
Counter checker = new Counter(data_list);
System.out.println(checker.check_data());
for (int i =0; i<100; i++){
data_list[current_location] = (list[current_location]+1);
}
}
//its done now lets print the results
for (Integer item : data_list) {
System.out.println(item);
}
}
}
class Counter {
private int count; // current value
private boolean continue_or_not;
private int[] data_list;
// create a new counter with the given parameters
public Counter(int[] data_list) {
data_list = this.data_list;
count = 0;
continue_or_not = true;
}
public boolean check_data() {
// TODO Auto-generated method stub
int count = 0;
for (int item : data_list) {
if (item != 0) {
count++;
if (count>=3) {
break;
}
}
}
if (count>=3) {
return false;
} else {
return true;
}
}
// increment the counter by 1
public void increment() {
count++;
}
// return the current count
public int value() {
return count;
}
}
This doesn't work because it thinks the data_list is a null pointer(I know I'm declaring it null, but if I make it private int[] data_list = data_list it doesn't compile either). My ultimate goal is to have some kind of controls, in this case its limiting it to 2 items but I want to also add other limits like total value of al items cannot exceed X or cannot be lower than X and want to save CPU power by not having to do full calculations every time. So I think I need to be able to increment the values and then need to check that those increments haven't exceeded thresholds.
Can anyone help me understand what I'm doing wrong? Am I only wrong with syntax; or am I designing this wrong?
//can only put commands in here. Nothing above.
Counter checker = new Counter(data_list);
System.out.println(checker.check_data());
When you are calling checker.check_data(), its trying to parse through the data_list, but its empty. So, it throws a NullPointerException. The data_list is empty because inside your constructor, you may need to initialize like this this.data_list = data_list instead of data_list = this.data_list (here this.data_list has no reference so NULL)
If you avoid that call, the output will be 2,3,4,5,6,7,8,9,10,11.

Java array sorting in reverse! Need to reverse the reverse

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)?

Categories

Resources