I need the sum of the variables around 2,2 and then to print it out.
I have no idea on how to do this. Please do help!
This is my code so far:
import java.util.*;
import java.io.*;
public class MatrixSumming
{
private int[][] m = {{5,6},{7,8},{3,4}}; //load in the matrix values
public int sum( int r, int c )
{
return 0;
}
public String toString()
{
return "";
}
}
Here is my runner
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import static java.lang.System.*;
public class MatrixSummingRunner
{
public static void main( String args[] ) throws IOException
{
//Scanner file = new Scanner (new File("matsum.dat"));
int[][] mat = {{0, 0, 0, 0, 0, 0, 0},
{0, 1, 2, 3, 4, 5, 0},
{0, 6, 7, 8, 9, 0, 0},
{0, 6, 7, 1, 2, 5, 0},
{0, 6, 7, 8, 9, 0, 0},
{0, 5, 4, 3, 2, 1, 0},
{0, 0, 0, 0, 0, 0, 0}};
}
}
I tried finding but couldn't find anything similar to this in matrix.
Do a regular search for the required number and let the index vvalues be "curi" and "curj"
Use the following logic
Let maxi and maxj be the m and n for (mxn) matrix
sum = 0;
for(int i=curi-1;i<curi+3;i++){
for(int j=curj-1;j<curj+3;j++){
if(i>-1 && j>-1 && i<maxi && j<maxj){ // boundary conditions
if(i!=curi && j!=curj){
continue; // skip the current search key to add
}
sum += array[i][j];
}
}
}
You have this method public int sum( int r, int c ) where you pass in two ints.
These are the row and column index, and correspond to a position in the matrix. (Or you have to substract 1, if you take row 1 as the first row, because of the zero-indexed arrays in Java)
So if you have a matrix and the values r and c, you will be at position matrix[r][c] (or the other way round).
Imagine standing on a chess board. Now you have 8 fields around you, which you can reach by taking one step. (Or two, if you cannot move diagonally in one step). You might not have fields on one or more sides. You have to check this before computing a sum.
Now, taking a step means adding or substracting 1 to either r or c. Thus you get other indexes around the field you're standing at by addressing matrix[r-1][c] or matrix[r][c+1] etc. To move diagonally, you have to change both r and c (take two steps. e.g. first move one to the left, then one up. you moved to the field diagonally at the upper left of the original field)
You can then, using this knowledge, access the fields around the current field and sum them up.
This method will get all the surrounding cells values and sum them.
private static int neighboursSum(int[][] grid, int r, int c) {
int sum = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
// Make sure that we don't sum the Original Value, we only want it's neighbours
if (i == 0 && j == 0) {
continue;
} else {
int newX = r + i;
int newY = c + j;
// Make sure that the new Coordinates do not point outside the range of the Array
if (newX >= 0 && newX <= grid.length && newY >= 0 && newY <= grid.length) {
sum += grid[newX][newY];
}
}
}
}
return sum;
}
Related
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.
I am trying to search for a number in a particular column of a two dimensional array. I tried a few different approach and would like to use stream in Java 8. However, it doesn't seem to be the best performance. Wonder if someone can help?
boolean isInColumn(int col, int number) {
return IntStream.range(0, board.length)
.map(i -> board[i][col])
.filter(num -> num == number )
.findFirst()
.isPresent();
}
trying to search in a block as well. Any hints?
public boolean isInBlock(int row, int col, int number) {
int r = row - row % 3;
int c = col - col % 3;
for (int i = r; i < r + 3; i++) {
for (int j = c; j < c + 3; j++) {
if (board[i][j] == number)
return true;
}
}
return false;
}
the input data is the following array.
public static int[][] PUZZLE = {
{9,0,0,1,0,0,0,0,5},
{0,0,5,0,9,0,2,0,1},
{8,0,0,0,4,0,0,0,0},
{0,0,0,0,8,0,0,0,0},
{0,0,0,7,0,0,0,0,0},
{0,0,0,0,2,6,0,0,9},
{2,0,0,3,0,0,0,0,6},
{0,0,0,2,0,0,9,0,0},
{0,0,1,9,0,4,5,7,0},
};
This 'stream'-version seems a little bit optimzed, but I think searching for a hit in an array will always be faster the old fashioned way, see Java performance tutorial – How fast are the Java 8 streams?
boolean isInColumn(int col, int number) {
return IntStream.range(0, board.length)
.anyMatch(i -> (board[i][col] == number) );
}
I made a short attempt with a parallel stream, but the overhead made it far worse.
I think it would be different if the action wasn't a simple compare...
If it's only about speed for a Sudoku-solver/generator maybe you shouldn't loop at all but write the 9 conditions in one return statement
return board[0,col] == number || board[1,col] == number ...
Since this seems to be Sudoku what you could do is store the data redundantly. Don't only store the numbers in "normally" in a two dimensional array, but also have two-dimensional boolean arrays, where you store whether the row/column/block contains the number.
class Sudoku {
private final int[][] puzzle = new int[9][9];
private final boolean[][] rows = new boolean[9][9];
private final boolean[][] columns = new boolean[9][9];
private final boolean[][] blocks = new boolean[9][9];
public void setCell(int row, in column, int number) {
puzzle[row][column] = number;
rows[row][number - 1] = true;
columns[column][number - 1] = true;
blocks[calcBlockId(row, column)][number - 1] = true;
}
// returns a number (0 - 8) identifying a block
// 0 - 2 is first line, 3 - 5 second line, etc.
private int calcBlockId(int row, int column) {
// Left as an exercise to the reader
}
public boolean isInColumn(int col, int number) {
return columns[col][number - 1];
}
public boolean isInBlock(int row, int column, int number) {
return blocks[calcBlockId(row, column)][number - 1];
}
}
This code searches for an element in a 2d array and returns the coordinates of the first match, if such an element is present, or null otherwise:
public static int[] findElement(int[][] arr, int element) {
return IntStream
// iterate through the indexes
// of the rows of the array
.range(0, arr.length)
// for each row
.mapToObj(i -> {
// look for the element in this row
int j = IntStream
// iterate through the indexes
// of the elements of the row
.range(0, arr[i].length)
// filter a matching element
.filter(el -> arr[i][el] == element)
// take first match
.findFirst().orElse(-1);
// if element is present
if (j >= 0)
// return its coordinates
return new int[]{i, j};
else
// or null otherwise
return null;
})
// take first non-null coordinates, if they are present
.filter(Objects::nonNull).findFirst()
// or null otherwise
.orElse(null);
}
// test
public static void main(String[] args) {
int[][] puzzle = {
{9, 0, 0, 1, 0, 0, 0, 0, 5},
{0, 0, 5, 0, 9, 0, 2, 0, 1},
{8, 0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 6, 0, 0, 9},
{2, 0, 0, 3, 0, 0, 0, 0, 6},
{0, 0, 0, 2, 0, 0, 9, 0, 0},
{0, 0, 1, 9, 0, 4, 5, 7, 0}};
int[] coordinates = findElement(puzzle, 7);
System.out.println(Arrays.toString(coordinates)); // [4, 3]
}
See also:
• Difference between anyMatch and findAny in java 8
• First unique character in a string using LinkedHashMap
I have the following array:
int [] mi_array= {9,4,0,0,4,0,3,0,1,8,0};
I want to order the numbers other than 0 on the left, and the 0s on the right, but I find that the function steps on one of the numbers.
The output must be
{9,4,4,3,1,8,0,0,0,0,0}
public class Array {
public static void main(String[] args) {
int [] mi_array= {9,4,4,3,1,8,0,0,0,0,0};
int x=0;
int y=mi_array.length-1;
for (int i=0;i<mi_array.length;i++)
if(mi_array[i]!=0) {
mi_array[x]=mi_array[i];
x++;
}
else {
mi_array[y]=mi_array[i];
y--;
}
for (int i=0;i<mi_array.length;i++)
System.out.println(mi_array[i]);
System.out.println(x);
}
}
Try this.
int[] mi_array = {9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0};
for (int i = 0, j = i + 1, s = mi_array.length; j < s;)
if (mi_array[i] == 0) {
mi_array[i] = mi_array[j];
mi_array[j] = 0;
++j;
} else if (++i >= j)
j = i + 1;
System.out.println(Arrays.toString(mi_array));
// -> [9, 4, 4, 3, 1, 8, 0, 0, 0, 0, 0]
You can use filter and IntStream.concat to merge the parts of the array that are not 0 with the parts that are.
final int[] mi_array = { 9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0 };
final int[] result = IntStream.concat(Arrays.stream(mi_array).filter(i -> i != 0),
Arrays.stream(mi_array).filter(i -> i == 0)).toArray();
System.out.println(Arrays.toString(result));
Demo!
You can also do this:
final int[] mi_array = { 9, 4, 0, 0, 4, 0, 3, 0, 1, 8, 0 };
final int[] result = new int[mi_array.length];
final AtomicInteger idx = new AtomicInteger();
Arrays.stream(mi_array).filter(i -> i != 0).forEach(val -> result[idx.getAndIncrement()] = val);
System.out.println(Arrays.toString(result));
Your primary problem here is that you overwrite numbers you haven't already covered.
if (mi_array[i] != 0) {
mi_array[x] = mi_array[i];
x++;
}
x can never exceed i in this code; it starts at 0 just like i does, and increments at most by 1 every loop (and i increments by 1 every loop). So, no problem here; at 'worst' this is mi_array[i] = mi_array[i]; which does nothing.
however...
} else {
mi_array[y]=mi_array[i];
y--;
}
This is much more problematic. Given inputs {9,4,0,0,4,0,3,0,1,8,0};, when i is 2, then mi_array[i] is 0, thus this code runs. y is still 10, so this will end up running: mi_array[10] = 0;. The second 0 occurs when i is 3, and ends up running: mi_array[9] = 0;. And at that point, the 8 at index 9? You deleted it. It cannot be recovered.
The solution
The dumb solution is to make a copy of the array; edit the copy, refer to the original (which you won't change at all). You don't actually end up needing a copy; this code will write every number back, so just make a new array of the same size and write in that.
A slightly more elegant solution will not write 0s at all. Instead, it just writes the non-zeroes (as that code cannot overwrite anything, as shown before), and then at the end, overwrite the rest with zeroes. Now you don't need a copy.
O(n), two-pointer approach:
public static void shiftZeroesRight(int[] array) {
int notZeroPos;
for (int i = 0; i < array.length; i++) {
if (array[i] != 0)
continue;
notZeroPos = i + 1;
while (notZeroPos < array.length && array[notZeroPos] == 0)
++notZeroPos;
if (notZeroPos >= array.length)
break;
array[i] = array[notZeroPos];
array[notZeroPos] = 0;
}
}
Basically my code needs to calculate the sum of the path in an nxn matrix ( starts at 0,0), and adds up the smallest sum where I'm only allowed to move right or downwards.
For example the matrix below should output 18 because the min path is 5 1 2 4 6, but I don't know how should my base case be here. I know I should stop the recursion once I reach array [n][n] though..in my code below I'm getting a stackoverflow error.
512
234
566
import java.util.*;
public class shortestpath {
public static int findminpath(int [][]c,int x,int y,int n) {
if (x==n-1 && y==n-1) {
return c[x][y];
} else {
int path1 = findminpath(c,x+1,y,n);
int path2 = findminpath (c,x,y+1,n);
return c[x][y] + Math.min(path1,path2);
}
}
public static void main (String [] args) {
Scanner sc = new Scanner (System.in);
int[][] array = new int[3][3];
for (int i=0; i<array.length; i++){
for (int j=0; j<array.length; j++){
array[i][j] = sc.nextInt();
}
}
System.out.println(findminpath(array,0,0,array.length));
}
}
The issue comes from your if statement.
if (x==n-1 && y==n-1)
Note that if you trace through your code by hand, you will have the following method calls on your stack.
findminpath(array, 0, 0, 3)
findminpath(array, 1, 0, 3)
findminpath(array, 2, 0, 3)
findminpath(array, 3, 0, 3)
findminpath(array, 4, 0, 3)
findminpath(array, 5, 0, 3)
findminpath(array, 6, 0, 3)
findminpath(array, 7, 0, 3)
....
The reason is because of the && you have in the if statement. y hasn't incremented yet, and it will never increment from this recursion because you will go until x reaches the maximum int value.
I've been working in a little Java project but I can't figure out how to overwrite the elements of an array based on the values on another array.
Basically I have two arrays: repeated[] = {1,4,0,0,0,3,0,0} and hand[] = {1,2,2,2,2,6,6,6} and I use repeated[] to count the amount of times a number appears on hand[], and if it is between 3 and 7 it should overwrite the corresponding element in hand[] with a zero but I keep getting this output {1,0,0,2,2,6,0,6} when it should give me {1,0,0,0,0,0,0,0}. What am I doing wrong?
public static void main(String[] args) {
int repeated[] = {1,4,0,0,0,3,0,0};
int hand[] = {1,2,2,2,2,6,6,6};
for(int z=0;z<repeated.length;z++){
if(repeated[z]>=3 && repeated[z]<8){
for(int f:hand){
if(hand[f]==(z+1)){
hand[f]=0;
} } } }
for(int e:hand){
System.out.print(e+",");
}
}
First, the value in repeated is offset by one (because Java arrays start at index zero). Next, you need to test if the value is >= 3 (because 6 only appears 3 times). And, you could use Arrays.toString(int[]) to print your array. Something like,
public static void main(String[] args) {
int repeated[] = { 1, 4, 0, 0, 0, 3, 0, 0 };
int hand[] = { 1, 2, 2, 2, 2, 6, 6, 6 };
for (int z = 0; z < repeated.length; z++) {
if (repeated[hand[z] - 1] >= 3) {
hand[z] = 0;
}
}
System.out.println(Arrays.toString(hand));
}
Output is
[1, 0, 0, 0, 0, 0, 0, 0]