Adding blank rows to a 2d array in Java - java

Say I have the following 2d array in Java set to a variable named myMap:
1 3 1
3 2 3
1 3 1
The next step in my program is to add rows and columns of zeros as follows:
1 0 3 0 1
0 0 0 0 0
3 0 2 0 3
0 0 0 0 0
1 0 3 0 1
Basically, I'm adding arrays of zero into the spaces between the previous rows/columns. I then fill them in with appropriate numbers (irrelevant to my question) and repeat the process (adding more rows/columns of zeros) a finite number of times.
My question is as follows- what is the easiest and most efficient way to do this in Java? I know I could create a new 2d array and copy everything over, but I feel like there may be a more efficient way to do this. My intuition says that a 2d ArrayList may be the better way to go.
Also, and this my be important, when my program begins, I DO know what the maximum size this 2d array. Also, I cannot expect the symmetry of the numbers that I put in for this example (these were just put in for a good visual reference).

Here's a solution with ArrayLists: (test included)
int[][] ar = new int[][]
{
{ 0, 1, 2 },
{ 3, 4, 5 },
{ 6, 7, 8 } };
ArrayList<ArrayList<Integer>> a = new ArrayList<>(ar.length);
ArrayList<Integer> blankLine = new ArrayList<>(ar.length * 2 - 1);
for (int i = 0; i < ar.length * 2 - 1; i++)
{
blankLine.add(0);
}
for (int i = 0; i < ar.length; i++)
{
ArrayList<Integer> line = new ArrayList<>();
for (int j = 0; j < ar[i].length; j++)
{
line.add(ar[i][j]);
if (j != ar[i].length - 1)
line.add(0);
}
a.add(line);
if (i != ar.length - 1)
a.add(blankLine);
}
for (ArrayList<Integer> b : a)
{
System.out.println(b);
}
Output:
[0, 0, 1, 0, 2]
[0, 0, 0, 0, 0]
[3, 0, 4, 0, 5]
[0, 0, 0, 0, 0]
[6, 0, 7, 0, 8]

Algorithm
int[][] appendRows(int[][] bag, int[]... rows) {
int[][] extendedBag = new int[bag.length + rows.length][];
int i = 0;
for (int[] row : bag) { fillRow(extendedBag, row, i++); }
for (int[] row : rows) { fillRow(extendedBag, row, i++); }
return extendedBag;
}
// WHERE #fillRow(int[][], int[], int) =
void fillRow(int[][] bag, int[] row, int i) {
bag[i] = new int[row.length];
System.arraycopy(row, 0, bag[i++], 0, row.length);
}
Demo
import java.util.Arrays;
/** Utilities for 2D arrays. */
public class Array2dUtils {
public static void main(String[] args) {
int[][] bag = new int[][] {
{ 0 },
{ 1, 1 },
{ 2, 2, 2 }
};
int[] row1 = new int[] { 3, 3};
int[] row2 = new int[] { 4 };
int[][] biggerBag = appendRows(bag, row1, row2);
System.out.println("Bag:\n" + toString(bag));
System.out.println("Bigger Bag:\n" + toString(biggerBag));
}
/** Append one or more rows to a 2D array of integers. */
public static int[][] appendRows(int[][] bag, int[]... rows) {
int[][] extendedBag = new int[bag.length + rows.length][];
int i = 0;
for (int[] row : bag) { fillRow(extendedBag, row, i++); }
for (int[] row : rows) { fillRow(extendedBag, row, i++); }
return extendedBag;
}
/* fill i-th item of the bag */
private static void fillRow(int[][] bag, int[] row, int i) {
bag[i] = new int[row.length];
System.arraycopy(row, 0, bag[i++], 0, row.length);
}
/** Pretty-prints a 2D array of integers. */
public static String toString(int[][] bag) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bag.length; ++i) {
sb.append(Arrays.toString(bag[i])).append("\n");
}
return sb.toString();
}
}
$ javac Array2dUtils.java
$ java -cp "." Array2dUtils
Bag:
[0]
[1, 1]
[2, 2, 2]
Bigger Bag:
[0]
[1, 1]
[2, 2, 2]
[3, 3]
[4]

