I expected this to print [] but it prints [1, 3, 5, 7, 9]. Can anyone explain why every index is not removed?
Thanks.
import java.util.ArrayList;
import java.util.List;
public class test {
public static void main (String args[])
{
ArrayList<Integer> aL= new ArrayList<>();
int[] aList = {0,1,2,3,4,5,6,7,8,9,10};
for(int i: aList){
aL.add(i);}
mystery(aL);
System.out.println(aL);
}
public static void mystery(List<Integer> nums)
{
for (int k = 0; k < nums.size(); k++)
{
nums.remove(k);
}
}
}
If you want to remove all the elements from your array, you have to start at the end and work backwards, otherwise your indices will get messed up.
Consider your array is as follows: {0, 1, 2, 3}
Now you want to loop through and delete starting with the 0th index. So the first loop happens, and now your array looks like this: {1, 2, 3}.
Next time, you loop through, you are deleting the 1st index, but this fails to take into account that the array shifted left, so now your array is: {1, 3}.
I think you can see the problem. So either you continue to delete at index 0: nums.remove(0) or you can start at the end of the array and work back.
Every time you remove an element the list shifts left to fill that element from the higher indices, so when you then increment k you're skipping the element after the one you just removed. You can remove from index 0 until the list is empty.
I usually build my for loops backwards to avoid this problem. It's especially helpful in situations where you want to delete a number of items sporadically from within a list without having to worry about reindexing causing you to remove the wrong items. You can try this:
for(int k = nums.size()-1; k >= 0; k--) nums.remove(k);
Related
I'm trying to generate an array of 5 non-repeating integers in Java, but there are still repeats when I run it. Here's my code so far:
public int[] generateCode(){
code[0] = (int)Math.round(Math.random()*8+1); // initialize first number so it won't be compared against
for(int i=1; i<code.length; i++){
code[i] = (int)Math.round(Math.random()*8)+1;
for(int j=0; j<i; j++){
while(code[i]==code[j]){
code[i] = (int)Math.round(Math.random()*8)+1;
}
} // end inner for loop
} // end outer for loop
return code;
} // end generateCode method
Any help is very much appreciated!
So, your for-loop is checking for repeated characters, BUT each time you generate a new value (in the while-loop) you're not checking to see if the value exits before j.
There are a number of possible ways you might address this issue, I prefer ones which uses Collections.shuffle, but assuming that you can't use features like Arrays, Collections, List, Set or possibly even streams, we need to work with what we have, arrays.
Since you have a small range of acceptable values which need to fit into an even smaller range, a simple solution might be to generate a "master" list of allowed values and randomly select a value from the master list, tracking which values you've already picked.
Sounds more complicated then it actually is, for example...
public int[] generateCode() {
int[] masterValues = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int[] codes = new int[5];
Random rnd = new Random();
int index = 0;
while (index < codes.length) {
int lookupIndex = 0;
do {
lookupIndex = rnd.nextInt(masterValues.length);
} while (masterValues[lookupIndex] == 0);
codes[index] = masterValues[lookupIndex];
masterValues[lookupIndex] = 0;
index++;
}
return codes;
}
This creates a "master" list of values. It then randomly calculates a "lookup" index, checks to see if the value in the master list is 0 or not, if not, it assigns it to the next index in the codes array and sets the value in the master list to 0, otherwise it generates a new random index and tries again. This all repeats till it fills the codes array
So doing something like...
System.out.println(Arrays.toString(generateCode()));
System.out.println(Arrays.toString(generateCode()));
System.out.println(Arrays.toString(generateCode()));
System.out.println(Arrays.toString(generateCode()));
could print (because it's "random")...
[8, 1, 4, 7, 5]
[9, 6, 2, 1, 8]
[6, 5, 9, 4, 7]
[2, 5, 3, 1, 4]
There are much easier ways to do this. Using a Set<Integer> would be one. Here is another.
List<Integer> list = new ArrayList<>(List.of(1,2,3,4,5,6,7,8));
Collections.shuffle(list);
System.out.println(list.subList(0,5));
prints something like
[4, 5, 8, 2, 1]
As was pointed out to me, you may not be allowed to use or know about collections. But I would recommend you at least make a helper method to check for duplicates to reduce the clutter. Something like the following:
public boolean contains(int[] arr, int n) {
for (int v : arr) {
if (v == n) {
return true;
}
}
return false;
}
Then you can keep checking the current value to be false before you add it. Once it works it also lets you focus on other aspects of your code.
For an assignment, I have to write some Bogosort code, and empirically determine the program's Big O notation.
However, I am unsure of whether the code works, because even though it sorts it for 3 and 4 element arrays of type int, I don't think it should be doing it in 0 ms.
Conversely, it's taking really long for 5 elements (still haven't gotten a successful case within 15 minutes yet), which indicates to me that there may be something wrong with the program. Since there are no errors being thrown, I believe any problem found would be a logic error.
I've tried running the IDE debugger on the program. Each of the methods used for the bogosort seemed to be working as intended, although I was not able to reach the case where it sorted an array properly while using the debugger.
However, by changing the values of the array to have it already sorted, I was able to test the case where the array was sorted, and the code was executed successfully.
This seems to indicate that the problem if there is any, would have to do with a logic error in sorting, where the sort method is somehow never getting to the correct solution.
The file is as shown below, and is commented.
Any suggestions for the program will have to pertain to the current structure (no adding methods, no using ArrayLists) since this is a homework assignment.
public class BogoSort {
public static void main(String[] args) {
int[] myArray = {20, 142, 115, 120, 140};
//sets start time
long start = System.currentTimeMillis();
bogoSort(myArray);
//sets end time
long end = System.currentTimeMillis();
printArray(myArray);
//print time (end time - start time)
System.out.println((end - start) + "ms");
}
// Places the elements of a into sorted order.
public static void bogoSort(int[] a) {
while(!isSorted(a)){
//calls the shuffle method if it's not sorted
shuffle(a);
}
}
// Returns true if a's elements are in sorted order.
public static boolean isSorted(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
if (a[i] > a[i+1]) {
//returns false if the number in this index is greater than
//the number in the next index aka not sorted
return false;
}
}
//else return true
return true;
}
// Shuffles an array of ints by randomly swapping each
// element with an element ahead of it in the array.
public static void shuffle(int[] a){
Random r = new Random();
for(int i = a.length - 1;i > 0;i--){
//random number between 0 and i
int j = r.nextInt(i);
//calls swap method
swap(a, i, j);
}
}
// Swaps a[i] with a[j].
public static void swap(int[] a, int i, int j) {
//temp variable to hold value of a[i] for swap
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void printArray(int[] a)
{
for(int i = 0; i < a.length; i++)
{
System.out.println(a[i]);
}
}
}//end of BogoSort class
Results should be as follows:
20
115
120
140
142
???ms
??? is a value for how long the program runs for, maybe about 720 ms, if I understand bogosort's Big O notation correctly.
Currently, I have not gotten a result for an array above a size of 4.
The time it takes for an array of 3 or 4 elements to sort is 0 ms, which is a bit odd to me, I feel like it should be about 24 ms for 3 elements, and 120 ms for 4 elements.
The result of the sorting of a 3 or 4 element array is that the numbers are sorted correctly, as per the expected result.
Your shuffle algorithm is broken due to an off-by-1 error. If you try it with int[] myArray = {2,1,3};, you'll see that it fails to complete for 3 elements as well.
When dealing with randomness, it's better to use statistics than eyeballing, because it's hard to notice this at a glance:
$ java BogoSort | head -n 100000 > file
$ sort file | uniq -c
33325 [1, 3, 2]
33315 [2, 1, 3]
33360 [3, 2, 1]
As you can see, you only ever generate 3 out of 6 possible permutations.
When you shuffle, like your comment indicates, you swap each element with one earlier in the array. You need to additionally allow the element to stay in place. You can do this by adding 1 to the index you choose:
// Shuffles an array of ints by randomly swapping each
// element with an element ahead of it in the array **or leave it in place**.
public static void shuffle(int[] a){
Random r = new Random();
for(int i = a.length - 1;i > 0;i--){
//random number between 0 and i
int j = r.nextInt(i+1); // <-- +1 here to select the current element
//calls swap method
swap(a, i, j);
}
}
The result now looks better (I rigged the program to keep printing even when it's sorted):
$ sort file | uniq -c
16807 [1, 2, 3]
16579 [1, 3, 2]
16745 [2, 1, 3]
16697 [2, 3, 1]
16361 [3, 1, 2]
16811 [3, 2, 1]
and indeed, it now finishes in 0-1ms. Running it on 8 numbers takes ~10ms, and 10 numbers take ~150ms, in line with the expected factorial curve.
The accepted answer correctly identified the fault and a straight forward solution.
I attempted to dig a bit deeper into why there were missing permutations. From that answers suggested starting point, [2,1,3], the incorrect shuffle would result can only produce two outcomes: [1,3,2] and [3,2,1]. This is already a mistake, since you expect a shuffle to be able to produce any of the 6 permutations. However, in addition, under the incorrect shuffle, those outcomes can only produce each other on another iteration of the bad shuffle.
So, to think about it differently, the only way for [2,1,3] to shuffle into [1,2,3] would be if the third element was allowed to stay in place. The only way for [1,3,2] to shuffle into [1,2,3] would be if the first element was allowed to stay in place. Finally, the only way for [3,2,1] to shuffle into [1,2,3] would be if the second element was allowed to stay in place. But the algorithm does not allow elements to stay, and any moved element during the shuffle iteration is not moved again.
The bad shuffle only produces the permutations that cause all the elements to be in a different position. In other words, it can only produce rotations!Only for the 3 element case
So, if the starting point is not a rotation of the sorted array, the algorithm will never terminate.
In comments, I had suggested an alternative shuffle implementation:
public static void shuffle(int[] a){
Random r = new Random();
int x = r.nextInt(a.length);
for(int i = a.length-1;i > 0;i--){
int j = r.nextInt(i);
if (j < x) break;
swap(a, i, j);
}
}
However, the weakness of this shuffle is that itself still lacks the ability to generate any possible permutation. The ability of the bogosort to eventually see all possible permutations using this implementation depends on each successive call to shuffle producing slightly different inputs for the next call.
if(responseArr.size()!=0) {
for(int i=0;i<responseArr.size();i++) {
if(responseArr.get(i).equals("busy")) {
stylistId.remove(i);
}
}
}
If any values in the array contain the string busy, I want to remove the value from the stylistId array in that position. In the code above, the responseArr array and the stylistId array are the same size.
When I try to remove values from stylistId, it works fine when the loop executes for the first time. When loop executes the second time, I get indexOutOfBound Exception.
This is happening because the index of some elements in the list changes when you remove an element. For example, if your list has five elements (0, 1, 2, 3, 4) and you remove element 2, then elements 3 and 4 will get renumbered so that you have (0, 1, 2, 3) afterwards.
There are many possible solutions to this problem, but one way is simply to traverse responseArr backwards.
for(int i= responseArr.size() - 1;i >= 0; i--){
if(responseArr.get(i).equals("busy")){
stylistId.remove(i);
}
}
That way, you'll only be changing the indexes of elements that you've already checked.
Because There are two version of remove method.
remove element at index
remove given element
You need to call second method which return element. So, You can use Like,
for (int i = 0; i < responseArr.size(); i++) {
if (responseArr.get(i).equals("busy")) {
int id = stylistId.remove(i); //use your type instead of int.
}
}
I have an integer array of size 4. I am adding elements to it via the add method. This is as an unsorted array. I am sorting it via the sort method shown in the code below. The sort method places the smallest number in the position a[0]. When I try to add elements after I call the sort method I always get a return value of 0. Is there a way around this?
import java.util.Arrays;
public class Scrap {
private static int[] array = new int[4];
private static int i = 0;
public static void main(String[] args) {
Scrap pq = new Scrap();
pq.add(4);
pq.insert(3);
pq.add(5);
pq.sort();// smallest to largest sort method.
// System.out.println(array[0]);
pq.insert(1);
pq.sort();
int test = pq.Minimum();
System.out.println("The smallest element of the array is " + test);
pq.sort();
}
//
public void add(int input) {
insert(input);
}
// Method to insert number into the array.
public void insert(int input) {
array[i] = input;
i++;
}
// Finding smallest number of the array.
public int Minimum() {
int a = array[0];
return a;
}
// Sorts the array from smallest to largest integer
public void sort() {
int first, temp;
for (int i = array.length - 1; i > 0; i--) {
first = 0;
for (int j = 1; j <= 1; j++) {
if (array[j] > array[first])
first = j;
}
temp = array[first];
array[first] = array[i];
array[i] = temp;
}
}
public int remove() {
return delete();
}
public int delete() {
return remove();
}
// Method to convert the array into a string for output
}
The problem in a nutshell:
You start with an array of length 4.
At this point the array contains 4 zeros, that is: [0, 0, 0, 0]
You add 4, 3, and 5. These operations update the content of the array to [4, 3, 5, 0].
You sort the array. This should change the content of the array to [0, 3, 4, 5]. In fact it changes to [0, 5, 3, 4], which means your implementation of sort is clearly broken.
You probably didn't expect the 0 value to move. You can fix this by sorting only the first 3 values. (And, of course, you should also fix your implementation of sort.)
Then when you insert 1, the program updates the value at index 3, so the content changes to [0, 5, 3, 1].
If you implement the fix I suggested above, and sort only the first size elements, then the content after the first call to sort should become [3, 4, 5, 0], and the content after the insert 1 should become [3, 4, 5, 1]. And when you sort that again, the content should become [1, 3, 4, 5] and the smallest value will be 1 as expected, instead of 0.
More concretely:
First of all, change private static int i = 0; to private int size = 0;. The name i is extremely inappropriate here, and will surely confuse you. size is appropriate. It also doesn't make sense to make it static, so I suggest to drop that keyword.
Fix the implementation of sort. There are many basic sorting algorithms that are easy to implement. In the implementation, instead of going until array.size, go until size. Do you see the difference? size is the field in Scrap, essentially it's the number of elements you added using the add or insert methods.
Some cleaning up would be good too:
Delete the add method and rename insert to add.
Delete the remove and delete methods. They are not used, and you will get a stack overflow if you try to use them as they are now (the methods call each other, forever)
Look at the content of the array after each step in the program.
After Scrap pq is created, this is the content of its array:
[0, 0, 0, 0]
Then a couple of modifications:
pq.add(4);
pq.insert(3);
pq.add(5);
The content at this point:
[4, 3, 5, 0]
So far so good.
Then you sort it:
pq.sort();
The content at this point:
[0, 5, 3, 4]
Ouch. The sort implementation doesn't work very well, does it. But let's ignore that for now. Next step:
pq.insert(1);
The content at this point:
[0, 5, 3, 1]
None of this behavior makes sense, probably this is not how you intended the program to work. Review the program, verify the content after each step. Do not proceed to the next step until the current step is working correctly.
I am assuming that you will be using a correct sort method (because, this is not correct, you can use Arrays.sort). But still with a correct sort, there is a logical problem in your code.
At the beginning, the array contains all 0s. After adding the first 3 int, when you call the sort method, the array contains the values in following order:
0,3,4,5
Note that, the value of i is not changed. At this state the value of i is 3. So when you insert 1, the new values become
0,3,4,1
So after sorting again, the values of arrays become
0,1,3,4
So obviously the minimum will retrun 0
I don't think that is the most effective way to sort an array. It is possible to do this with just 1 for loop. Try this to sort your array from smallest to largest.
int temp;
for(int i=0;i<array.length-1;i++){
if(array[i]>array[i+1]){
temp=array[i];
array[i]=array[i+1];
array[i+1]=temp;
i=-1;
}
}
So I'm trying to remove all cards from a player's 'Rack' (an ArrayList) and put it in the discard pile (Stack), one by one. So far I have the following code which I've come to realize will stop once it hits 5. (Note: each players rack has 10 cards).
int rackSize = player.getPlayerRack().getRack().size(); // rackSize = 10
for (int i = 0; i < rackSize; i++) {
getDeck().getDiscardPile().add(player.getPlayerRack().getRack().remove(i));
}
My question is how do I remove all items in the players 'Rack' so the rackSize = 0, and add all of them to the discard pile?
Terribly sorry if this is confusing. You can generalize this by saying there are 10 integers in an ArrayList<Integer> hand, so: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. How would you remove all items from this list and add them to a Stack<Integer> discardPile?
What's happening is as you're removing the elements from Rack, you're still incrementing with i++, meaning that the new value at the old index i is still left behind. What you'll want to do is change your code to this:
int rackSize = player.getPlayerRack().getRack().size(); // rackSize = 10
for (int i = 0; i < rackSize; i++) {
getDeck().getDiscardPile().add(player.getPlayerRack().getRack().remove(0));
}
This way, you're always reaching into the first new element in the Rack until it's empty, assuming Rack is not repopulated while this code is executing.
Use 0 instead of i to access the ArrayList.
When you remove an element, it is no longer in the ArrayList so you have to keep this is mind - further references through the array index should be decremented 1 in each iteration. As a result you probably want to access the first item every time.