Finding the desired sum in a row of a 2d array java - java

I'm having trouble wrapping my head around how to implement a method that starts with an int[][] input and a predefined sum value that returns an int[][] output that only displays the adjacent values in the row that add up to the sum. For example, if the input array was
int[][] input = new int[][]{
{3,4,4,2,7},
{2,3,2,8,6},
{1,4,2,1,2}
}
when the sum is set to 7, it would yield an output array with the following values
{3,4,0,0,7},
{2,3,2,0,0},
{1,4,2,1,0}
}
The output array should only display values that add up to a set number (7) with their neighbors, or if its a number from 0-9 values that are the desired sum (when you search for 7 it displays all 7s). To further clarify, as you can see in the output array, it displays the first two values, 3 and 4, because they add to 7. It displays 2,3,2 because they also add to 7. It prints out 1,4,2,1 on the bottom because 1,4,2 add to 7 and 4,2,1 add to 7. To summarize, it displays only values which are 7 or add up to 7 with the numbers next to them, and otherwise displays 0. Also the input values must be <0.
After brainstorming for a while I know that the code will need a number of nested loops: one to loop through the rows, inside that one to loop through the columns, inside that a loop to update the sum which stops when the sum equals the preset sum (7 in this case), and finally a loop to update the output[][]. However, I'm having a great deal of trouble on writing code that implements all of these loops correctly. I am planning on doing the same thing with numbers that add up vertically, but want to focus on horizontal as of now.

This can be done in O(NxM) complexity.
For each row, you keep two indexes (say, iLow and iHigh initialised to the first item input [i][0]) and a sumSoFar variable. At each iteration, if the sumSoFar < 7 you increment iHigh. If it is > 7 then you increment iLow and iHigh. If It is == 7 then you've found one combination + increment iLow and iHigh.
This should give the high-level idea of the algorithm and I'm sure that a lot of details are missing/incomplete but you should be able to put that in code.

You need three nested loops. Or really, three levels of nested loops with two loops after each other on the innermost level, but I will return to that in the end.
Before any loops, create the backbone of your result array. It’s OK if it’s an array of null references to arrays at this point.
Outer loop: loop through the outer array. A classical for loop is one option. For each entry, create an inner array of the correct length in the result, filled with zeroes for a start.
Middle loop, loop through the entries in the inner array. Again a classical for loop is fine. Your goal is that each iteration will determine if a series of adjacent values with the sum 7 begins at this entry, and if so, find out how long it is, and copy the entries in question to the result array.
Inner loop (first inner loop, that is) is for adding adjacent entries to find out if the sum is 7. You start from the entry from the middle loop and add up the values. This loop has a double stop condition: you stop when the sum is 7 or greater (assuming all values are positive), but obviously you also stop when reaching the end of the inner array. A while loop would be for my taste. Only if the sum hits exactly 7, do you use a new inner loop to copy the values to the result.
PS If you assume all values are positive, you shouldn’t just assume, you should check. In the middle loop, if the value in that entry is 0 or negative, throw an IllegalArgumentException.

Related

A collection which holds a specific number of values before being overwritten

I need to use a Collection type in Java which will allow me to add values input by the user one at a time. When a new value is added it is added at index 0 and the previous index 0 value is moved to index 1 etc. Once there are 20 values I then want it to start replacing the 1st value, then the 2nd value and so on whilst moving the other values up 1 index.
i.e once all 20 values are filled, the next input becomes index 0, index 1 -> index 2 and so on. index 20 will be forgotten.
I have so far used an ArrayList of Integers but now I have come across this problem. I am wondering if another type of Collection would be best? The Collection will more than likely hold duplicate values.
From the 20 values I will want to sort in ascending order and then find the average of the top 8. I am currently doing that by copying to a second Arraylist within a method, sorting and then adding up the top 8 values and dividing by 8. This way the master list remains the same.
I am not sure there is an efficient way to do what I need with an arraylist.

How nested array in a loop will work

