A Sorted Integer List - java

So the original code is
// An (unsorted) integer list class with a method to add an
// integer to the list and a toString method that returns the contents
// of the list with indices.
//
// ****************************************************************
public class IntList {
private int[] list;
private int numElements = 0;
//-------------------------------------------------------------
// Constructor -- creates an integer list of a given size.
//-------------------------------------------------------------
public IntList(int size) {
list = new int[size];
}
//------------------------------------------------------------
// Adds an integer to the list. If the list is full,
// prints a message and does nothing.
//------------------------------------------------------------
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
} else {
list[numElements] = value;
numElements++;
}
}
//-------------------------------------------------------------
// Returns a string containing the elements of the list with their
// indices.
//-------------------------------------------------------------
public String toString() {
String returnString = "";
for (int i = 0; i < numElements; i++) {
returnString += i + ": " + list[i] + "\n";
}
return returnString;
}
}
and
// ***************************************************************
// ListTest.java
//
// A simple test program that creates an IntList, puts some
// ints in it, and prints the list.
//
// ***************************************************************
import java.util.Scanner ;
public class ListTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
IntList myList = new IntList(10);
int count = 0;
int num;
while (count < 10) {
System.out.println("Please enter a number, enter 0 to quit:");
num = scan.nextInt();
if (num != 0) {
myList.add(num);
count++;
} else {
break;
}
}
System.out.println(myList);
}
}
I need to change the add method to sort from lowest to highest. This is what I tried doing.
// An (unsorted) integer list class with a method to add an
// integer to the list and a toString method that returns the contents
// of the list with indices.
//
// ****************************************************************
public class IntList {
private int[] list;
private int numElements = 0;
//-------------------------------------------------------------
// Constructor -- creates an integer list of a given size.
//-------------------------------------------------------------
public IntList(int size) {
list = new int[size];
}
//------------------------------------------------------------
// Adds an integer to the list. If the list is full,
// prints a message and does nothing.
//------------------------------------------------------------
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
} else {
list[numElements] = value;
numElements++;
for (int i = 0; i < list.length; i++) {
if (list[i] > value) {
for (int j = list.length - 1; j > i; j--) {
list[j] = list[j - 1];
list[i] = value;
break;
}
}
}
for (in i = 0; i < list.length; i++) {
}
}
}
//-------------------------------------------------------------
// Returns a string containing the elements of the list with their
// indices.
//-------------------------------------------------------------
public String toString() {
String returnString = "";
for (int i = 0; i < numElements; i++) {
returnString += i + ": " + list[i] + "\n";
}
return returnString;
}
}
The outcome is very wrong. Any one able to steer me in the right direction? I can sort of see why what I have doesn't work, but I can't see enough to fix it.
So I realize I was not very descriptive here the first time. With the exception of the add method modifications the code was not my doing. My assignment is to only touch the add method to sort the array to print out smallest to largest. This is a beginners class and we do little to no practice my only tools for this are some basic understandings of loops and arrays.
I tried redoing it again and came up with this:
if(list[numElements-1] > value){
for(int i=0; i<numElements; i++){
if(list[i]>value){
for(int j = numElements; j>i; j-- ){
list[j] = list[j-1];
}
list[i] = value;
break;
}
}
numElements++;
}
else
{
list[numElements] = value;
numElements++;
}
my input was:8,6,5,4,3,7,1,2,9,10
the output was: 1,10,1,9,10,1,1,2,9,10
this thing is kicking my butt. I understand I want to check the input number to the array and move all numbers higher than it up one space and enter it behind those so it is sorted on entry, but doing so is proving difficult for me. I apologize if my code on here is hard to follow formatting is a little odd on here for me and time only allows for me to do my best. I think break is not breaking the for loop with i like i thought it would. Maybe that is the problem.

The biggest bug I see is using list.length in your for loop,
for(int i = 0; i <list.length; i++)
you have numElements. Also, I think it's i that needs to stop one before like,
for(int i = 0; i < numElements - 1; i++)
and then
for (int j = numElements; j > i; j--)

There are two lines that have to be moved out of the inner loop:
for (int i = 0; i < list.length; i++) {
if (list[i] > value) {
for (int j = list.length - 1; j > i; j--) {
list[j] = list[j - 1];
// list[i] = value;
// break;
}
list[i] = value;
break:
}
}
In particular, the inner break means that the loop that is supposed to move all larger elements away to make room for the new value only runs once.