Related

How to shift everything in a 2D array to the left

I need to take a 2D array and move everything as far left as possible. It is a 4x4 array and I have tried to do it but either only move certain items or the index goes out of bounds.
The gameBoard array looks like this:
{0 2 4 2}
{0 0 2 0}
{2 2 0 0}
{0 4 0 2}
and after you call the swipeLeft() method it should look like this:
{2 4 2 0}
{2 0 0 0}
{2 2 0 0}
{4 2 0 0}
There is also the issue of placing a zero into the previous index that you moved it from.
I created a double for loop to just loop through the array and tried to code something that would move it over but it hasn't worked.
Here was the code I had so far
public void swipeLeft() {
for ( int r = 0; r < gameBoard.length; r++ ) {
for ( int c = 0; c < gameBoard[r].length; c++ ) {
gameBoard[r][c] = gameBoard[r][ (c+1) %
gameBoard.length];
}
}
}
Based on your desired OUTPUT, it looks like swipeLeft() is supposed to push all non-zero values to the very left of their row, displacing the zeroes to the right of all non-zero values.
If that's correct, this is similar to Old Dog Programmer's approach, except all shifting is done "in place" without creating any new arrays:
import java.util.*;
class Main {
private static int[][] gameBoard;
public static void main(String[] args) {
gameBoard = new int[][] {
{0, 2, 4, 2},
{0, 0, 2, 0},
{2, 2, 0, 0},
{0, 4, 0, 2}
};
System.out.println("Before:");
displayBoard();
swipeLeft();
System.out.println("\nAfter:");
displayBoard();
}
public static void displayBoard() {
for(int[] row : gameBoard) {
System.out.println(Arrays.toString(row));
}
}
public static void swipeLeft() {
for(int[] row : gameBoard) {
// find the first blank (zero) spot
int nextIndex = 0;
while(nextIndex < row.length && row[nextIndex] != 0) {
nextIndex++;
}
// start with the first blank, and shift any non-zero
// values afterwards to the left
for(int col=nextIndex; col < row.length; col++) {
if (row[col] != 0) {
row[nextIndex] = row[col];
row[col] = 0;
nextIndex++;
}
}
}
}
}
Output:
Before:
[0, 2, 4, 2]
[0, 0, 2, 0]
[2, 2, 0, 0]
[0, 4, 0, 2]
After:
[2, 4, 2, 0]
[2, 0, 0, 0]
[2, 2, 0, 0]
[4, 2, 0, 0]
From the example in the question, it appears to me that what is wanted is to shift all non-zero elements to the left, and zero elements are shifted to the right. The order of the non-zero elements is to be retained.
Note that each row is independent of other rows.
One way to approach this is to create a method that works on a 1D array. This method takes a 1D array as a parameter, and returns another 1D array with the elements shifted:
public static int [] zeroShift (int [] arr) {
int [] left = new int [arr.length];
int count = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] != 0) {
left [count++] = arr [i];
}
}
return left;
}
This copies each non-zero element to a new array of the same size, keeping track (count) of how many have been copied so far. Note this relies on left being initialized to all-zeros.
Once that method is working, it can be used for gameBoard on a row-by-row basis:
public void swipeLeft() {
for (int r = 0; r < gameBoard.length; r++) {
gameBoard [r] = zeroShift (gameBoard [r]);
}
// output for testing
for (int i = 0; i < gameBoard.length; ++i) {
System.out.println(Arrays.toString(gameBoard[i]));
}
}
To rotate the array in place, you should roteate the array 3 times:
123456 -> 654312
654321
3456..
....12
public static void shiftLeft(int[] arr, int offs) {
if (offs <= 0)
return;
offs = arr.length - offs % arr.length - 1;
for (int i = 0, j = arr.length - 1; i < j; i++, j--)
swap(arr, i, j);
for (int i = 0, j = offs; i < j; i++, j--)
swap(arr, i, j);
for (int i = offs + 1, j = arr.length - 1; i < j; i++, j--)
swap(arr, i, j);
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
So your code intends to rotate the board one column to the left. Rotate? Well, the numbers you push out on the left might come back on the end, right?
Probably the line
gameBoard[r][c] = gameBoard[r][ (c+1) % gameBoard.length];
should be
gameBoard[r][c] = gameBoard[r][ (c+1) % gameBoard[r].length];
But try to do this stuff with pen & paper, and you should notice that you are going to loose one column/copy the values from the second column into the first, then copy that into the last column again.
You will need to change two items:
store the value from the first column somewhere if you still need it so you can push it into the last one.
only rotate the column data if it needs to be rotated. Or in other words, rotate the remainder of the row if you find a zero. In this case you do not need to remember the first column, as you will overwrite a zero and push a zero into the last column. And then it would not be called rotate but shift.
Exercise this with pen & paper until you can write down instructions for someone else to perform the same operation. Then you are ready to also write it in Java.

How to merge two elements in an array together?

For example you have the 2d array Board as shown below:
{0, 2, 4, 2}
{0, 0, 2, 2}
{2, 2, 0, 0}
{0, 5, 0, 2}
You want it to become:
{0, 2, 4, 2}
{0, 0, 4, 0}
{4, 0, 0, 0}
{0, 5, 0, 2}
When there are 2 elements next to each other you need to merge them to make 4 into the left-most place out of those two elements and then make the 2nd element to be 0.
You want to do this with java.
forgot to show my existing loop, this is it below:
for (int row = 0; row < Board.length; row++){
for (int col = 0; col <= Board.length; col++){
if ((Board[row][col] == Board[row][col +1])){
Board[row][col] = 2 * Board[row][col];
Board[row][col + 1] = 0;
}
}
}
Well, I guess that should work. In the loop, you must be careful not to refer to the wrong ( or non-existing) array element.
public static void main(String[] args) {
int[][] arr = new int[][]{{0, 2, 4, 2}, {0, 0, 2, 2}, {2, 2, 0, 0}, {0, 5, 0, 2}, {2, 2, 2, 2}, {2, 2, 2, 0}};
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length - 1; j++) {
if (arr[i][j] == arr[i][j + 1]) {
arr[i][j] = arr[i][j] + arr[i][j + 1];
arr[i][j + 1] = 0;
}
}
}
System.out.println(Arrays.deepToString(arr));
}
Here is one way, focusing only array values that equal 2.
iterate the 2D array.
then iterate over each linear array, checking adjacent values and making the changes.
for(int[] arr : v) {
for(int i = 0; i < arr.length-1; i++) {
if (arr[i] == 2 && arr[i+1] == 2) {
arr[i]+= arr[i+1];
arr[i+1] = 0;
}
}
}
for(int arr[]: v) {
System.out.println(Arrays.toString(arr));
}
prints
[0, 2, 4, 2]
[0, 0, 4, 0]
[4, 0, 0, 0]
[0, 5, 0, 2]
Well I assume that Board variable holds array (quick tip, common convention is to name variable in camelCase (first letter lowercase, then each letter of next work upper, if that variable is constant, then convention is SNAKE_UPPER_CASE)
Your first for is pretty okay, the second one too but it assumes that matrix will be always NxN and will fail if thats not the case or it will not work properly (depending if amount of cols is lower or greater than length of array)
Inside it you dont want to check if the values are equal, you want to check if these values are both equal to 2. And you should check if thats not processing of last column of the row, in that case youll get IndexOutOfBoundException because you want to get value of matrix that is not present.
So with small changes, you will achieve what you want. This code will hopefuly shows my thoughts better
public class MergingTwos {
public static void main(String args[]) {
// Init a matrix
int[][] array = new int[][] { { 0, 2, 4, 2 }, { 0, 0, 2, 2 }, { 2, 2, 0, 0 }, { 2, 2, 0, 0 }, { 0, 5, 0, 2 }};
// Iterating over each row of matrix, in veriable i, the current X index is stored
for(int i = 0; i < array.length; i++) {
// Iterating over each column of row, in variable n, the current Y index is stored
for(int n = 0; n < array[i].length; n++) {
// To prevent index out of bound exception, last element of row wont be processed so as we dont want to proceed if given and next value on row are not 2
if(n == array[i].length -1 || array[i][n] != 2 || array[i][n+1] != 2) {
continue;
}
// To value at given coordinates [i,n] you add values of value on coordinates [i, n+1]
array[i][n] = array[i][n] + array[i][n+1];
// And setting next element to 0
array[i][n+1] = 0;
}
}
// Printing the result
for (int[] x : array) {
for (int y : x) {
System.out.print(y + " ");
}
System.out.println();
}
}
}

How to get output and get sum of columns in array / matrix?

hello to all you code geniuses on here
ill try to explain my problem as simply as i can
image1
To produce image1, lets say an array like below is required, keeping in mind that the numbers are placed left to right in the first row, then go backwards in the second row, and if you added more numbers, it would create a third row.
int[] something = {1, 2, 3, 2, 1, 2, 1, 3, 3, 1, 1, 2}
so i want to make to make a "map" of the layout, like this desired output below.
2 1 1 3 3 1
1 2 3 2 1 2
and then from there i would want to find the total for each column, so like this.
2 1 1 3 3 1
1 2 3 2 1 2
..................
3 3 4 5 4 3
(and i then want to make store this layout and sum within another array)
hopefully that all made sense, if so,
how could i go about doing this?
thanks heaps : )
Seems like you can use a two-dimensional array data structure to solve this:
int[][] something = new int[][]{
{2, 1, 1, 3, 3, 1},
{1, 2, 3, 2, 1, 2}
};
int totalForColomn1 = something[0][0] + something [1][0];
int totalForColomn2 = something[0][1] + something [1][1];
// ...
int totoalForColomn6 = something[0][5] + something [1][5];
If you could only use one-dimensional array:
int[] something = new int[] {2, 1, 1, 3, 3, 1, 4, 2, 3, 2, 1, 2};
int row_size = 6;
int totalForColomn1 = something[0] + something[0 + row_size];
int totalForColomn2 = something[1] + something[1 + row_size];
// ...
int totalForColomn6 = something[5] + something[5 + row_size];
Remember to keep a consistant row_size by putting those undecided element to 0.
In this case, you should init your array like:
int[] something = new int[] {0, 0, 0, 0, 1, 4, 1, 2, 3, 2, 1, 1};
So If I am reading this correctly if L is the length of your array you want to add the nth and L-1-nth element of the array and store the result in an array. I through this together quickly so I did not handle what happens if the input array is of odd length (your question did not specify).
import java.util.Arrays;
public class App {
public static void main(String[] args) {
int[] something = {1, 2, 3, 2, 1, 2, 1, 3, 3, 1, 1, 2};
System.out.println(Arrays.toString(addValues(something)));
}
public static int [] addValues(int [] input){
int[] output = new int[input.length / 2];
for(int i = 0; i<input.length/2; i++){
output[i] = input[i] + input[input.length -1 - i ];
}
return output;
}
}
EDIT:
I think this will work for the case where the are an arbitrary number of rows.
The main insite into how this work is in the grid below.
0 1 2 3 4 5 :row 0
11 10 9 8 7 6 :row 1
12 13 14 15 16 17:row 2
23 22 21 20 19 18:row 3
So whether the output index is going up or down is determined by the row number and every time we hit an input index that is the same size as our output array we need to stay at the same output index.
import java.util.Arrays;
public class App {
public static void main(String[] args) {
int[] something = { 1, 2, 3, 2, 1, 2, 1, 3, 3, 1, 1, 2 };
System.out.println(Arrays.toString(addValues(something, 6)));
}
public static int[] addValues(int[] input, int row_lenth) {
int[] output = new int[row_lenth];
int output_index = 0;
for (int i = 0; i < input.length; i++) {
if (i % row_lenth != 0) {
if ((i / row_lenth) % 2 == 0) {
output_index++;
} else {
output_index--;
}
}
output[output_index] += input[i];
}
return output;
}
}
import java.util.Scanner;
public class Stckoverq {
public static void main(String args[]) {
Scanner sn = new Scanner(System.in);
System.out.print("What is the size of array? ");
int size = sn.nextInt();
System.out.print("What is length of the row?");
int len = sn.nextInt();
int ind = 0, i = 0, j = 0;
//variable 'ind' is for getting the element from arr[] array at index ind
int rac[][] = new int[size/len][len];
//variable 'i' and 'j' is for storing rows and column elements respectively in array rac[]
int arr[] = new int[size];
System.out.println("Enter array elements: ");
for(int k=0;k<size;k++)
arr[k] = sn.nextInt();
while(ind!=arr.length)
{
if(j==len) {
j=0; //Reset column index
i++; //Increase row index
}
rac[i][j] = arr[ind];
ind++;
j++; //Increase column index
}
//Now print the rows and columns................
for(int r =0;r<size/len;r++) {
for(int c=0;c<len;c++)
System.out.print(rac[r][c]+"\t");
System.out.println();
}
int sum[] = new int[len];
//this array sum[] is used to store sum of all row elements.
int s = 0;
for(int c=0;c<len;c++) {
for(int r =0;r<size/len;r++)
s += rac[r][c];
sum[c] = s;
s = 0;
}
for(int x: sum)
System.out.print(x+"\t");
}
}