I am trying to understanding the working of this array in a loop
for (int answer=0; answer<responses.length; answer++)
{
++frequency[responses[answer]]
}
Frequency is an array initialized in start as
int [] frequency = new int [6];
We also have responses as an array having values int[] responses= {1,2,3,4,4,4,4,4}
I am not understanding how this ++frequency[responses[answer]] works, it look to me nested array but how it will work ?
There is no nested arrays. You are just nesting two array access syntaxes.
To explain this code, we first need to know how will the answer variable change. From the for loop header, we can see that it starts from 0, and goes all the way up to responses.length - 1, which is 8. Now we can evaluate the expression frequency[responses[answer]]:
// in each iteration of the loop
frequency[responses[0]]
frequency[responses[1]]
frequency[responses[2]]
frequency[responses[3]]
frequency[responses[4]]
frequency[responses[5]]
frequency[responses[6]]
frequency[responses[7]]
Now we can evaluate the responses[x] part. We just need to find the corresponding response in the responses array. responses[0] is the first item, which is 1.
frequency[1]
frequency[2]
frequency[3]
frequency[4]
frequency[4]
frequency[4]
frequency[4]
frequency[4]
The statement also includes the ++ operator, which increments that particular index of frequency by 1. So all of the above indices will be incremented by 1 one after another, making the frequency array look like this:
[0, 1, 1, 1, 5, 0]
On a higher level of abstraction, this code is counting how many times a particular response appears in the responses array. For example, 4 appeared 5 times.
The expession
++frequency[responses[answer]]
is exactly the same as if it had been written
int fi = responses[answer];
++frequency[fi];
frequency has six elements, and all the entries in responses are valid indices for a six-element array. answers has eight elements, so as long as answer is between 0 and 7, the whole thing will work.

Swapping a particular element with the one above it, in a randomly ordered ArrayList

I have a ArrayList from 1 - 9 that is randomly ordered and will be represented in three rows like this order for example:
6,5,7
4,8,1
9,2,3
It should be noted that I'm working with just a flat list, but I intend to represent it like above later on.
What I need is to be able to always swap the 9 element with the one above it. So for the configuration above I would need to swap the 9 and the 4. This needs to be done for any order where the 9 element might appear.
I've already created a switch statement that should do this when a user presses a key on the keyboard. So the logic of this swap should go in that switch case.
I wrote this code to try and achieve this goal, but it doesn't work as intended.
case 'u' :
int nineIndex = temp.indexOf(9);
int nine = 9;
int indexToSwapTo = temp.indexOf(9) - 3 % 9;
System.out.println("index of 9: " + nineIndex);
System.out.println("index to swap to : " + indexToSwapTo);
temp.remove(nineIndex);
temp.add(nineIndex, indexToSwapTo);
temp.remove(indexToSwapTo);
temp.add(indexToSwapTo, nine);
break;
The idea is, I first get the index of the 9 and then to get the index of the item above it I do the index at 9 - 3. I then perform some adds and removes. I should also note that the temp is an ArrayList that holds the random configuration of numbers. However this code doesn't work quite as intended. It does this instead:
The randomly order array list produces the following:
[6,1,8,3,7,**4**,2,5,**9**]
And after a swap occurs as described above, the ArrayList turns into this:
[6,1,8,3,7,**9**,2,5,**5**]
The printout says this as well which is useful:
index of 9: 8 index to swap to : 5. As you can see although it does swap the items in the correct place it for some reason puts index 5 as the item to be swapped rather than the actual value of index 5 which is 4. It also sometimes runs with out of bounds exceptions.
Use Collections.swap
You're way overthinking the problem. Just use the API available to you.
int nineIndex = temp.indexOf(9);
int indexToSwapTo = (nineIndex + 6) % 9;
Collections.swap(temp, nineIndex, indexToSwapTo);
Note this assumes that when 9 is on the top line, the "above" line is the bottom one, as in a circular way.
First off, the % operator in Java has a higher precedence than - so your line 4 is
equivalent to
int indexToSwapTo = temp.indexOf(9) - 3;.
This will work, but only for the last two rows. You should add some parentheses around the right hand side to cover every case, like this:
int indexToSwapTo = (temp.indexOf(9) - 3 ) % 9;
Secondly, there is a logical error in your code. In particular, in the first code block that adds and removes the ArrayList entries:
temp.remove(nineIndex);
temp.add(nineIndex, indexToSwapTo);
The second line is wrong, as it attempts to insert the index of the entry that you're meant to swap with, and not the value of that entry. In your example, the program correctly realises that it needs to swap the ArrayList entries at indices 5 and 8. However, in your code, you are telling the program to store 5 in the position of 9, instead of telling it to store the contents of index 5 in the position of 9 (which in this case, is the 8th entry of the ArrayList).
To fix your code, you should replace the code block above with this:
int value_to_be_swapped = temp.get(indexToSwapTo)
temp.remove(nineIndex);
temp.add(nineIndex, value_to_be_swapped);