You might want to include Java.util.Arrays which has its own sort function:
http://www.tutorialspoint.com/java/util/arrays_sort_int.htm
Then you can do:
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
}
else {
list[numElements] = value;
numElements++;
Arrays.sort(list);
//Or: Java.util.Arrays.sort(list);
}
}

As Eliott remarked, you are getting confused between list.length (the capacity of your list) and numElements (the current size of your list). Also, though, you do not need to completely sort the list on each addition if you simply make sure to insert each new element into the correct position in the first place. You can rely on the rest of the list already to be sorted. Here's a simple and fast way to do that:
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
} else {
int insertionPoint = Arrays.binarySearch(list, 0, numElements);
if (insertionPoint < 0) {
insertionPoint = -(insertionPoint + 1);
}
System.arrayCopy(list, insertionPoint, list, insertionPoint + 1,
numElements - insertionPoint);
list[insertionPoint] = value;
numElements += 1;
}
}
That will perform better (though you may not care for this assignment), and it is much easier to see what's going on, at least for me.

Here are some hints.
First, numElements indicates how many elements are currently in the list. It's best if you change it only after you have finished adding your item, like the original method did. Otherwise it may confuse you into thinking you have more elements than you really do at the moment.
There is really no need for a nested loop to do proper adding. The logic you should be following is this:
I know everything already in the list is sorted.
If my number is bigger then the biggest number (which is the one indexed by numElements-1, because the list is sorted) then I can just add my number to the next available cell in the array (indexed by numElements) and then update numElements and I'm done.
If not, I need to start from the last element in the array (careful, don't look at the length of the array. The last element is indexed by numElements-1!), going down, and move each number one cell to the right. When I hit a cell that's lower than my number, I stop.
Moving all the high numbers one cell to the right caused one cell to become "empty". This is where I'm going to put my number. Update numElements, and done.
Suppose you want to add the number 7 to this array:
┌─┬──┬──┬─┬─┐
│3│14│92│-│-│
└─┴──┴──┴─┴─┘
⬆︎ Last element
You move everything starting from the last element (92) to the right. You stop at the 3 because it's not bigger than 7.
┌─┬─┬──┬──┬─┐
│3│-│14│92│-│
└─┴─┴──┴──┴─┘
(The second element will probably still contain 14, but you're going to change that in the next step so it doesn't matter. I just put a - there to indicate it's now free for you to enter your number)
┌─┬─┬──┬──┬─┐
│3│7│14│92│-│
└─┴─┴──┴──┴─┘
⬆︎ Updated last element
This requires just one loop, without nesting. Be careful and remember that the array starts from 0, so you have to make sure not to get an ArrayIndexOutOfBoundsException if your number happens to be lower than the lowest one.

One problem I spotted is that: you are trying to insert the newly added number into the array. However your loop:
for (int i = 0; i < list.length; i++) {
if (list[i] > value) {
for (int j = list.length - 1; j > i; j--) {
list[j] = list[j - 1];
list[i] = value;
break;
}
}
}
is always looped through the total length of the array, which is always 10 in your test, rather than the actual length of the array, i.e. how many numbers are actually in the array.
For example, when you add the first element, it still loops through all 10 elements of the array, although the last 9 slots does not have value and are automatically assigned zero.
This caused your if statement always returns true:
if (list[i] > value)
if you have to write the sort algorithm yourself, use one of the commonly used sorting algorithm, which can be found in Wikipedia.

If any one was curious I finally worked it out. Thank you to everyone who replied. This is what i ended up with.
public void add(int value)
{
if(numElements == 0){
list[numElements] = value;
numElements++;
}
else{
list[numElements] = value;
for(int check = 0; check < numElements; check++){
if(list[check] > value){
for(int swap = numElements; swap> check; swap--){
list[swap] = list[swap-1];
}
list[check] = value;
break;
}
}
numElements++;
}
}

so my original is the same but we have to make another class
A Sorted Integer List
File IntList.java contains code for an integer list class. Save it to your project and study it; notice that the only things you can do are create a list of a fixed size and add an element to a list. If the list is already full, a message will be printed. File ListTest.java contains code for a class that creates an IntList, puts some values in it, and prints it. Save this to your folder and compile and run it to see how it works.
Now write a class SortedIntList that extends IntList. SortedIntList should be just like IntList except that its elements should always be in sorted order from smallest to largest. This means that when an element is inserted into a SortedIntList it should be put into its sorted place, not just at the end of the array. To do this you’ll need to do two things when you add a new element:
Walk down the array until you find the place where the new element should go. Since the list is already sorted you can just keep looking at elements until you find one that is at least as big as the one to be inserted.
Move down every element that will go after the new element, that is, everything from the one you stop on to the end. This creates a slot in which you can put the new element. Be careful about the order in which you move them or you’ll overwrite your data!
Now you can insert the new element in the location you originally stopped on.
All of this will go into your add method, which will override the add method for the IntList class. (Be sure to also check to see if you need to expand the array, just as in the IntList add() method.) What other methods, if any, do you need to override?
To test your class, modify ListTest.java so that after it creates and prints the IntList, it creates and prints a SortedIntList containing the same elements (inserted in the same order). When the list is printed, they should come out in sorted order.

Related

achieving the same result but using a different kind of loop

so this method performs daily checks that adds one day to the displayedDays in order to determine the freshness of an item, so the method adds a day then check if it's rotten by calling the method isRotten() and if it's rotten it removes it the array
for (int i = 0; i < numItems; i++) {
items[i].displayedDays++;
}
for (int i = 0; i < numItems;) {
if (items[i].isRotten()) {
if (removeItem(i)) {
if (i > 0) {
i--;
}
continue;
}
}
i++;
}
this is also another method that uses the same loop and if's
so this method is supposed to remove the sweets from the array ( the array has two types of items bread and sweets)
double totalSweetsPrice = 0;
int count = numItems;
for (int i = 0; i < count;) {
Item item = items[i];
if (item instanceof Sweet) {
totalSweetsPrice += item.getPrice();
if (removeItem(i)) {
if (i > 0) {
i--;
}
continue;
}
}
i++;
}
and I don't understand the middle part and was hoping that there is a different loop or something whilst getting the same result
this was how a wrote the daily check method
for (int i = 0; i < numItems; i++) {
items[i].displayDays++ ;
if(items[i].isRotten())
removeItem(i); }
and the output was wrong
Most of the code stems from the fact you change the elements positions in an array you're enumerating. A different kind of data structure, more suited to the removal of elements, such as a linked list, would simplify greatly your code and would be more efficient.
As FooBar said, you can’t both iterate an ArrayList and remove items from that same ArrayList. So you need to separate the conditions. For example:
for (int i = 0; i < items.size(); i++) {
items.get(i).displayedDays++;
}
int i = 0:
while (i < items.size()) {
if(items.get(i).isRotten()) {
items.remove(i);
// don’t increment our counter here because now
// we’ve changed what object exists in the ArrayList
// at this index position
} else {
// only increment our counter if the item in that index
// is good, so we can now move on to check the next item
i++;
}
}
Why not use ArrayList.removeAll(Collection c)? This way, you can create a Collection, such as an ArrayList, iterate through the original list, add all rotten items to your new collection, then call removeAll on the original ArrayList after iterating through the entire list? That way, you don't have to worry about modifying the list while you're iterating through it.

Why is my if loop is getting skipped while my condition is true?

I am coding a small program where I add an an ArrayList of Strings and I have a method that removes every String ending with S, it is working fine for 4 of elements but it seems to skip one.
Minimum reproducible example:
import java.util.ArrayList;
public class sList {
public static void main(String [] args) {
ArrayList<String> sList=new ArrayList<String>();
sList.add("leaf");
sList.add("leaves");
sList.add("box");
sList.add("boxes");
sList.add("phones");
sList.add("phone");
method m=new methods();
System.out.println(m.removePlurals(sList));
}
}
\\ that is my main method
import java.util.ArrayList;
public class method {
ArrayList<String> removePlurals(ArrayList<String> s) {
for (int i = 0; i < s.size(); i++) {
char c = s.get(i).charAt(s.get(i).length() - 1);
if (c == 's') {
s.remove(i);
}
}
return s;
}
}
I am getting as an output: [leaf, box, phones, phone] so it is skipping "phones"
Any help?
Think about what happens when after you removed "boxes" from the list. The index of "phones" decreases by 1. If it is originally the nth item in the list, it is now the (n-1)th item in the list, isn't it? So now "phones" is at the same position in the list as where "boxes" originally was. On the other hand, i increases by 1.
Now you should see the problem, to check for "phones", i should remain the same because after removing "boxes", the index of "phones" decreased by 1.
Solution, just loop from the end of the list to the start, and you won't have this problem:
for (int i = s.size() - 1; i >= 0; i--) {
char c = s.get(i).charAt(s.get(i).length() - 1);
if (c == 's') {
s.remove(i);
}
}
It is because at the moment you remove an item of a list, the list size is less than at the begining and when your counter is incremented, points to the next one element (skips one).
Yous can solve that just looping the list on the other way, as follow:
ArrayList<String> removePlurals(ArrayList<String> s) {
for (int i = s.size()-1; i >= 0; i--) {
char c = s.get(i).charAt(s.get(i).length() - 1);
if (c == 's') {
s.remove(i);
}
}
return s;
}
}
This is happening because the list you are iterating is being updated in the same loop. So when you remove one element is previous iteration it's index is being updated and element is not picked up at all by loop. So the solution should be like:
1) Create new list and return that:
ArrayList<String> removePlurals(final ArrayList<String> s) {
final ArrayList<String> updatedList = new ArrayList<String>();
for (int i = 0; i < s.size(); i++) {
final char c = s.get(i).charAt(s.get(i).length() - 1);
if (c != 's') {
updatedList.add(s.get(i));
}
}
return updatedList;
}
2) Using Iterator:
ArrayList<String> removePlurals(final ArrayList<String> s) {
final Iterator<String> itr = s.iterator();
while (itr.hasNext()) {
final String x = itr.next();
if (x.charAt(x.length() - 1) == 's') {
itr.remove();
}
}
return s;
}
Aside from the issue reported in the question: you have the issue that removing from the middle of an ArrayList one element at a time is really inefficient, because you keep on shifting all of the elements between (i+1) and the end of the list along by one position - and then you do it again for most of them.
Performance should not be your first concern - slow, correct code is always better than fast, incorrect code - but you should keep in the back of your mind issues that some things are worth avoiding: in this case, it is repeated removal from the middle of an ArrayList.
A better solution is not to keep shifting the elements, but rather just to move them once.
Unlike the solutions which iterate the list backwards, this can be done iterating forwards, which feels more natural (to me, at least).
int target = 0;
for (int i = 0; i < s.size(); ++i) {
if (!s.get(i).endsWith("s")) {
s.set(target, s.get(i));
target++;
}
}
This shifts each element that you are going to keep to its new position. All that then remains is to chop off the end of the list:
while (s.size() > target) s.remove(s.size()-1);
Or, in a single operation:
s.subList(target, s.size()).clear();
All together:
int target = 0;
for (int i = 0; i < s.size(); ++i) {
if (!s.get(i).endsWith("s")) {
s.set(target, s.get(i));
target++;
}
}
s.subList(target, s.size()).clear();
Note that this is effectively what is done by ArrayList.removeIf:
s.removeIf(e -> e.endsWith("s"));
(removeIf does a little bit more, in that it does the removal in a failure-atomic way, that is, if the e.endsWith fails for some reason, such as a null element, the list is left untouched rather than partly updated).

