How to traverse an array like a sine-wave? - java

Assume I had a 2D integer array, mxn.
I want to traverse this array like a sine wave.
In specific, traversal would start from the last row, and the first column, move onto the first row and the second column, move onto the last row and the third column.
I have attached an image to elaborate further.
t:
I only know how to traverse in order, but I was thinking of transposing the columns, changing the starting index of the column at every round, but I couldn't create a consisting loop to do so.
My attempt:
boolean startsAtbottom=true;
//cols become rows, startPoint alternates
for(int i = 0;i<n;i++)
{
if(startsAtbottom)
{
for(int j =m-1;j>-1;j--)
{
System.out.print(myArr[j][i]);
}
startsAtbottom=false;
}
else
{
for(int j =0;j<m;j++)
{
System.out.print(myArr[j][i]);
}
startsAtbottom=true;
}
}

The following code will do what you want. All you want is to change the way you traverse in consecutive iterations.
boolean traverseInOrder=true;
for(int i=0;i<columnCount;i++){
for(int j=0;j<rowCount;j++){
index=j;
if(!traverseInOrder){
index=rowCount-j-1;
}
//access the element
int element=array[i][index];
}
traverseInOrder= !traverseInOrder;
}

Your solution works, and there's nothing wrong with it. However you can get rid of the if by doing this:
for (int i = 0; i < n; i++) {
boolean goingUp = i % 2 == 0;
for (int j = 0; j < m; j++) {
int row = goingUp ? m - 1 - j : j;
System.out.println(myArr[row][i]);
}
}

Starting from your input you have that:
the outer loop index just increments from 0
the inner loop index increments for even columns and decrements for odd columns
you can determine if a number is even or odd by just checking if modulo is 0 (or by checking if (i & 0x01) == 0 but that's irrelevant)
Given this it's quite easy to model that pattern:
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
int value = data[i][i % 2 == 0 ? (cols - j - 1) : j]
}
}
The formula cols - j - 1 allows you to start from the end and go backward (see that with j = 0 you have cols - 1 and with j = cols - 1 you have cols - (cols - 1) - 1 == 0).
Mind that Java is nor column major nor row major, since a bidimensional array is just an array of arrays so according to your real layout you may need to swap indices.

Related

Manual array copy in a nested for loop

