Shuffling an arraylist in java - java

Using an ArrayList, I need to subdivide a deck into two sections, one top section, and one bottom section. The top section will be the front of the ArrayList arr. If the size of the ArrayList arr happens to be odd, the top section size must be one more than the bottom section. Below you will see a few more specifications, there seems to be a slight logic error, but I'm having trouble figuring out where. As you can see, I have pretty much all of the code written and I feel as though this should be working. I need to shuffle without using collections.

for(int i =0; i<topHalf.size();i++){
topHalf.size() will return 0 because you have no elements in it yet. When you initialize it you are just allocating a size for the underlying array but the arraylist will have a size of 0...

As an aside you could use the sublist method.
// divide by two and round up
int middle = (int)(arr.size() / 2.0f + 0.5f);
ArrayList<Battleable> topHalf = arr.sublist(0, middle);
ArrayList<Battleable> bottomHalf = arr.sublist(middle, arr.size());

The easiest way is to use the 'sublist' method. You can do:
Double middle = Math.ceil(new Double(arr.size())/2);<br>
topHalf = arr.subList(0, middle.intValue());<br>
bottomHalf = arr.subList(middle.intValue(), arr.size());

The only change I would have made is adding a ternary operator to (simplify?) the code a little bit:
ArrayList<Battleable> topHalf = new ArrayList<Battleable>();
int topSize = arr.size() % 2 == 0 ? arr.size()/2 : (arr.size()/2)+1;
for(int i = 0; i < topSize; i++) {
topHalf.add(i, arr.get(i));
}
ArrayList<Battleable> bottomHalf = new ArrayList<Battleable>();
int count = topHalf.size();
int bottomSize = arr.size() - topHalf.size();
for(int i = 0; i < bottomSize; i++) {
bottomHalf.add(i, arr.get(count));
count++;
}
int x = 0, y = 0;
int end = arr.size();
for(int i = 0; i < end; i++) {
if(I % 2 == 0) {
arr.add(i, topHalf.get(x));
x++;
} else {
arr.add(i, bottomHalf.get(y));
y++;
}
}

Related

Randomly filling a 2d boolean array with equal amounts of both values

I'm trying to find a way to fill a 2d array of length n with boolean values randomly. The array must have an equal amount of each value if n is even, and if n is odd the extra value must be the same boolean each and every time (doesn't matter which one). Any tips on how to do this in Java? I'm currently shuffling arrays that I make with equal amounts of both values, but this isn't truly random because there will always be n/2 (or n/2+1 and n/2-1 for the odd ns) of each value.
Any advice?
Given your requirements, filling the array with the amount you need, then shuffling it, is a good solution.
Make sure to use a truly random shuffling algorithm, such as the Fisher-Yates shuffle, not the "swap a random pair a bunch of times" method. If you're using Collections.shuffle or similar, you don't need to worry about this.
Adapting the Fisher-Yates shuffle to a 2D array is probably the simplest approach.
boolean[][] array = new boolean[rows][cols];
boolean alternating = false;
Random random = new Random();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int k = random.nextInt(i * cols + j + 1);
int swapRow = k / cols;
int swapCol = k % cols;
boolean tmp = array[swapRow][swapCol];
array[swapRow][swapCol] = alternating;
array[i][j] = tmp;
alternating = !alternating;
}
}
This is pretty much a verbatim implementation of http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_.22inside-out.22_algorithm , except that we're filling the array as we go with falses and trues.
A different approach might be to randomise the position you are placing the next value rather than the value itself. You know ahead of time exactly how many of each value you are placing.
Something like:
List<Integer> indicesList = IntStream.range(0, n * n).collect(Collectors.toList());
Collections.shuffle(indicesList);
indicesList.stream().forEach(n -> array[n % size][n / size] = (n % 2 == 0));
By my understanding that should give you completely random placement of your values and an equal number of each.
Here's a real simple solution a coworker came up with. It looks to me like it would work and be truly random (please let me know if not, I have terrible intuition about that kind of thing), although it's definitely ugly. Would be pretty efficient compared to a shuffle I imagine.
public boolean[][] generateRandom2dBooleanArray(int length) {
int numFalses = (length*length)/2;
int numTrues = (length*length)/2;
if ((length*length)%2!=0) numTrues++;
boolean[][] array = new boolean[length][length];
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if (Math.random() > 0.5) {//Or is it >= 0.5?
if (numTrues >= 0) {
array[i][j] = true;
numTrues--;
} else {
//Since boolean arrays are false by default, you could probably just break here to get the right anser, but...
array[i][j] = false;
numFalses--;
}
} else {
if (numFalses >= 0) {
array[i][j] = false;
numFalses--;
} else {
array[i][j] = true;
numTrues--;
}
}
}
}
}
return array;
}

