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.
Related
I'm working on a custom Arraylist implementation and I have one method where I'm trying to remove an item per conditions from an array such as E[] elements. The array is initialized by doing something like this:
String[] contents = {"chicken", "hippo", "goat"};
ArrayI<String> newarray = new ArrayI(contents);
newarray.chooser(new LongChooser());
It should remove words length 4 or less and return an array like this:
["chicken", "hippo"]
I'm trying not to use any built in methods, like remove(), clone(), arraycopy(), etc. I can't seem to get this to work, I've tried creating a duplicate array and trying to copy elements over like this:
E[] copy = (E[]) (new Object[this.size-1]);
for (int i = 0; i < size; i++) {
if (shorter) {
copy[i] = elements[i];
}
else {
for (int j = i; j<this.size-1; j++) {
elements[j] = elements[j+1];
}
elements[size-1] = null;
size -= 1;
}
for (int i =0; i< copy.length; i++) {
elements[i] = copy[i];
}
size -=1;
I know this is not the correct way because they aren't the same size array and just returns [longword, longerword, null]. Also I'm pretty sure I should be using the size variable, but it doesn't seem to do much.
How do I get this to work? Thanks.
I'm trying to test a multidimensional array to see if contains any duplicate values. If it does I would like the method to return false. Otherwise I would like it to return true.
Here is my current code. Where is my logic wrong?
public static boolean isUnique(int[][] array2, int num) {
for (int i = 0; i < array2.length - 1; i++) {
for (int j = i + 1; j < array2.length; j++) {
if (array2[i] == array2[j]) {
return false;
}
}
}
return true;
}
Your current implementation is checking whether two rows are the same (this is a reference based check, rather than a value.) This means that it asks 'Are array2[i] and array2[j] the same address in memory, rather than do they contain the same things.
If you want to see whether the rows are unique you'd use array2[i].equals(array2[j]) instead of array2[i] == array2[j].
If you wanted to check for unique elements (array[i][j] != array2[i+m][j+n] where !(m == n == 0)) you'd need to iterate through both levels in a
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
// compare array2[i][j] to all other array2[m][n] here.
}
}
Right now your code is checking whether any of the arrays inside array2 are the same. array2[i] and array2[j] are both referring to arrays, because array2 is an array of arrays.
Instead, you want to look at the values inside of each of those arrays. Since you want to fail on any repeated value anywhere in the grid, you're effectively trying to flatten the structure into one collection, and check for duplicates in that.
A HashSet is the best data structure to use in this case. Traverse the entire grid, row-by-row, adding values into your new struture. If you encounter a duplicate, return false:
public static boolean isUnique(int[][] array2) {
Set<Integer> values = new HashSet<>();
for (int i = 0; i < array2.length; i++) {
for (int j = 0; j < array2[i].length; j++) {
if (!values.add(array2[i][j])) {
return false;
}
}
}
return true;
}
Some things to note here:
The set's add method will return false if you attempt to add a duplicate to the collection, so that's wrapped in an if statement for a simple, fail-fast stopping condition.
The sizes of each of the inner arrays are completely independent from the size of the outer array, so you still want to loop from 0 to the length of the array (when you're using <, you don't need the length - 1).
Right now I have the following idea:
int WORK[] = new int[]{5, 4, 3};
int release[] = new int[]{3, 2, 3};
boolean check = false;
for (int i = 0; i < WORK.length; i++)
{
if (WORK[i] >= release[i])
{
for (int j = 0; j < WORK.length; j++)
{
if (WORK[j] >= release[j])
{
for (int k = 0; k < WORK.length; k++)
{
if (WORK[k] >= release[k])
{
check = true;
System.out.print("All elements in work are bigger than release");
break;
}
}
break;
}
}
break;
}
}
if(!check)
{
System.out.print("Not every element in work is bigger than release");
}
Now I want to know if there is a more efficient way to do this? But my main problem is that I need to do this with n elements. With `n´ elements it is not efficient neither useful, because I don't know how many elements will be there.
What I want to know is there a function in Java Arrays or something, which could help me?
Any help?
With Java 8, you can do this in a functional style with streams (this would not be a performance optimization; it's just less code to write).
IntPredicate lowerThanRelease = i -> IntStream.of(release).allMatch(j -> i <= j);
boolean allLower = IntStream.of(work).allMatch(lowerThanRelease);
One efficient way to do this is two have 4 variables
workmax, workmin, needmax, needmin.
Iterate through both arrays one at a time and find the max and min values within that array. Then all you need to do is compare the min value of one array with max value of the second array
This way you just need two loops (no nesting).
Then its a matter of simple comparison.
e.g.
if (workmin > needmax) then System.out.print("All elements in " + work + "are bigger than need");
I think you can come up with the code if you understand the approach mentioned above.
I hope I got your question correctly.
if (array1.length == array2.length) {
for (int i = 0; i < array1.length; i++) {
for (int j =0; j < array2.length; j++) {
// compare array1[i] with array2[j];
}
}
} else {
System.out.println("Arrays have different lengths.");
}
This gives you the opportunity to compare all numbers of one array with all numbers of the second. So your basic idea was not that bad.
Hope it helps.
This one seems very basic, but it should do it.
I have a program where I need to remove a set of rows from a byte[][] array. I want to remove every row that has no zeroes in it. Right now I'm using the following methods:
public byte[][] checkRows(byte[][] grid) {
LinkedList<Integer> temp = new LinkedList<Integer>();
boolean willRemove = false;
for (int y = 0; y < grid.length; y++) {
boolean tempCheck = true;
for (int x = 0; x < grid[0].length; x++) {
if (grid[y][x] == 0) {
tempCheck = false;
break;
}
}
if (tempCheck) {
temp.add(y);
willRemove = true;
}
}
if (willRemove) {
int[] rowArray = convert(temp);
return removeRows(grid, rowArray);
}
return grid;
}
public byte[][] removeRows(byte[][] grid, int[] rows) {
int total = rows.length;
int current = 0;
byte[][] retGrid = new byte[grid.length][grid[0].length];
for (int i = total; i < grid.length; i++) {
if (current < total && i-total+current == rows[current]) {
current++;
}
//retGrid[i] = grid[i-total+current].clone();
System.arraycopy(grid[i-total+current], 0, retGrid[i], 0, xsize);
}
return retGrid;
}
public int[] convert(LinkedList<Integer> intList) {
int[] retArray = new int[intList.size()];
for (int i = 0; i < retArray.length; i++) {
retArray[i] = intList.get(i).intValue();
}
return retArray;
}
This gives me a reasonably fast way of removing rows from a 2D Array and replacing them with zero rows at the top of the array. Is there any faster way to achieve the same result?
If it's unclear what the script does, it's for removing full rows in a game of Tetris.
UPDATE: Using System.arraycopy() instead of clone() provides a 5% performance boost for small arrays.
Using a linked list would give O(1) removals, see this answer, since the list must be iterated over anyway.
At first I thought multidim arrays are compact in the sense that it is one contiguous block of memory, but it seems this is not the case. So you don't loose any caching benefits that might have been in effect.
Pity Java has not value types (currently), I'd use one instead of a byte to encode information. Well this is not strictly necessary...
And from a code review perspective, having a bool willRemove in method checkRows is unnecessary since in these cases, temp will have more than one element. I'd try to eliminate that ArrayList allocation altogether if it's not needed - defer it.
IMHO it's too complicated. Drop the LinkedList as this is a terrible thing anyway. Don't bother with collecting the indexes for removal, instead copy every rows to be preserved to another array. Then use arraycopy to overwrite the original.
You're copying whole rows, but you don't have to. Just rearrange them, so the the preserved rows falls down and move the full ones to the top and clean them. There's no memory allocation needed.
As all copying operation work with one dimension only, there's not much to optimize since the most time-consuming operations are probably determining if there's any zero in a row and (now and then) cleaning some rows.
I wonder what machine does it run on as I guess it must be damn fast on even the slowest phones. Btw. CR would be better suited. Think about better names, e.g., tempCheck -> noZeroFound.
This small method executes the desired functionality of the question for the one dimensional case.
private static final void onClearFilledRows(final byte[] pTetris, final int pRowLength) {
int i = 0, j = 0;
/* Track the last valid position of row data. */
int lLastValidIndex = 0;
/* Iterate through each row. */
for(i = 0; i < pTetris.length; i += pRowLength) {
/* Iterate through each cell in the row. */
boolean lContainsZero = false;
for(j = i; j < (i + pRowLength) & !lContainsZero; j++) {
lContainsZero |= pTetris[j] == 0;
}
/* This row is valid. Copy it to the last valid index. */
if(lContainsZero) {
System.arraycopy(pTetris, i, pTetris, (lLastValidIndex++ * pRowLength), pRowLength);
}
}
/* Empty the remaining rows. */
for(i = lLastValidIndex * pRowLength; i < pTetris.length; i++) {
/* Set the element to zero. */
pTetris[i] = 0;
}
}
This logic can then be reworked for the two dimensional case:
private static final void onClearFilledRows(final byte[][] pTetris) {
int i = 0, j = 0;
/* Track the last valid position of row data. */
int lLastValidIndex = 0;
/* Iterate through each row. */
for(i = 0; i < pTetris.length; i ++) {
/* Iterate through each cell in the row. */
boolean lContainsZero = false;
for(j = 0; j < pTetris[i].length & !lContainsZero; j++) {
lContainsZero |= pTetris[i][j] == 0;
}
/* This row is valid. Copy it to the last valid index. */
if(lContainsZero) {
System.arraycopy(pTetris[i], 0, pTetris[lLastValidIndex++], 0, pTetris[i].length);
}
}
/* Empty the remaining rows. */
for(i = lLastValidIndex; i < pTetris.length; i++) {
for(j = 0; j < pTetris[i].length; j++) {
/* Set the element to zero. */
pTetris[i][j] = 0;
}
}
}
I am in the process of writing a sudoku solver (still need to write the box check and actually complete the program) but I'm testing it as I know. The puzzle I'm testing right now is "very easy" as in there is only one empty cell in any row/column. THe puzzle starts with "empty" cells as zeros. My issues is that when I run the program and print out the puzzle after solve() is called, the zeros aren't changing and the original puzzle is just printed out. Not sure what my issue is, would appreciate some direction!
public ArrayList<Integer> create(){
ArrayList<Integer> possible = new ArrayList<Integer>();
for(int i=1; i<10; i++){
possible.add(i);
}
return possible;
}
public sudoku( int size )
{
SIZE = size;
N = size*size;
Grid = new int[N][N];
for( int i = 0; i < N; i++ )
for( int j = 0; j < N; j++ )
Grid[i][j] = 0;
}
public void solve()
{
int a, b, c, d, i, j, k, l;
int count = 0;
int value= 0;
for(i=0; i<N;i++){
for(j=0; j<N;j++){
if(Grid[i][j]==0){
ArrayList<Integer> possible = create();
//check row
for(a=0; a<N;a++){
for(b=0; b<N; b++){
if(Grid[a][0]==possible.get(a)){
possible.set(a, 0);
}
}
}
//check column
for(c=0; c<N;c++){
for(d=0; d<N;d++){
if(Grid[0][d]==possible.get(d)){
possible.set(d,0);
}
}
}
for(k=0; k<9; k++){
if(possible.get(k)!=0){
count++;
}
}
if(count==1){
for(l=0; l<9; l++){
if(possible.get(l)!=0){
value=possible.get(l);
}
}
}
Grid[i][j]=value;
}
}
}
}
Look at your line if(Grid[a][0]==possible.get(a)) (and similar spots). What is it doing there vs what do you actually want?
Your possible array looks something like this:
[1,2,3,4,5,6,7,8,9]
and your grid (just the first row, since you're only checking Grid[a][0]) might look something like this:
[3,7,8,1,2,9,5,0,4]
Your loop is looking at each element stepwise individually and seeing if they're equal, like this:
if(1 == 3) ... it's not
if(2 == 7) ... it's not
if(3 == 8) ... it's not
... etc
So, as you can see, when you do your
for(k=0; k<9; k++){
if(possible.get(k)!=0){
count++;
}
}
Your possible array is still going to be full of options most of the time, unless your first row happens to be some variation on [1,2,3,4,5,6,7,8,9] with a 0 in one of the spaces... so count is definitely going to be > 1
So, your next loop (for(l=0; l<9; l++)) next gets executed, so value is still (as you initialized it) 0.
Try stepping through a debugger on these points and seeing how the arrays are interacting.
if(Grid[a][0]==possible.get(a))
if(Grid[0][d]==possible.get(d))
You don't use b or c in these lines. You probably want:
if(Grid[a][i]==possible.get(b))
if(Grid[j][d]==possible.get(c))
Also, the Grid[i][j]=value check should be inside the if block.
You might want to use a Set for the possible values instead of an ArrayList.
You are always checking only the first row and first column and the way you check for the possible numbers is also not doing what you want.
A few tips first:
First of all, it is not necessary to always define a new variable for the loops, you can reuse them and then you won't have too many of them and you won't get so easily confused in them.
Secondly, if you name all the variables a, b, c, d, etc. you can also easily get confused. While it is ok to name variables in loops as i, j, if you have too many loops, it may be better to think of better names. In this case row and column for example.
Why don't you remove the numbers from the possible list? Something like:
int index = possible.indexOf(a);
if (index != -1) possible.remove(index);
Then it would be easier to determine how many values you still have left. You can simply do:
if (possible.size()==1) value = possible.get(0);
And one last note, to obey the convention for variable names, you should probably use grid instead of Grid.
And now the code:
public void solve() {
int row, column, i;
int count = 0;
int value= 0;
int index = 0;
for(row=0; row<N; row++){
for(column=0; column<N; column++){
if(Grid[row][column]==0){
ArrayList<Integer> possible = create();
//check row
for(i=0; i<N; i++){
index = possible.indexOf(Grid[row][i]);
if (index != -1) possible.remove(index);
}
//check column
for(i=0; i<N; i++){
index = possible.indexOf(Grid[i][column]);
if (index != -1) possible.remove(index);
}
if (possible.size()==1) value = possible.get(0);
Grid[row][column]=value;
}
}
}
}
EDIT: Rewritten the whole answer into a better form.