Generating Power Set of a String Recursively in Java

I'm trying to do recursive implementation of a Power Set generator working off of some pseudocode I was given, but when given a string like "abc", rather than having sets
{}, {a}, {b}, {c}, {a,b}, {a,c}, {b,c}, and {a,b,c},
I get {}, {0}, {1}, {2}, {0,1}, etc.
public static ArrayList GenerateSubsets(String setString) {
ArrayList A = new ArrayList<String>();
ArrayList temp = new ArrayList<String>();
if(setString.length() > 0) {
temp = GenerateSubsets(setString.substring(0,setString.length() - 1));
for(int i = 0; i < temp.size(); i++) {
System.out.println("Temp i: "+temp.get(i));
A.add(temp.get(i));
A.add(temp.get(i) + " " + (setString.length() - 1));
}
return A;
}
else
A.add("");
return A;
}
This is based directly on the pseudocode, why isn't it working correctly?
Edit: This is the test
public static void main(String[] args) {
ArrayList one = GenerateSubsets("abcd");
for(int i = 0; i < one.size(); i++) {
System.out.print(one.get(i)+ ", ");
if(i%5 == 0) {
System.out.println("");
}
}
}
And I get output of (without the line breaks)
,
3, 2, 2 3, 1, 1 3,
1 2, 1 2 3, 0, 0 3, 0 2,
0 2 3, 0 1, 0 1 3, 0 1 2, 0 1 2 3,
Statement (setString.length() - 1) gives you the index of char. And by concatenating it you receive a Power set of indexes. You need use setString.charAt(setString.length()-1) to receive char at given position.