I trying to find all 2s, move them to the back of the array, and turn them into 0s without loosing the order of the array. For example, [1,2,3,2,2,4,5] would become [1,3,4,5,0,0,0]. My code works fine but the IDE is telling me that the nested for loop is copying the array manually and wants me to replace it with System.arraycopy(). How would I go about that?
Code looks like this:
int[] numbers = {1,2,3,2,2,4,5};
for (int i = 0; i < numbers.length; i++){
if (numbers[i] == 2){
for (int j = i; j < numbers.length - 1; j++){
numbers[j] = numbers[j + 1];
}
numbers[numbers.length-1] = 0;
i --;
}
}
The following statement:
for (int j = i; j < numbers.length - 1; j++){
numbers[j] = numbers[j + 1];
}
Can be replaced by:
System.arraycopy(numbers, i + 1, numbers, i, numbers.length - 1 - i);
IDEs like IntelliJ should suggest that automatically when you press alt + enter (default key combination).
Now about arraycopy()
From the documentation, java.lang.System.arraycopy() will copy n elements (last argument) from the source array (1st argument) to the destination array (3rd argument) with the corresponding indexes to start from (2nd and 4th arguments).
More specifically, when calling arraycopy(numbers, i + 1, numbers, i, numbers.length - 1 - i) the arguments are:
numbers: The source array.
i + 1: The starting position in the source array.
numbers: The destination array.
i: The starting position in the destination data.
numbers.length - 1 - i: The number of array elements to be copied.
In your case, elements will be copied from your array, to itself, but the fact that source starting position is shifted from the destination starting position will induce the global shifting you're after (moving elements to the left).
About the number of elements to be moved, it should move i elements minus the first one that doesn't move and only gets overwritten. Hence the length - 1 - i.
The inner loop could be replaced with an arraycopy, however, you don't need an inner loop:
int[] numbers = {1,2,3,2,2,4,5};
int j = 0;
for (int i = 0; i < numbers.length; i++){
if (numbers[i] != 2){
numbers[j++] = numbers[i];
}
}
while (j < numbers.length) {
numbers[j++] = 0;
}
UPDATE
Or even:
int[] numbers = {1,2,3,2,2,4,5};
int j = 0;
for (int n: numbers){
if (n != 2){
numbers[j++] = n;
}
}
Arrays.fill(numbers,j,numbers.length,0);
The key thing is pretty simple: if you can reduce the lines of code you are responsible for (for example by using utility methods such as Arrays.arraycopy()) - then do that.
Keep in mind: each line that you write today, you have to read and understand tomorrow, and to probably modify in 5 weeks or months from now.
But then: I think you are over-complicating things here. I would use a temporary list, like this:
List<Integer> notTwos = new ArrayList<>();
int numberOfTwos = 0;
for (int i=0; i<source.length; i++) {
if (source[i] == 2) {
numberOfTwos++;
} else {
notTwo.append(source[i]);
}
}
... simply append `numberOfTwo` 0s to the list, and then turn it into an array
You see: you are nesting two for-loops, and you are repeatedly copying around elements. That is inefficient, hard to understand, and no matter how you do it: way too complicated. As shown: using a second list/array it is possible to "solve" this problem in a single pass.
After replacing your inner loop with System.arrayCopy the code should look like:
int[] numbers = { 1, 2, 3, 2, 2, 4, 5 };
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == 2) {
System.arraycopy(numbers, i + 1, numbers, i, numbers.length - 1 - i);
numbers[numbers.length - 1] = 0;
i--;
}
}

selection sort loop questions in Java

I have a basic question about the inner loop length in Java selection sort. Here is the commonly used code for selection sort:
package com.java2novice.algos;
public class MySelectionSort {
public static int[] doSelectionSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int index = i;
for (int j = i + 1; j < arr.length; j++)
/* why not the length is not arr.length-1? I think the length is
exactly the same as what it is, the array's length is a
static number as array.length-1, but when it comes to the inner
loop why it plus 1 to the array length? */
if (arr[j] < arr[index])
index = j;
int smallerNumber = arr[index];
arr[index] = arr[i];
arr[i] = smallerNumber;
}
return arr;
}
}
Imagine you're trying to sort five items. The array length is 5, which means the indexes are 0 through 4.
In the first iteration of the inner loop, you have i=0 and j=1. You need j to index to the end of the array. That's why the expression in the inner loop is j < array.Length.
i, of course, only goes from 0 to 3, which is why the outer loop has i < array.Length - 1.
If you lay five playing cards on a table and walk through the steps of the selection sort, you'll get a better idea of what's happening here.
the first loop does not need to check the last index, therefore, it goes to arr.length - 1. on the second loop, of course, the last index of the array must be checked so the loop goes to the last index (arr.length).
imagine if the first loop goes to the last index. then this line for (int j = i + 1; j < arr.length; j++) will never execute.
check out this Pseudo code of selection sort for a better understanding of the algorithm

Checking for Adjacent elements in 2d Arrays and replacing them