efficient algorithm to check if there exists a row and a column with same values?

I am trying to solve this problem using the least running time.
If we're given a 2D array, we need to return x if there exists a row where all values equal x, and there is a column where all values equal x.
For example, for the following 2d array,
0 3 1
2 3 1
1 1 1
we are supposed to return 1 since the last row and last column are all of same value 1. If no such number exists, we can return -1.
I know there are many ways to solve the problem and most of them are of O(n^2), I'm wondering if there is an efficient way(i.e O(n)) to find such value. (where n represents the number of cells in this array)
Ok, you clarified that you consider O(n) to be the number of values in the 2D array.
I'll outline the approach in pseudo-code, which you can translate to either Java or C++, whichever is your preference. Your question is tagged with both, and the pseudocode is trivial enough to be directly translatable into either C++ or Java. Or Perl. Or Python...
Part 1
Let's start with the first, easy step, how to check whether there's any row that contains the same value. The pseudocode for this is elementary:
start with the 0th row, n=0
check if matrix[n][0] through [n][m-1] (where m is the number of columns in the matrix) contain the same value. If so, you found it.
otherwise, increment n, to go to the next row, until you reach the bottom of the matrix.
You should be able to understand that. This is basic, elementary "Computer Science 101" stuff.
Part 2
Now, let's modify this pseudocode to simultaneously check the columns as well. Modify the above pseudocode as follows.
Create two one-dimensional vectors, call the first one top_values, or something, whose size is m, the number of columns in your matrix. Call the second one flags, it's a vector of boolean flags, also their size is m.
When you scan the 0th row, in the pseudocode given in the first part, copy the values from the 0th row, into top_values. That is, copy matrix[0][x] into top_values[x]. Also set flags[x] to true (you can initialize all flags to true even before you scan the 0th row, it doesn't matter).
When you scan each one of the remaining rows, using the pseudocode given in Part 1, compare matrix[y][x] (where y is the row# you're scanning) against top_values[x]. If they are not the same, set flags[x] to false.
At the end of the pseudocode from part 1, check your flags vector. If any value in it is still true, there's a column in your matrix whose values are the same.
Your homework assignment is to make a slight tweak to the above pseudocode to also tell you which value is the same, in some row or column.

Complex Loop with limited iterations and IF statement

The loop needs to scan an external file, from the bottom to the top. BUT...
When the loop has scanned 6 items from the external file, it needs to stop.
Then, IF there are less than 6 items to scan from the list on the external file it needs to print all of the those items to the screen.
I know how to do a loop that can scan the file from top to bottom using inFile.hasNext(); etc. I just don't know how to do from bottom to top and then define how many iterations I want the loop to actually do, with an if statement that is something like:
if (number of iterations < 6 print all)
{
JOptionPane.showMessageDialog(iteration1, iteration2, etc...)
}`
else if (number of iterations >= 6 only show the first 6 the loop has scanned)
{
JOptionPane.showMessageDialog(iteration1, iteration2, etc...)
}
Sorry about my awful pseudo code, just really stuck and this is the last part I need to do to finish my system!
any help would be brilliant!
I would recommend using a predefined class for reading backward. As to looping:
for(int i = 0; i < 6 && /* test for more input*/; i++)
{
JOptionPane.showMessageDialog( /*next input*/ );
}
I'd try instantiating an array with 6 empty strings and then concatenate the item you get in each iteration of the loop with the corresponding empty string in your array.
Afterwards you can check for your < 6 condition and depending on the result concatenate the string you want to give to your JOptionPane
You can't read a file from bottom to top. Instead, read the file (top to bottom) keeping the last (up to) 6 items read. When you hit the end if the file, test if you you have 6 items or not and act accordingly.
Use a LinkedList object, which allows removal of the element of the list via removeFist().
You could just store all items and use only the last 6, but that may mean using a lot of memory if the file is very large.

Categories

Resources