how to reduce 2d array

I have a 2d array, let's say like this :
2 0 8 9
3 0 -1 20
13 12 17 18
1 2 3 4
2 0 7 9
How to create an array reduced by let's say 2nd row and third column?
2 0 9
13 12 18
1 2 4
2 0 9
Removing rows and columns in arrays are expensive operations because you need to shift things, but these methods do what you want:
static int[][] removeRow(int[][] data, int r) {
int[][] ret = new int[data.length - 1][];
System.arraycopy(data, 0, ret, 0, r);
System.arraycopy(data, r+1, ret, r, data.length - r - 1);
return ret;
}
static int[][] removeColumn(int[][] data, int c) {
for (int r = 0; r < data.length; r++) {
int[] row = new int[data[r].length - 1];
System.arraycopy(data[r], 0, row, 0, c);
System.arraycopy(data[r], c+1, row, c, data[r].length - c - 1);
data[r] = row;
}
return data;
}
You may want to investigate other data structures that allow for cheaper removals, though, i.e. doubly-linked lists. See, for example, Dancing Links.
public class TestMe {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int array[][] = {{2,0, 8, 9,},
{3, 0, -1, 20},
{13, 12, 17, 18},
{1, 2, 3, 4,},
{2, 0, 7, 9}};
for(int i=0; i<array.length;i++){
if(i == 1 ){
continue;
}
for(int j=0; j<array[i].length;j++){
if(j==2){
continue;
}
System.out.print(array[i][j]+" ");
}
System.out.println("");
}
}
}

Categories