Handling ArrayList out of bounds exception Java

My program will be creating a two dimensional grid / ArrayList. It will search for all boxes around a specific box and return their elements. However if the box is at an edge it may not have any surrounding boxes in the grid. So we will try to access an empty slot in an arrayList, possibly slot -1.
Is there anyway I can write some code like this in Java:
ArrayList arr = new ArrayList();
//add 5 elements to arr
for(int i = 0; i<10; i++){
if(arr.get(i) is out of bounds){
System.out.println("No elements here");
else{
System.out.println(arr.get(i));
}
You can check to see if i is outside the array bounds.
if i >= arr.size();
Though a better solution would be to loop over the contents of the array with a for each loop like so:
for (Object i : arr){
// Do something
}
You need boundary control check. For instance, if you need to loop around the neighbors of a point x, y, you could do
// assuming that you're checking around point x and y
// here you set minI, maxI
int minI = Math.max(0, x - 1);
int maxI = Math.min(listMax - 1, x + 1);
for (int i = minI; i <= maxI; i++) {
// here you set minJ and maxJ
int minJ = Math.max(0, y - 1);
int maxJ = Math.min(innerListMax - 1, y + 1);
for (int j = minJ; j <= maxJ; j++) {
// do your stuff here
}
}

How to remove object from array

Please bear within as it might be difficult to understand
I have an array of jbuttons 50 size big, for this example ill use 7 I have jbutton object within 1 2 3 4 6 7 but not 5. These are printed on the screen. I want to remove these jbuttons however all buttons up to 5 are removed while the last two are not.
for(int i = 1; i < 51; i++){
if(seat.buttonArray[i] == null){
remove(seat.buttonArray[i]);
seat.buttonArray[i] = null;}
}
There is no way to remove element from array, assuming you want latter indexes changed after remove. For this purpose, you should use List:
Iterator buttonIterator = seat.buttonList.iterator();
while (buttonIterator.hasNext()) {
Object button = buttonIterator.next(); //or more specific type, if your list was generified
if (button == null) { //or some other criteria, wrote this just as an example
buttonIterator.remove();
}
}
If using array is mandatory, you have two options:
Set seat.buttonArray[i] to null value, indicating it has been removed;
Recreate array each time you deleted something. See System.arraycopy javadoc for details, although I do not recommend this approach because of performance considerations.
You could store the values in a temp array and then copy what you want back into your original array. Somewhat similar to this:
int myArray[50];
int temp[50];
int good;
for (int i = 0; i < 50; i++) {
myArray[i] = i;
}
for (int i = 0; i < 50; i++) {
temp[i] = myArray[i];
}
good = 0;
for (int i = 0; i < 50; i++) {
if (i < 10) {
} else {
myArray[good] = temp[i];
good += 1;
}
}
Looks messier than I first thought... But it essentially does what you're wanting.

Going back to the first index after reaching the last one in an array

After my array in the for loop reaches the last index, I get an exception saying that the index is out of bounds. What I wanted is for it to go back to the first index until z is equal to ctr. How can I do that?
My code:
char res;
int ctr = 10
char[] flames = {'F','L','A','M','E','S'};
for(int z = 0; z < ctr-1; z++){
res = (flames[z]);
jLabel1.setText(String.valueOf(res));
}
You need to use an index that is limited to the size of the array. More precisely, and esoterically speaking, you need to map the for-loop iterations {0..9} to the valid indexes for the flame array {0..flames.length()-1}, which are the same, in this case, to {0..5}.
When the loop iterates from 0 to 5, the mapping is trivial. When the loop iterates a 6th time, then you need to map it back to array index 0, when it iterates to the 7th time, you map it to array index 1, and so on.
== Naïve Way ==
for(int z = 0, j = 0; z < ctr-1; z++, j++)
{
if ( j >= flames.length() )
{
j = 0; // reset back to the beginning
}
res = (flames[j]);
jLabel1.setText(String.valueOf(res));
}
== A More Appropriate Way ==
Then you can refine this by realizing flames.length() is an invariant, which you move out of a for-loop.
final int n = flames.length();
for(int z = 0, j = 0; z < ctr-1; z++, j++)
{
if ( j >= n )
{
j = 0; // reset back to the beginning
}
res = (flames[j]);
jLabel1.setText(String.valueOf(res));
}
== How To Do It ==
Now, if you are paying attention, you can see we are simply doing modular arithmetic on the index. So, if we use the modular (%) operator, we can simplify your code:
final int n = flames.length();
for(int z = 0; z < ctr-1; z++)
{
res = (flames[z % n]);
jLabel1.setText(String.valueOf(res));
}
When working with problems like this, think about function mappings, from a Domain (in this case, for loop iterations) to a Range (valid array indices).
More importantly, work it out on paper before you even begin to code. That will take you a long way towards solving these type of elemental problems.
While luis.espinal answer, performance-wise, is better I think you should also take a look into Iterator's as they will give you greater flexibility reading back-and-forth.
Meaning that you could just as easy write FLAMESFLAMES as FLAMESSEMALF, etc...
int ctr = 10;
List<Character> flames = Arrays.asList('F','L','A','M','E','S');
Iterator it = flames.iterator();
for(int z=0; z<ctr-1; z++) {
if(!it.hasNext()) // if you are at the end of the list reset iterator
it = flames.iterator();
System.out.println(it.next().toString()); // use the element
}
Out of curiosity doing this loop 1M times (avg result from 100 samples) takes:
using modulo: 51ms
using iterators: 95ms
using guava cycle iterators: 453ms
Edit:
Cycle iterators, as lbalazscs nicely put it, are even more elegant. They come at a price, and Guava implementation is 4 times slower. You could roll your own implementation, tough.
// guava example of cycle iterators
Iterator<Character> iterator = Iterators.cycle(flames);
for (int z = 0; z < ctr - 1; z++) {
res = iterator.next();
}
You should use % to force the index stay within flames.length so that they make valid index
int len = flames.length;
for(int z = 0; z < ctr-1; z++){
res = (flames[z % len]);
jLabel1.setText(String.valueOf(res));
}
You can try the following:-
char res;
int ctr = 10
char[] flames = {'F','L','A','M','E','S'};
int n = flames.length();
for(int z = 0; z < ctr-1; z++){
res = flames[z %n];
jLabel1.setText(String.valueOf(res));
}
Here is how I would do this:
String flames = "FLAMES";
int ctr = 10;
textLoop(flames.toCharArray(), jLabel1, ctr);
The textLoop method:
void textLoop(Iterable<Character> text, JLabel jLabel, int count){
int idx = 0;
while(true)
for(char ch: text){
jLabel.setText(String.valueOf(ch));
if(++idx < count) return;
}
}
EDIT: found a bug in the code (idx needed to be initialized outside the loop). It's fixed now. I've also refactored it into a seperate function.

Rearranging array when it has a null position

I have this code that searches one object in an array and removes it. I'm having a problem with its position, since some other methods work with this array (and it gives me a NullPointerException every time). My method looks like this:
public void deleteHotel(String hotelName) {
for (int i = 0; i < this.hoteis.length; i++) {
if (this.hoteis[i].getName().equalsIgnoreCase(nomeHotel)) { //searches the array, looking for the object that has the inputted name
this.hoteis[i] = null; //makes that object null
if (this.hoteis.length > 1 && this.hoteis[this.hoteis.length - 1] != null) { //for arrays with lenghts bigger than 1 (since there's no problem with an array with one position)
for (int x = i; x < this.hoteis.length; x++) {
this.hoteis[x] = this.hoteis[x + 1]; //makes that null position point to the next position that has an object, and then that position points to the object in the next position and so on
}
this.hoteis[this.hoteis.length - 1] = null; //since the last to positions will be the same, make that last one null
Hotel[] hoteisTemp = new Hotel[this.hoteis.length - 1];
for(int x = 0; x < this.hoteis.length - 1; x++){ //create a new array with one less position, and then copy the objects on the old array into the new array, then point the old array to the new array
hoteisTemp[x] = this.hoteis[x];
}
this.hoteis = hoteisTemp;
}
i = this.hoteis.length;
}
}
}
When I use other methods (for example, one that returns the implemented toString()s of each object) it gives me a NullPointerException. Can you guys identify the error in the code? Much appreciated...
I have tested your function and I see what you mean by it getting a nullpointerexception, this is due to the array not resizing the list - which is due to your conditional:
if (this.hoteis.length > 1 && this.hoteis[this.hoteis.length - 1] != null).
Simply removing this solved the issue, here is the working function:
public static void deleteHotel(String hotelName) {
for (int i = 0; i < hotels.length; i++) {
if (hotels[i].getName().equalsIgnoreCase(hotelName)) { //searches the array, looking for the object that has the inputted name
hotels[i] = null; //makes that object null
for (int x = i; x < hotels.length -1; x++)
hotels[x] = hotels[x + 1]; //makes that null position point to the next position that has an object, and then that position points to the object in the next position and so on
Hotel[] hoteisTemp = new Hotel[hotels.length - 1];
for(int x = 0; x < hotels.length - 1; x++) //create a new array with one less position, and then copy the objects on the old array into the new array, then point the old array to the new array
hoteisTemp[x] = hotels[x];
hotels = hoteisTemp;
break;
}
}
}
Though please consider using a list of some sort when needing to use a list with a changing size.
The fundamental problem is that you're not allowing for where you removed the entry from the array.
Instead of
for(int x = 0; x < this.hoteis.length - 1; x++){
you want
for(int x = 0; x < this.hoteisTemp.length; x++){
(although that's a style choice)
and more significantly, instead of
hoteisTemp[x] = this.hoteis[x];
you want
int y = x < i ? x : x + 1;
hoteisTemp[x] = this.hoteis[y];
You also want to get rid of everywhere you're setting array elements to null, because if your copying logic works correctly, that's unnecessary.
For this use case, I would consider using one of the List implementations.
Consider rewriting your code
List result = new ArrayList();
for (int i = 0; i < this.hoteis.length; i++) {
if (!this.hoteis[i].getName().equalsIgnoreCase(nomeHotel)) {
result.add(this.hoteis[i]);
}
}
return result.toArray();
The point where you're shifting the array elements towards the left
for (int x = i; x < this.hoteis.length; x++) {
this.hoteis[x] = this.hoteis[x + 1];
}
The loop condition should be x < this.hoteis.length - 1 because at the last iteration when x = this.hoteis.length - 1 the index value this.hoteis[x + 1] would throw a NullPointerException.
Try using ArrayList it will simplify your code complexity.Here is the link to documentation.
http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html

Categories