So, I am building a method to check a 2d array for a target value and replace each adjacent element with that target value. I have literally tried to brainstorm the solution to this for about an hour and I just want to know if anyone can help me with this, this is the code I have so far
public int[][] replaceValue(int n, int[][]y){
int [][]temp0 = new int[y.length][y[0].length];
int[]top, down ,left, right = new int[y[0].length];
for(int row = 0; row < y.length; row++){
for(int col = 0; col < y[row].length; col++){
temp0[row][col] = y[row][col];// new array so I wouldn't mess with the array passed in
}
}
for(int row = 0; row < temp0.length; row++){
for(int col = 0; col < temp0[row].length; col++){
top[row] = temp0[row-1][col];
down[row] = temp0[row+1][col];
right[row] = temp0[row][col+1];
left[row] = temp0[row] [col-1];
}
}
I got error messages such as I didn't initialize my top and left and right and down variables but I simply don't understand how the logic works for checking the adjacent elements and making sure the whole array is not replaced with the target value. Thanks
The question is a little confusing so I will try to interpret it.
What you are given is a 2-dimensional array with some integer values. Your function should scan the 2-d array, and if you find some target value,
return a 2-d array with the adjacent indices as the target value as well.
For example, if we have a 3x3 array and the target is 2...
1 1 1 1 2 1
1 2 1 ====> 2 2 2
1 1 1 1 2 1
Your problem is that you can't think of a way to change the value without changing the entire array to 2.
Solution One: You scan for the target value in the given array, but you update the values in the temporary array.
Solution Two: You scan the temporary array, and store whether or not it should be changed using a 2-d boolean array.
Solution One is much better in terms of efficiency (both memory and time), so I'll just give you my solution #2, and leave you to do Solution One on your own.
Also, please use more descriptive variable names when it matters :P (why is the input called temp??)
public static int[][] replaceValue(int target, int[][] currArray){
int[][] temp = new int[currArray.length][];
//get a boolean array of same size
//NOTE: it is initialized as false
boolean[][] needsChange = new boolean[currArray.length][currArray[0].length];
//copy the current array into temp
for(int i = 0; i < currArray.length; i++){
temp[i] = currArray[i].clone();
}
//Go through each value in the 2d array
for(int i = 0; i < temp.length; i++){
for(int j = 0; j < temp[0].length; j++){
//if it is the target value, mark it to be changed
if(temp[i][j] == target){
needsChange[i][j] = true;
}
}
}
//Go through each value in the 2d array
for(int i = 0; i < temp.length; i++){
for(int j = 0; j < temp[0].length; j++){
if(needsChange[i][j]){ //NOTE: same as "needsChange[i][j] = true;"
//Now, we will check to make sure we don't go out of bounds
//Top
if(i > 0){
temp[i-1][j] = target;
}
//Bottom
if(i + 1 < temp.length){
temp[i+1][j] = target;
}
//Left
if(j > 0){
temp[i][j-1] = target;
}
//Right
if(j + 1 < temp[0].length){
temp[i][j+1] = target;
}
}
}
}
//return the new array we made
return temp;
}
You have not initialized your local variables before first use. So you need to change your 3rd line to some thing like the below code:
int[] top = new int[temp[0].length], down = new int[temp[0].length],
left = new int[temp[0].length], right = new int[temp[0].length];
After that your code is compiled and you can check your logic.

Print characters as a Matrix

Below problem has a list of characters and number of columns as the input. Number of columns is not a constant and can vary with every input.
Output should have all the rows fully occupied except for the last one.
list: a b c d e f g
colums: 3
Wrong:
a b c
d e f
g
Wrong:
a d g
b e
c f
Correct:
a d f
b e g
c
I have tried below:
public static void printPatern(List<Character> list, int cols) {
for (int i = 0; i < cols; i++) {
for (int j = i; j < list.size(); j += cols) {
System.out.print(list.get(j));
}
System.out.println();
}
}
It gives output as (which is wrong):
a d g
b e
c f
I am trying to come with an algorithm to print the correct output. I want to know what are the different ways to solve this problem. Time and Space complexity doesn't matter. Also above method which I tried is wrong because it takes columns as the parameter but that's actually acting as the number of rows.
FYI: This is not a HOMEWORK problem.
Finally able to design the algorithm for this problem
Please refer below java code same
public class puzzle{
public static void main(String[] args){
String list[] = { "a", "b", "c","d","e","f","g","h","i","j" };
int column = 3;
int rows = list.length/column; //Calculate total full rows
int lastRowElement = list.length%column;//identify number of elements in last row
if(lastRowElement >0){
rows++;//add inclomplete row to total number of full filled rows
}
//Iterate over rows
for (int i = 0; i < rows; i++) {
int j=i;
int columnIndex = 1;
while(j < list.length && columnIndex <=column ){
System.out.print("\t"+list[j]);
if(columnIndex<=lastRowElement){
if(i==rows-1 && columnIndex==lastRowElement){
j=list.length; //for last row display nothing after column index reaches to number of elements in last row
}else{
j += rows; //for other rows if columnIndex is less than or equal to number of elements in last row then add j value by number of rows
}
}else {
if(lastRowElement==0){
j += rows;
}else{
j += rows-1; //for column greater than number of element in last row add j = row-1 as last row will not having the column for this column index.
}
}
columnIndex++;//Increase column Index by 1;
}
System.out.println();
}
}
}
This is probably homework; so I am not going to do it for you, but give you some hints to get going. There are two points here:
computing the correct number of rows
computing the "pattern" that you need when looping your list so that you print the expected result
For the first part, you can look into the modulo operation; and for the second part: start iterating your list "on paper" and observe how you are printing the correct result manually.
Obviously, that second part is the more complicated one. It might help if you realize that printing "column by column" is straight forward. So when we take your correct example and print the indexes instead of values, you get:
0 3 6
1 4 7
2 5
Do that repeatedly for different input; and you will soon discover the pattern of indexes that you need to print "row by row".

java 2d array comparing UPDATED

(UPDATED)
I'm having trouble figuring out what to do here, i need to compare a 2d array that to see if any of the numbers match. I need four numbers to match either up/down, left/right, or diagonal. I just can't get it to test for the down/left diagonal ( / ) here is my updated code
public static boolean isAdjacentFour( int[][] a ) {
// Code to test if column has four adjacent numbers
for ( int row = 0; row <= a.length - 3 ; row++) {
for (int col = 0; col <= a[0].length - 1 ; col++) {
if (a[row][col] == a[row+1][col] && a[row+2][col] == a[row][col]
&& a[row+3][col] == a[row][col]) {
return true;
}
}
}
// Code to test if row has four adjacent numbers
for ( int row = 0; row <= a.length - 1 ; row++) {
for (int col = 0; col <= a[0].length - 3 ; col++) {
if (a[row][col] == a[row][col+1] && a[row][col] == a[row][col+2]
&& a[row][col] == a[row][col+3]) {
return true;
}
}
}
// Code to test if there are 4 adjacent numbers in a down/right ( \ )diagonal
for ( int row = 0; row <= a.length - 3 ; row++) {
for (int col = 0; col <= a[0].length - 3 ; col++) {
if (a[row][col] == a[row+1][col+1] && a[row][col] == a[row+2][col+2]
&& a[row][col] == a[row+3][col+3] ) {
return true;
}
}
}
for ( int row = 0; row <= a.length - 3 ; row++) {
for (int col = 0; col <= a[0].length + 3 ; col--) {
if (a[row][col] == a[row+1][col-1] && a[row][col] == a[row+2][col-2]
&& a[row][col] == a[row+3][col-3] ) {
return true;
}
}
}
return false;
}
Well one problem I noticed in the first nested for loop is this line of code,
for ( int row = 0; row <= a.length - 3 ; row++)
The way you have it now, the row variable is going to be incremented with each iteration of the outer for loop. However, with how you're executing your program, the condition should be row <= a.length - 4 and here's why. Suppose you had a four by four 2D array. The nested for loop will go through one normal iteration of the inner loop, which actually checks every single column for possible matches of four consecutive matching numbers in a column. Here's what it looks like when actually running the program starting at the outer for loop and row = 0,
Iteration One of the inner for loop:
if (a[0][0] == a[1][0] && a[2][0] == a[0][0] && a[3][0] == a[0][0])
Iteration Two of the inner for loop:
if (a[0][1] == a[1][1] && a[2][1] == a[0][1] && a[3][1] == a[0][1])
Iteration Three of the inner for loop:
if (a[0][2] == a[1][2] && a[2][2] == a[0][2] && a[3][2] == a[0][2])
Last Iteration of the inner for loop:
if (a[0][0] == a[1][3] && a[2][3] == a[0][3] && a[3][0] == a[0][3])
Once this is done, the row variable will be incremented according to the outer loop definition. This is what is most likely causing an error because now as we start iterating through the inner loop with row = 1, this happens
Iteration One of the inner for loop:
if (a[1][0] == a[2][0] && a[3][0] == a[1][0] && a[4][0] == a[1][0])
Here, we already have an indexoutofboundsexception when trying to access the 5th row in a 4x4 2D array. So the simple fix here is to change
for(int row = 0; row <= a.length - 3 ; row++)
to
for(int row = 0; row <= a.length - 4 ; row++)`
A similar argument can be made for the second nested for loop. If you don't believe me, do something similar to what I did for the rows and write out the iterations for it using a 4x4 2D array. You'll get the arrayindexoutofbounds exception in the first iteration of the outer for loop and in the second iteration of the inner for loop when row = 0 and col = 1, causing the program to make a check at the fifth column in the first row of a 2D array. So the simple fix should be to change
for (int col = 0; col <= a[0].length - 3 ; col++)
to
for (int col = 0; col <= a[row].length - 4 ; col++)
Personally, I prefer to use a[row].length only because there could be some instances where it's not a perfect nxn 2D array. For example, some rows may have only 3 columns where the first row has 7 columns. If this is the case, then you'll get an outofbounds exception for trying to access columns that exist in the first row that don't exist in other rows.
For the third nested for loop, again, same argument can be made just by writing out the iterations and it should be changed to
for(int row = 0; row <= a.length - 4 ; row++) {
for(int col = 0; col <= a[row].length - 4 ; col++)
The last nested for loop has a logic problem pertaining to the inner for loop. Since you're decrementing from 0, you're going to get an out of bounds exception just from trying to access negative indices in the array. So the simple fix should be to initialize col to the last column and change the condition to col being greater than or equal to 3 since you're accessing elements at the columns, col, col-1, col-2, and col-3. If that is confusing, think about it this way. You're checking columns starting from col and the three that come before it. What if there aren't even four columns to begin with? This is why there's the condition col >= 3 because you check a column and the three that come before it until you've reached column #4 (col = 3). Once you've reached column #3 (col = 2), there's no way of checking that column and the three before because there are only 3 columns to check at this point. Changes similar to the other 3 nested loops should be made to for ( int row = 0; row <= a.length - 3 ; row++) regarding the -3. It should end up looking like this,
for ( int row = 0; row <= a.length - 4 ; row++) {
for (int col = a[row].length - 1; col >= 3; col--)
As a rule of thumb , always put debug points to see why you are getting exception/error.
The issue here is your outer loop runs from 0 to row-1 . But inside in inner loop you are using [row+2] and [row+3] and [row+1] . Now when the outer loop goes to row-2 iteration , you will get a out of bound exception.
Can post the code here , but if you understand this , you should be able to solve it.
(EDIT) : example as asked in comment.
assume you have a 2D array A[][]of size 10X10 .
Now if the current loop is at A[4][4] or (A[row][col]) :
left element : A[4][3] or (A[row][col-1]) // here we are at same row but (column -1) as we want the left element.
top-right element : A[3][5] or ((A[row-1][col+1]) // here we are going to (4-1) row as we are interested in above row and (4+1)column as we want right element.
bottom-left: A[5][3] (A[row+1][col-1]) ...
Now the two consecutive bottom-left elements will be (A[row+1][col-1]) and (A[row+2][col-2]).
Try visualizing it by drawing a 2D array and naming each cell in terms of A[i][j].

Categories

Resources