Making 2 Modifications to a Bubblesort Program

I have to make the following 2 modifications to a simple bubblesort program:
After the first pass, the largest number is guaranteed to be in the highest-numbered element of the array; after the second pass, the two highest numbers are “in place”; and so on. Instead of making nine comparisons on every pass, modify the bubble sort to make eight comparisons on the second pass, seven on the third, and so on.
The data in the array may already be in the proper order or near proper order, so why make nine passes if fewer will suffice? Modify the sort to check at the end of each pass if any swaps have been made. If none have been made, the data must already be in the proper order, so the program should terminate. If swaps have been made, at least one more pass is needed."
Any help as to how I should approach these would be greatly appreciated!
//sort elements of array with bubble sort
public static void bubbleSort (int array2[])
{
//loop to control number of passes
for (int pass = 1; pass < array2.length; pass++)
{
//loop to control number of comparisons
for (int element = 0; element < array2.length - 1; element++)
{
//compare side-by-side elements and swap them if
//first element is greater than second element
if (array2[element] > array2[element + 1]){
swap (array2, element, element + 1);
}
}
}
}
//swap two elements of an array
public static void swap (int array3[], int first, int second)
{
//temporary holding area for swap
int hold;
hold = array3[first];
array3[first] = array3[second];
array3[second] = hold;
}
I think this will do for you. A boolean is added to check and the run (j) is subtracted from the input.length for each run.
public static int[] bubbleSort(int input[])
{
int i, j, tmp;
bool changed;
for (j = 0; j < input.length; j++)
{
changed = false;
for (i = 1; i < input.length - j; i++)
{
if (tmp[i-1] > input[i])
{
tmp= input[i];
input[i] = input[i-1];
input[i-1] = tmp;
changed = true;
}
}
if (!changed) return input;
}
return input;
}

