I have 2D ArrayList which was filled with elements (objects which contain images etc.) so the 2D array was full. After calling removing functions my array looks like the picture on the left side; on the right side you can see the desired result. Could someone please give me the idea how to reorganize my array as you can see on the picture?
The idea was to go from to bottom to top. If I find the gap (the gap means that I set the background of element to null, respectively, imageIcon is set to null) I will switch it for the previous element. And because I have switched it I have to do it for the whole column. Problem is, when they are 2 or more gaps and also, this algorithm does nothing.
for (int i = 0; i < 10; i++) {
for (int j = 7; j > 0; j--) {
Item currentItem = this.elements.get(j).get(i).getItem();
if (currentItem.getBack().getIcon() == null) {
int count = j;
while (count > 1) {
Position temp = this.elements.get(count).get(i);
Position zero = this.elements.get(count).get(i);
Position previous = this.elements.get(count - 1).get(i);
zero = previous;
previous = temp;
count--;
}
}
}
}
The arrayed data size is limited to 10x8 because of my gameboard panel. The items in array are not distinguishable, they only have different backgrounds (type of JLabel component). The items have to "fall from top to down".
PS: I am creating a clone of Bejeweled
From what you have shown in the pictures, you want the column's elements to be "dropped to bottom"? If that is the case, you should probably use a regular 2D array instead of ArrayList, with an array for each of your columns, and assume the bottom is indexed 0 - why? because ArrayList doesn't have fixed size, and your problem statement shows you want the container to be of fixed size. The solution would then be (roughly, because you shown only a part of your code, not a SSCCE):
//Item[][] items;
for( Item[] arr : items )
for( int i = arr.length - 2; i >= 0; i-- )
if ( arr[i] == null ) // or arr[i].getBack().getIcon() == null or whatever
for( int j = i; j < arr.length - 1; j++ )
arr[j] = arr[j+1];
This is a crude bubble sort, suitable for small arrays. There are other solutions possible (as this is a sorting problem by itself - you may look up qsort for this), but this one is arguably the simplest.
Note: You may implement the very same solution for ArrayLists, yet I strongly advocate against it. Using nested ArrayLists to mimic multi-dim arrays is seldom a good idea - it'll create the arrays anyway, but you'll get a large overhead, making the code both slower and less readable - anyway you can do so by replacing []s with get()/set() etc.
For the sake of reference:
//ArrayList<ArrayList<Item>> items;
//int columnHeight;
for( ArrayList<Item> arr : items )
for( int i = columnHeight - 2; i >= 0; i-- )
if ( arr.get(i) == null ) //or arr.get(i).getIcon()==null or whatever
for( int j = i; j < columnHeight - 1; j++ )
arr.set(j, arr.get(j+1));
or simply, by providing a comparator:
//ArrayList<ArrayList<Item>> items;
//int columnHeight;
for( ArrayList<Item> arr : items )
Collections.sort(arr, new Comparator<Item>() {
#Override
public int compare(Item i1, Item i2) {
return ...; // place the sorting rule here
}
});
For more info, see docs for Collections.sort() & Comparator.
Also, if this is indeed for Bejewelled clone - you may consider doing the "dropping" by doing an iteration dropping all jewels with an empty field beneath by one step, counting the amount of dropped jewels, and repeating this iteration till the amount of drops == 0. That's the algo I used in my clone in the days of the past.
As #vaxquis has already mentioned, it's better to rewrite your code in some more elegant way.
for (int i = 0; i < 10; i++) {
// Perfoming bubble sort for each column
boolean swapped = true;
for(int j = 6; j > 0 && swapped; j--) {
swapped = false;
for (int k = 0; k < j; k++) {
Item currentItem = this.elements.get(k).get(i).getItem();
Item nextItem = this.elements.get(k+1).get(i).getItem();
if (currentItem.getBack().getIcon() != nextItem.getBack().getIcon()) {
swap(currentItem, nextItem); // implement this yourself
swapped = true;
}
}
}
}
Besides the algorithm issues addressed by the other answers, your main problem is that you never change anything in the arrays. The following code just moves some values between local variables:
Position temp = this.elements.get(count).get(i);
Position zero = this.elements.get(count).get(i);
Position previous = this.elements.get(count - 1).get(i);
zero = previous;
previous = temp;
You probably have a setItem() method to set things back into a Position object? Then a swap would be:
Position current = this.elements.get(count).get(i);
Position previous = this.elements.get(count - 1).get(i);
Item temp = current.getItem();
current.setItem(previous.getItem();
previous.setItem(temp);
Related
I came across this problem in class and I'm stuck on it. I did plenty of research but I'm not being able to fix my code.
I need to create a matrix and find the smallest value in the row of the largest value (I believe this element is called minimax). I'm trying to do with a simple 3 x 3 matrix. What I have so far:
Scanner val = new Scanner(System.in);
int matrizVal[][] = new int[3][3];
for (int a = 0; a < matrizVal.length; a++) {
for (int b = 0; b < matrizVal.length; b++) {
System.out.print("(" + a + ", " + b + "): ");
matrizVal[a][b] = val.nextInt();
}
}
int largest = matrizVal[0][0];
int largestrow = 0;
int arr[] = new int[2];
for (int row = 0; row < matrizVal.length; row++){
for (int col = 0; col < matrizVal.length; col++){
if (largest < matrizVal[row][col]){
largest = matrizVal[row][col];
largestrow = row;
}
}
}
To find the so called minimax element I decided to create a for each loop and get all the values of largestrow except the largest one.
for (int i : matrizVal[largestrow]){
if (i != largest){
System.out.print(i);
}
}
Here's where I'm stuck! I'd simply like to 'sort' this integer and take the first value and that'd be the minimax. I'm thinking about creating an array of size [matrizVal.length - 1], but not sure if it's gonna work.
I did a lot of research on the subject but nothing seems to help. Any tips are welcome.
(I don't think it is but I apologize if it's a duplicate)
Given the code you have provided, matrizVal[largestrow] should be the row of the matrix that contains the highest valued element.
Given that your task is to extract the smallest value in this array, there are a number of options.
If you want to simply extract the minimum value, a naive approach would go similarly to how you determined the maximum value, just with one less dimension.
For example:
int min = matrizVal[largestrow][0];
for (int i = 0; i < matrizVal.length; i++) {
if (matrizVal[largestrow][i] < min) {
min = matrizVal[largestrow][i];
}
}
// min will be the target value
Alternatively, if you want to sort the array such that the first element of the array is always the smallest, first ensure that you're making a copy of the array so as to avoid mutating the original matrix. Then feel free to use any sorting algorithm of your choice. Arrays.sort() should probably suffice.
You can simplify your approach by scanning each row for the maximum and minimum values in that row and then deciding what to do with those values based on the maximum value found in previous rows. Something like this (untested) should work:
int largestValue = Integer.MIN_VALUE;
int smallestValue = 0; // anything, really
for (int[] row : matrizVal) {
// First find the largest and smallest value for this row
int largestRowValue = Integer.MIN_VALUE;
int smallestRowValue = Integer.MAX_VALUE;
for (int val : row) {
smallestRowValue = Math.min(smallestRowValue, val);
largestRowValue = Math.max(largestRowValue, val);
}
// now check whether we found a new highest value
if (largestRowValue > largestValue) {
largestValue = largestRowValue;
smallestValue = smallestRowValue;
}
}
This doesn't record the row index, since it didn't sound like you needed to find that. If you do, then replace the outer enhanced for loop with a loops that uses an explicit index (as with your current code) and record the index as well.
I wouldn't bother with any sorting, since that (1) destroys the order of the original data (or introduces the expense of making a copy) and (2) has higher complexity than a one-time scan through the data.
You may want to consider a different alternative using Java 8 Stream :
int[] maxRow = Arrays.stream(matrizVal).max(getCompertator()).get();
int minValue = Arrays.stream(maxRow).min().getAsInt();
where getCompertator() is defined by:
private static Comparator<? super int[]> getCompertator() {
return (a1, a2)->
Integer.compare(Arrays.stream(a1).max().getAsInt(),
Arrays.stream(a2).max().getAsInt()) ;
}
Note that it may not give you the (undefined) desired output if two rows include the same highest value .
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Consider input [3,2,4] and target is 6. I added (3,0) and (2,1) to the map and when I come to 4 and calculate value as 6 - 4 as 2 and when I check if 2 is a key present in map or not, it does not go in if loop.
I should get output as [1,2] which are the indices for 2 and 4 respectively
public int[] twoSum(int[] nums, int target) {
int len = nums.length;
int[] arr = new int[2];
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i = 0;i < len; i++)
{
int value = nums[i] - target;
if(map.containsKey(value))
{
System.out.println("Hello");
arr[0] = value;
arr[1] = map.get(value);
return arr;
}
else
{
map.put(nums[i],i);
}
}
return null;
}
I don't get where the problem is, please help me out
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice. Consider input [3,2,4] and target is 6. I added (3,0) and (2,1) to the map and when I come to 4 and calculate value as 6 - 4 as 2 and when I check if 2 is a key present in map or not, it does not go in if loop.
Okay, let's take a step back for a second.
You have a list of values, [3,2,4]. You need to know which two will add up 6, well, by looking at it we know that the answer should be [1,2] (values 2 and 4)
The question now is, how do you do that programmatically
The solution is (to be honest), very simple, you need two loops, this allows you to compare each element in the list with every other element in the list
for (int outter = 0; outter < values.length; outter++) {
int outterValue = values[outter];
for (int inner = 0; inner < values.length; inner++) {
if (inner != outter) { // Don't want to compare the same index
int innerValue = values[inner];
if (innerValue + outterValue == targetValue) {
// The outter and inner indices now form the answer
}
}
}
}
While not highly efficient (yes, it would be easy to optimise the inner loop, but given the OP's current attempt, I forewent it), this is VERY simple example of how you might achieve what is actually a very common problem
int value = nums[i] - target;
Your subtraction is backwards, as nums[i] is probably smaller than target. So value is getting set to a negative number. The following would be better:
int value = target - nums[i];
(Fixing this won't fix your whole program, but it explains why you're getting the behavior that you are.)
This code for twoSum might help you. For the inputs of integer array, it will return the indices of the array if the sum of the values = target.
public static int[] twoSum(int[] nums, int target) {
int[] indices = new int[2];
outerloop:
for(int i = 0; i < nums.length; i++){
for(int j = 0; j < nums.length; j++){
if((nums[i]+nums[j]) == target){
indices[0] = i;
indices[1] = j;
break outerloop;
}
}
}
return indices;
}
You can call the function using
int[] num = {1,2,3};
int[] out = twoSum(num,4);
System.out.println(out[0]);
System.out.println(out[1]);
Output:
0
2
You should update the way you compute for the value as follows:
int value = target - nums[i];
You can also check this video if you want to better visualize it. It includes Brute force and Linear approach:
I have a JLabel array that starts with an integer number of elements. How can I remove an certain number of elements from the array? For example, every time the int is updated:
int i = 21;
i = i - removedElements
How can I update the array to contain that many elements, instead of creating an entirely new array with the desired number of elements?
As others have already mentioned, List is the way to go here since it is specifically designed for adding and or deleting elements.
However if you would prefer to use the JLabel Array you already have in established then you will need to realize that the only way to delete an element from that array is to actually create another array with the desired element to delete excluded from it then return it into the original array. Below I have supplied a simple method named deleteJLabelFromArray() that can do this for you:
public static JLabel[] deleteJLabelFromArray(JLabel[] srcArray, int... indexesToDelete) {
int counter = 0;
JLabel[] newArray = new JLabel[srcArray.length - indexesToDelete.length];
for (int i = 0; i < srcArray.length; i++) {
boolean noGo = false;
for (int j = 0; j < indexesToDelete.length; j++) {
if (i == indexesToDelete[j]) { noGo = true; break; }
}
if (noGo == false) { newArray[counter] = srcArray[i]; counter++; }
}
return newArray;
}
With this method you can delete whatever indexes you supply within the indexesToDelete argument (delimited with a comma). Copy/Paste the code into your project then you can use it something like this:
JLabel[] jla = {jLabel2,jLabel3,jLabel4,jLabel5};
jla = deleteJLabelFromArray(jla, 2);
for (int i = 0; i < jla.length; i++) {
System.out.println(jla[i]);
}
In this example we are going to delete the element number 2 (remember that arrays are 0 based) and therefore jLabel4 would be removed from the Array.
Keep in mind that this would be scary stuff with really big arrays.
Hope this helps.
I am trying to create shopping lists from a collection of products, where the returned shopping list should be optimized for cost as well as to meet another condition.
For example, let's say that I want to create shopping lists based on the energy content of the products. When the user enters a total sum, the returned shopping list should try to max out the kcal content while keeping the total sum at or around the sum specified by the user.
I've gotten so far as to create the collection of products, and all products are stored as objects with fields holding nutritional values and price etc. The kcal-value is also stored as a member variable in each product's object.
At first I considered looping through all combinations of products, sort out those that are way out of the price interval, and then return the one with the highest kcal content. But as the numbers of products available increases this soon becomes a non-viable option I think.
I now wonder if there is any algorithm to solve this problem, if not, is there any way to easily implement this?
I did something similiar with Dynamic Programming Wikipedia article on Dynamic Programming
In the following costs and values should be arrays of the same length. The length of the possible items to choose from. The capacity is the maximum sum of all the costs of items you choose. It returns an array of booleans of the same length determining whether to take the item or not.
The idea is to create a table with the solutions to sub-problems that can then be used to solve a bigger problem. The sub-problems just solve the same problem but with a smaller list, initially with only one item. The table contains the best value you can get with the first i items for each weight up to the maximum. As you add one potential item to the list you add its value to the previous solution for that allowed weight minus the weight your adding and check if that is better than the previous solution without the last item. Once the last row is created you can tell which items to take by checking for where there are differences in the values in that last row.
public boolean[] solve(int[] values, int[] costs, int capacity) {
boolean take[] = new boolean[values.length];
int min_cost = Integer.MAX_VALUE;
for (int i = 0; i < values.length; i++) {
if (costs[i] < min_cost) {
min_cost = costs[i];
}
}
int table[][] = new int[values.length][capacity + 1 - min_cost];
for (int i = 0; i < values.length; i++) {
int v = values[i];
int w = costs[i];
for (int j = 0; j < capacity - min_cost + 1; j++) {
int prev_value = 0;
int new_value = 0;
if (i > 0) {
prev_value = table[i - 1][j];
if (w <= j + min_cost) {
if (w <= j) {
new_value = table[i - 1][j - w] + v;
} else {
new_value = v;
}
}
} else if (w <= j + min_cost) {
new_value = v;
}
table[i][j] = Math.max(prev_value, new_value);
}
}
int index = capacity - min_cost;
for (int i = values.length - 1; i > 0 && index >= 0; i--) {
if (table[i][index] != table[i - 1][index]) {
take[i] = true;
index -= costs[i];
if (index < 0) {
System.err.println("index = " + index);
}
} else {
take[i] = false;
}
}
take[0] = index >= 0 && table[0][index] != 0;
return take;
}
// gives next index in array which wraps around in a ring; moves clockwise through indices
private int nextSlot(int k) {
return ((k + 1) % A.length);
}
// Insert method
public void insert(int k) {
if( size == A.length)
resize();
A[next] = k;
for(int i = 0; i < next; i = nextSlot(i)) {
if(k < A[i]) {
for( int j = next - 1; j >= i; j--){
A[nextSlot(j)] = A[j];
}
A[i] = k;
break;
}
}
next = nextSlot(next);
size++;
}
I am trying to create an insert/sort method that inserts values into a circular priority queue in ascending order. The problem I'm having is when the next pointer cycles back to the beginning of the array, the items at the front of the queue aren't being sorted. I've been struggling with this for hours now, any help would be greatly appreciated.
Specifically, when next cycles back to the beginning, it's going to be 0, and therefore this for loop:
for(int i = 0; i < next; i = nextSlot(i)) {
will not do anything.
In general, however, I see several problems with your program. First of all, why are you implementing this as a circular array? Circular arrays are useful when you want to be able to quickly add/remove from both the beginning and end of an array. You seem to be inserting into the middle, so there is no reason to complicate your code when you're doing a linear search through the entire list at each insert anyway.
Finally, be aware that when operating on a circular array, you need to take into account that your indices will wrap around and become 0. Therefore, this line:
for( int j = next - 1; j >= i; j--)
is wrong for at least two reasons:
j>=i is not the correct way to find out if j has reached i
j-- is also wrong as j-1 needs to be wrapped