Print first 20 items in array in reverse, then print the next 20 in reverse, and so on

so I'm working on my Java assignment where I'm given a big array.
I'm told to print the first 20 items in the array in reverse order,
then print the next 20 items in reverse order again, and so forth until I reach the end of the array.
I was able to work out how to print the first items in reverse, but then I'm having trouble implementing something that would let me continue where I left from the original array.
I'm also only allowed to have 21 items stored at a time.
Here's what I have so far (50items instead of 20)
public static void doIt(BufferedReader r, PrintWriter w) throws IOException {
LinkedList<String> s = new LinkedList<String>();
int counter = 0;
int max = 50;
for (String line = r.readLine(); line != null; line = r.readLine()) {
if (counter < max) {
s.addFirst(line);
counter++;
}
if (counter == max) {
for (String n : s) {
System.out.println(n);
}
}
}
}
I was wondering if someone can help me out, not sure what I can do from here.
First, you need to print the list whenever counter hits a multiple of 20 as well as when it hits max. Then, after you print the contents of s, clear the list:
s.clear();
That will remove all elements so it will fill up again. You also need to print the list after the for loop exits, otherwise the last few items will be left unprinted.
Note that you are not using an array anywhere in this code. It's not clear that you are following the spirit of the assignment by using a LinkedList. But only you know what the rubric is.
I hope this can get you started:
void example() {
for (int i = 0; i < 50; i++) { //fill array to be read (for this example)
myArray[i] = i;
}
readback();
}
void readback() {
int batch = 1; //represents a portion of the read operation
int batchSize = 20; //the size of the read portion
int pos = 0; //the current index of the array while it is being read
int hi; //the top of the batch
int lo; //the bottom of the batch
while (pos < myArray.length) {
if (batch*batchSize<myArray.length) { //make sure you are not going over the array boundary
hi = batch*batchSize;
lo = hi - batchSize;
} else {
hi = myArray.length;
lo = pos;
}
for (int i = hi - 1; i >= lo; i--) { //read
System.out.println(myArray[i]);
pos++;
}
batch++; //go to the next batch
}
}
For this part of the question:
I'm told to print the first 20 items in the array in reverse order, then print the next 20 items in reverse order again, and so forth until I reach the end of the array.
One simple solution would be to:
iterate 20 places in the array
store this position in a temp index
iterate back 20 places printing the array
repeat process from stored temp index
Also, keep in mind if the last print might have less than 20 elements.
int size = 20; // size of reversed chunks
for(int i = 0; i < array.length; i += size) {
int j = (i + (size - 1) < array.length) ? (i + size - 1) : array.length - 1;
for(; j >= i; j--) {
System.out.print(array[j] + " ");
}
}
However, there is no array in your code so I am not sure what you meant by that. You are reading values from a file and then using a LinkedList to print them in reverse. A better, more natural data structure, for printing in reverse (as well as most "reversal" operations) would be a Stack although Java's implementation for LinkedList is implemented such that it allows for Stack (LIFO) behavior. It is just generally used as a Queue (FIFO) structure. My answer will use a LinkedList as well to make it consistent with your approach but think about a Stack in this situation in the future.
So, since you are reading numbers, line by line from a file, here is what you can do:
You can read and insert the numbers at the top of a LinkedList until you reach the max value or the end of file
You already have that part working
Print all the numbers by removing them from the top of the LinkedList which will make them in reverse order
You are printing them but not removing them or clearing the list by calling s.clear()
Once you reach the end of file you could end up with values still in the LinkedList because you reached end of file before you reached max items and the loop finished but nothing was printed. Print these values as well.
Another thing, it seems like you are not writing to the file so you don't need the PrintWriter parameter of the function.
Here is the code:
public static void doIt(BufferedReader r) throws IOException {
LinkedList<String> s = new LinkedList<String>();
int counter = 0;
int max = 50;
for (String line = r.readLine(); line != null; line = r.readLine()) {
if (counter < max) {
s.addFirst(line);
counter++;
}
if (counter == max) {
while(!s.isEmpty()) { // remove and print in reverse order
System.out.println(s.removeFirst());
}
counter = 0; // reset counter
}
}
// print the remaining elements, if they exist
while(!s.isEmpty()) { // remove and print in reverse order
System.out.println(s.removeFirst());
}
}

Building a bag class in Java

I'm in dire need of help with this project. I'm trying to implement a Bag class for a programming assignment, and I'm getting hung up on the addAll(), Union(), and equals(), methods.
Edit: According to the assignment, addAll() is supposed to add all of the the objects from the second array into the first. I'm no longer getting an error when I run it, but for some reason it will not add all of the elements from the second array, it will only add the first 2. Thanks guys, this one is working perfectly now!
Edit: For Union(), I'm supposed to create a third bag that will contain all the contents of the first 2 bags. I was getting an ArrayIndexOutOfBoundsException when running this method. I've updated the code following biddulph.r and it's also working great. Thanks again!
Edit: "First attempt" And for equals(), it's supposed to check the size of the bags to make sure they are equal in size, then check to see if they contain the same numbers. So as it's written now, my equals() method will compare sizes and return the boolean value for that, but I'm unsure of how to make it compare the actual values.
import java.util.Arrays;
import javax.swing.*;
public class bag {
int maxSize = 10; //Size of the arrays
int count = 0; //Number of items stored in the array
int[] a;
int[] b;
bag c;
bag d;
public bag() {
//for(int i = 0; i < maxSize; i++){
//a[i] = (int)(1+Math.random()*100);
//}
a = new int[maxSize];
}
public String bagString() {
return Arrays.toString(a);
}
public void add(int b) {
try {
a[count] = b;
count++;
} catch (ArrayIndexOutOfBoundsException n) {
JOptionPane.showMessageDialog(null, "Array is full, element will not be added");
}
}
public void removeRandom() {
int i = (int)(1 + Math.random() * (count - 1));
a[i] = a[count - 1];
a[count - 1] = 0;
count--;
}
public void remove(int b) {
for (int i = 0; i < maxSize; i++) {
if (contains(b)) {
a[i] = a[count - 1];
}
}
}
public boolean isEmpty() {
if (count == 0) return true;
else return false;
}
public boolean contains(int b) {
int tf = 0;
for (int i = 0; i < maxSize; i++) {
if (a[i] == b) tf = 1;
}
if (tf == 1) return true;
else return false;
}
public int size() {
return count;
}
public void addAll(bag c, bag d) {
if (a.length >= c.size() + d.size()) {
for (int i = 0; c.size() <= d.size(); i++) {
c.add(d.a[i]);
}
}
}
public void union(bag c, bag d) {
bag bigger = new bag();
for (int i = 0; i < c.size(); i++) {
bigger.add(c.a[i]);
}
for (int i = 0; count < d.size() - 1; i++) {
bigger.add(d.a[i]);
}
System.out.println(bigger.bagString());
}
public boolean equals(bag c, bag d){
if(c.size() != d.size()){
return false;
}else{
for(int i = 0; i < c.union(c, d).size(); i++){
if(c.union(c, d).contains(c.a[i]) && c.union(c, d).contains(d.a[i])){
return true;
}
}
return false;
}
}
}
I really appreciate any help you guys can give me, thanks.
EDIT: Thanks to everyone for your help, you guys are life savers.
Your problem for addAll() is here
if (a.length >= c.size() + d.size()) {
for (int i = 0; c.size() <= d.size(); i++) {
c.add(d.a[i]);
}
}
You shouldn't be adding elements until your c bag becomes bigger than d, you should be adding all of d's elements to c.
for (int i = 0; i < d.size(); i++) {
c.add(d.a[i]);
}
So the part of the assignment you are having issue with is:
public void addAll(bag c, bag d){
if (a.length >= c.size() + d.size()) {
for (int i = 0; c.size() <= d.size(); i++) {
c.add(d.a[i]);
}
}
}
which you say is supposed to add all of the the objects from the second array into the first.
If you break that down and apply it to your addAll() method, it sounds like you are supposed to be adding all of the items in bag "d" into bag "c".
Your for loop is saying start i at 0, and add 1 to it until the size of c is less than or equal to d.
What it should be saying is start i at 0, and add 1 to it until you have gone through every item in d.
That would look like this:
for (int i = 0; i < d.size(); i++){
c.add(d.a[i]);
}
i is increased every time you go through the for loop, and i will stop increasing when you have got to the size of d (the second condition). At this point you will exit the for loop. You don't have to worry about the size of c.
In fact you can probably get rid of the if (a.length >= c.size() + d.size()) line as well.
I hope my explanation helps you understand why the changes have been made to the method.
I think you have a lot of problems with the design of the class that you should address first. If you are representing the bag as a static or dynamic array then you only need one array, not 2. You also don't need two bags inside each bag as attributes, that doesn't make any sense; all you should have left is the size of the bag or count and the array to hold all the elements (which are integers in your case). Also, avoid naming parameters for functions and attributes for the class the same way. Not doing so might confuse the compiler and will require code like self.attributeName to use attributes; otherwise, the compiler assumes you're talking about the parameter.
If you make these changes, the rest should be straight-forward from here. Since it's an assignment, you should make these changes and try again because you won't learn if we provide the answers for you; you'll see it will be much easier once you structure it correctly.
P.S. it's a convention to start a class name with a capital letter. Bag and not bag
addAll
There's a couple of problems with this function as written. First is that it's confusing to the caller. The code using this method would be something like this:
Bag bag1 = ...
Bag bag2 = ...
Bag bag3 = ...
bag1.addAll(bag2, bag3)
...or perhaps bag2.addAll(bag2, bag3). The function is intended to add elements from one bag in to another bag, so why does the caller have to specify three different bags? There's only two involved. You should either make the function static, so it can be called like Bag.addAll(bag1, bag2) or (better) make it totally clear who's getting elements added by making it take a single argument bag1.addAll(bag2).
Second problem is that the function isn't implemented correctly, but I think that's because you're getting confused because you've got three bags involved instead of two. To sketch out how it should be fixed:
Bag target = ...
Bag source = ...
if (target.a.length >= target.size() + source.size()) {
for (int i = 0; i < source.a.length; i++) {
target.add(source.a[i]);
}
}
Good variable naming is your friend.
union
You haven't specified what problem you're having with your implementation, so I'm not going to simply rewrite it for you. Edit your question with the problem, and I'll help.
However, this is an excellent example of a method that should be static (a Factory method, in fact). It should be able ot be called like: Bag biggerBag = Bag.union(bag1, bag2).
EDIT after his comment regarding the .union problem
The problem with .union is that you're looping through each bag using some else's size. It boils down to, if you want add each element from source in to target, you should be only counting elements from source, as so:
bag bigger = new bag();
for (int i = 0; i <= c.size(); i++) {
bigger.add(c.a[i]);
}
note that your method does not protect against the bigger bag not being big enough. You should have a check to make sure that it is BEFORE the loops, or even better just create a big enough bag.
equals
Again, you need to show that you've tried to write it, and then ask a question specifying what you need help with. Update your question and I'll help.
Your method:
public void addAll(bag c, bag d) {
if (a.length >= c.size() + d.size()) {
for (int i = 0; c.size() <= d.size(); i++) {
c.add(d.a[i]);
}
}
}
betrays your lack of understanding of Object Oriented programming.
Remember that the method addAll() is already acting on a bag, and so you should not need to specify 2 bags in the arguments.
Calling example:
mybag.addAll(yourBag);
would demonstrate a possible usage - it would add all contents of yourBag into myBag.
I'll give you this method for free (assuming that the array 'a' contains the contents of the bag - something I'm not sure about because your variable names aren't clear):
public void addAll(Bag otherBag) {
for (int i : otherBag.a) {
add(i);
}
}
The above method will copy all contents of otherBag into this bag.
Another thing I noticed - you also have a b[] instance variable - what's that for?
You also have 2 other bag instance variables. Not sure why.

Categories

Resources