i have a matrix and I want to sum all content on the array from one point to another of the matrix, so in other words it might be that in row 1 i want to start to sum from col2 then sume row1 and row2 completely and then on row3 only until the position on number2
so leet me give you an example
class Lab {
public static void main(string[] args) {
int [][] scores = {{ 2, 8, 3, 2, 6 },
{ 3, 2, 8, 1, 0 },
{ 6, 9, 6, 3, 4 },
{ 5, 4, 2, 4, 5 }};
outputArray(scores);
}
public int sumRow(int[][] matrix, int row)
{
int sum = 0;
startrow = scores[1][]
lastrow =scores[3][]
startcol =scores[][2]
lastcol = scores[][2]
for(int i = startrow; i==lastrow;i++){
for (int j=startcol ; j==lastcol;j++) {
sum += scores[i][j];
return sum;
}
basically the sum of
row 1 -> 8, 1, 0
row 2 -> 6, 9, 6, 3, 4
row 3 -> 5, 4, 2
but done in one for loop (or any other method you think will be best to do so)
not sure if it can be done at once or if its needed to go row by row and then sum all the rows?
thanks!
The sales by month, in my opinion, greatly clarifies what you want to do.
To accomplish that, the sum method should have parameters to specify the row and column of the first cell, and row and column of the last cell to be summed.
You might try something like this:
public static int sumRange ( int matrix[][]
, int startRow, int startCol
, int endRow , int endCol ) {
int sum = 0;
int colIdx, rowIdx;
// add elements at end of first row
for (colIdx = startCol; colIdx < matrix [0].length; colIdx++) {
sum += matrix [startRow][colIdx];
}
// add elements of "in-between" rows, if any
for (rowIdx = startRow + 1; rowIdx < endRow; rowIdx++) {
for (colIdx = 0; colIdx < matrix [rowIdx].length; colIdx++) {
sum += matrix [rowIdx][colIdx];
}
}
// add elements at start of last row
for (colIdx = 0; colIdx <= endCol; colIdx++) {
sum += matrix [endRow][colIdx];
}
return sum;
}
The above uses 4 for loops, but is straightforward -- almost.
You could do it with a pair of nested for loops, but with an if that has several tests.
public static int sumRange ( int matrix[][]
, int startRow, int startCol
, int endRow , int endCol ) {
int sum = 0;
for (int rowIdx = startRow; rowIdx <= endRow; rowIdx++) {
for (int colIdx = 0; colIdx < matrix[rowIdx].length;colIdx++) {
if ( rowIdx == startRow && colIdx >= startCol
|| rowIdx == endRow && colIdx <= endCol
|| rowIdx > startRow && rowIdx < endRow ) {
sum += matrix [rowIdx][colIdx];
}
}
}
return sum;
}
Is it possible to do it with one for loop? It is.
public static int sumRange ( int matrix[][]
, int startRow, int startCol
, int endRow , int endCol ) {
int sum = 0;
int len = matrix[0].length;
for ( int idx = len * startRow + startCol ;
idx <= len * endRow + endCol ;
idx++ ) {
sum += matrix [idx / len] [idx % len];
}
return sum;
}
There are preconditons:
All rows in matrix have the same length.
The values for startRow, endRow, startCol, endCol are valid when used as row and column indices for the matrix parameter.
In the first two examples, startRow < endRow.
In the third example, startRow <= endRow . If startRow == endRow, then startCol < endCol.
Note the 2nd precondition implies the first two examples won't work when startRow == endRow. To fix the bug, precede the first for loop with an if statement to check for that, a for loop to sum the proper columns, and a return statement.
Because, in your example, the matrix was included as a parameter, and there was no use of instance variables, I made the methods static in these examples. If the matrix the method is supposed to use is an instance variable, remove int matrix [][] from the parameter list, and remove static from the method header.
Related
I've just learned an algorithm called DFS and when I watched the videos, the most popular practice or example to use DFS is the Connected Cells or find islands one which is a 2D array with 0 and 1. But I really wish to know if I want the island shape only to be rectangular(or square), what should I do or how can I change the if or for loop in the program. Here's the code I'm looking at:
// No. of rows and columns
static final int ROW = 3, COL = 5;
// A function to check if a given cell (row, col) can
// be included in DFS
boolean isSafe(int M[][], int row, int col,
boolean visited[][])
{
// row number is in range, column number is in range
// and value is 1 and not yet visited
return (row >= 0) && (row < ROW) && (col >= 0) && (col < COL) && (M[row][col] == 1 && !visited[row][col]);
}
// A utility function to do DFS for a 2D boolean matrix.
// It only considers the 8 neighbors as adjacent vertices
void DFS(int M[][], int row, int col, boolean visited[][])
{
// These arrays are used to get row and column numbers
// of 8 neighbors of a given cell
int rowNbr[] = new int[] { -1, -1, -1, 0, 0, 1, 1, 1 };
int colNbr[] = new int[] { -1, 0, 1, -1, 1, -1, 0, 1 };
// Mark this cell as visited
visited[row][col] = true;
// Recur for all connected neighbours
for (int k = 0; k < 8; ++k)
if (isSafe(M, row + rowNbr[k], col + colNbr[k], visited))
DFS(M, row + rowNbr[k], col + colNbr[k], visited);
}
// The main function that returns count of islands in a given
// boolean 2D matrix
int countIslands(int M[][])
{
boolean visited[][] = new boolean[ROW][COL];
int count = 0;
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
if (M[i][j] >= 100 && !visited[i][j])
{
DFS(M, i, j, visited);
++count;
}
return count;
}
I am trying to store all of the values in the matrix from the top right to the bottom left and store them in an array.
int matrixSample [][] = {
{6,4,1,4},
{7,5,4,4},
{4,4,8,3},
{4,4,8,3}
};
The output should be
[4,1,4,4,4,3,6,5,8,3,7,4,8,4,4,4]
I can get the bottom right diagonal
static int[] getAllDiagonalsInMatrix(int matrix[][]){
// Sum of arithmetic progression
int diagonal[] = new int[matrix.length * (matrix.length + 1)*2];
int index = 0;
for(int row = 0; row < matrix.length; row++) {
for(int col = 0; col < matrix[row].length - row; col++) {
diagonal[index++] = matrix[row + col][col];
}
}
return diagonal;
}
Is this even possible to do using the same two loops by adjustments made in the loops above?
Okay, here is my thought process on your problem. However, I'm going to print values instead of collecting them to make it a little easier on me and keep the solution easy to read.
First, how do you get a diagonal? We need to do this frequently so lets start by making a function for that. Maybe we could pass in the top left corner of the diagonal and go from there.
public void getDiagonal(int[][] array, int row, int col) {
// While row and col are within the bounds of the array
while (row < array.length && col < array[row].length) {
// Print element in diagonal
System.out.println(array[row][col]);
// Diagonal moves from top-left to bottom-right
row++;
col++;
}
}
Now that we have a function to get a diagonal, we just need a way to call it. Essentially, we just need to follow an L shape going from the top-right to the top-left to the bottom-left.
// Get diagonals starting in the first row with a column > 0
for (int col = array.length - 1; col > 0; col--) {
getDiagonal(array, 0, col);
}
// Get all diagonals starting from the left most column
for (int row = 0; row < array.length; row++) {
getDiagonal(array, row, 0);
}
Now that we have a working way to iterate through the values, we can rewrite it to save the values into an array instead. You could also choose to remove the function entirely now that you have a process.
Edit: I almost forgot, but the mathematical solution you were looking for is as follows.
for (int row = 0; row < array.length; row++) {
for (int col = 0; col < array.length; col++) {
// Index along diagonal
int diagonal = Math.min(row, col);
// Which part of L contains value
if (col >= row) {
int start = array.length - 1 - (col - row);
int passed = start * (start + 1) / 2;
solution[passed + diagonal] = array[row][col];
} else {
int start = array.length - 1 - (row - col);
int passed = array.length * array.length - 1 - start * (start + 1) / 2; solution[passed - array.length + 1 + row] = array[row][col];
}
}
}
One solution is to iterate through a matrix where you consider positions outside of the matrix, but exclude every index out of bounds.
static int[] getDiagonals(int[][] mat) {
int diagonal[] = new int[mat.length * (mat[0].length)];
int index = 0;
int yStart = -mat[0].length;
for (int y = yStart; y < mat.length; y++) {
for (int x = 0; x < mat[0].length; x++) {
if (y + x >= 0 && y + x < mat.length) {
diagonal[index++] = mat[y+x][x];
}
}
}
return diagonal;
}
Might not be optimal as you are effectively traversing a matrix nearly twice the size, but it is pretty intuitive.
Problem
You are given a two-dimensional array (matrix) of potentially unequal height and width containing only 0s and 1s. Each 0 represents land, and each 1 represents part of a river. A river consists of any number of 1s that are either horizontally or vertically adjacent (but not diagonally adjacent). The number of adjacent 1s forming a river determine its size. Write a function that returns an array of the sizes of all rivers represented in the input matrix. Note that these sizes do not need to be in any particular order.
Input
[
[1,0,0,1,0],
[1,0,1,0,0],
[0,0,1,0,1],
[1,0,1,0,1],
[1,0,1,1,0],
]
Output [1,2,2,2,5]
My Approach
After evaluating the problem i felt like this should be done using a graph traversal like algorithm maybe depth first search. So that is exactly what i do .
I traverse the matrix from top left and see if the value is visited and if it is not then and if the value is 1 then i traverse all it's nodes and keep a counter to keep size of the river. In the end i update an array list with the total river size.
For some reason my result is not correct and i am not sure what i did wrong. I hand traced my code too but can't figure out the issue.
My Code
import java.util.ArrayList;
class Program {
public static ArrayList<Integer> riverSizes(int[][] matrix) {
ArrayList<Integer> result = new ArrayList<Integer>();
boolean [][] visitStatus = new boolean [matrix.length][matrix[0].length];
for(int row = 0; row<matrix.length; row++){
for(int col = 0; col<matrix.length; col++){
int count = 0;
count = traverseMatrix(row,col,matrix,visitStatus,count);
result.add(count);
}
}
return result;
}
public static int traverseMatrix(int row, int col, int [][] matrix, boolean [][] visitStatus, int count){
if(visitStatus[row][col] == true){
return count;
}else if(matrix[row][col] == 0){
visitStatus[row][col] = true;
return count;
}else{
count++;
visitStatus[row][col] = true;
if(isValid(row,col-1,matrix)){
return traverseMatrix(row,col-1,matrix,visitStatus,count);
}
if(isValid(row,col+1,matrix)){
return traverseMatrix(row,col+1,matrix,visitStatus,count);
}
if(isValid(row-1,col,matrix)){
return traverseMatrix(row-1,col,matrix,visitStatus,count);
}
if(isValid(row+1,col,matrix)){
return traverseMatrix(row+1,col,matrix,visitStatus,count);
}
}
return count;
}
public static boolean isValid(int row, int col,int[][] matrix){
return (row >= 0 && row < matrix.length) && (col >= 0 && col < matrix[0].length);
}
}
you are given a two-dimensional array (matrix) of potentially unequal height and widthÂ
But you are doing the operation for always same size of matrix both in height and width
for(int row = 0; row<matrix.length; row++){
for(int col = 0; col<matrix.length; col++){ .. }}
you should use the dimension like following way, rest of the things are enough well I guess
..
for(int row = 0; row<matrix.length; row++){
for(int col = 0; col<matrix[row].length; col++){ .. }}
and the changes need to apply in function 'isValid' also
public static boolean isValid(int row, int col,int[][] matrix){
return (row >= 0 && row < matrix.length) && (col >= 0 && col < matrix[row].length);
}
Convert count to a local variable and accumulate it:
static int traverseMatrix(int row, int col, int[][] matrix, boolean[][] visitStatus) {
if (visitStatus[row][col] || matrix[row][col] == 0) {
return 0;
}
visitStatus[row][col] = true;
int count = 1;
if (isValid(row, col - 1, matrix)) {
count += traverseMatrix(row, col - 1, matrix, visitStatus);
}
...
return count;
}
In addition to #OleksandrPyrohov's answer, also check if the current cell is visited already before calling traverseMatrix :
public static ArrayList<Integer> riverSizes(int[][] matrix) {
ArrayList<Integer> result = new ArrayList<Integer>();
boolean [][] visitStatus = new boolean [matrix.length][matrix[0].length];
for(int row = 0; row<matrix.length; row++){
for(int col = 0; col<matrix.length; col++){
if ( !visitStatus[row][col] ) {
int count = 0;
count = traverseMatrix(row,col,matrix,visitStatus,count);
result.add(count);
}
}
}
return result;
}
My solution is written in C#, but it's similar to Java:
You can replace List with ArrayList
Code:
public static List<int> RiverSizes(int[,] matrix)
{
var sizes = new List<int>();
bool[,] visited = new bool[matrix.GetLength(0), matrix.GetLength(1)];
for (int row = 0; row < matrix.GetLength(0); row++)
for (int col = 0; col < matrix.GetLength(1); col++)
if (visited[row, col])
continue;
else
Traverse(matrix, row, col, visited, sizes);
return sizes;
}
public static void Traverse(int[,] matrix, int row, int col, bool[,] visited, List<int> sizes)
{
int currentSize = 0;
var toExplore = new List<int[]>
{
new int[] { row, col }
};
while (toExplore.Count > 0)
{
var current = toExplore[^1];
toExplore.RemoveAt(toExplore.Count - 1);
row = current[0];
col = current[1];
if (visited[row, col])
continue;
visited[row, col] = true;
if (matrix[row, col] == 0)
continue;
currentSize++;
foreach (int[] item in GetNeighbours(matrix, row, col, visited))
toExplore.Add(item);
}
if (currentSize > 0)
sizes.Add(currentSize);
}
public static List<int[]> GetNeighbours(int[,] matrix, int row, int col, bool[,] visited)
{
List<int[]> neighbours = new List<int[]>();
if (row > 0 && !visited[row - 1, col])
neighbours.Add(new int[] { row - 1, col });
if (row < matrix.GetLength(0) - 1 && !visited[row + 1, col])
neighbours.Add(new int[] { row + 1, col });
if (col > 0 && !visited[row, col - 1])
neighbours.Add(new int[] { row, col - 1 });
if (col < matrix.GetLength(1) - 1 && !visited[row, col + 1])
neighbours.Add(new int[] { row, col + 1 });
return neighbours;
}
I hope it helps ^-^
Given code that included everything to build a maze, I was to write the makeMove method to solve the maze, which I have completed and is working fine. However everything is done to use 2-D array with the maze and visited, I need to edit this to be used with 1-d array for maze and visited.
public abstract class AbstractMaze {
protected int startRow; // starting row
protected int startCol; // starting column
protected int endRow; // ending row
protected int endCol; // ending column
/**
* Declare the maze, 1's are walls and 0's are open
*/
protected int[][] maze;
protected AbstractMaze(int[][] maze, int startRow, int startCol, int endRow, int endCol) {
super();
this.maze = maze;
this.startRow = startRow;
this.startCol = startCol;
this.endRow = endRow;
this.endCol = endCol;
}
public void solve() {
makeMove( startRow, startCol )
}
protected abstract void makeMove( int row, int col );
}
public class Maze2 extends AbstractMaze
{
public Maze2(int[][] maze, int startRow, int startCol, int endRow, int endCol) {
super(maze, startRow, startCol, endRow, endCol);
}
int MAX_ROWS = endRow + 1;
int MAX_COLS = endCol + 1;
boolean[][]visited = new boolean[MAX_ROWS][MAX_COLS];
protected void makeMove( int row, int col )
{
boolean found = false;
if (row < 0 || row >= MAX_ROWS || col < 0 || col >= MAX_COLS || visited[row][col] || maze[row][col] == 1)
return;
visited[row][col] = true;
found = row == endRow && col == endCol;
if (!found) {
makeMove(row, col - 1);
makeMove(row, col + 1);
makeMove(row - 1, col);
makeMove(row + 1, col);
}
Do I need to change every place where maze[][] is and visited[][]? What is the simplest way to go about this?
Thanks for any and all help!
I assume that you want to change the given 2D maze array into a 1D maze class member. Declare the maze member as
int ROWS = maze.length;
int COLS = maze[0].length;
this.maze = new int[ROWS * COLS];
You can index this array as maze[COLS * row + col]. You'll then need to copy the elements over:
for (int r = 0; r < ROWS; r++)
for (int c = 0; c < COLS; c++)
this.maze[COLS * r + c] = maze[r][c];
As you can see, accessing an element is accomplished via this.maze[COLS * r + c] instead of this.maze[r][c]. You can think of it as taking the 2D array and joining the rows together to form a long 1D array.
Similarly, the visited array can be declared as visited[MAX_COLS * MAX_ROWS] and indexed via visited[MAX_COLS * row + col].
I am new to OpenGL as learning exercise I decided to draw a set of horizontal lines from a grid of m x n matrix containing the vertices locations
This is what I have
and If I use LINE_STRIP
A code snippet using vertex arrays and indices will be great, I cant seem to be able to get the concept just from a text book I need to see and play with a code example
Any help will be much appreciated!
#Thomas
Got it working with the following code
totalPoints = GRID_ROWS * 2 * (GRID_COLUMNS - 1);
indices = new int[totalPoints];
points = new GLModel(this, totalPoints, LINES, GLModel.DYNAMIC);
int n = 0;
points.beginUpdateVertices();
for ( int row = 0; row < GRID_ROWS; row++ ) {
for ( int col = 0; col < GRID_COLUMNS - 1; col++ ) {
int rowoffset = row * GRID_COLUMNS;
int n0 = rowoffset + col;
int n1 = rowoffset + col + 1;
points.updateVertex( n, pointsPos[n0].x, pointsPos[n0].y, pointsPos[n0].z );
indices[n] = n0;
n++;
points.updateVertex( n, pointsPos[n1].x, pointsPos[n1].y, pointsPos[n1].z );
indices[n] = n1;
n++;
}
}
points.endUpdateVertices();
Then I update and draw by doing
points.beginUpdateVertices();
for ( int n = 0; n < totalPoints; n++ ) {
points.updateVertex( n, pointsPos[indices[n]].x, pointsPos[indices[n]].y, pointsPos[indices[n]].z );
}
points.endUpdateVertices();
This is the result
Fix it by changing the nested for loop
for ( int col = 0; col < GRID_COLUMNS; col++ ) {
for ( int row = 0; row < GRID_ROWS - 1; row++ ) {
int offset = col * GRID_ROWS;
int n0 = offset + row;
int n1 = offset + row + 1;
indices[n++] = n0;
indices[n++] = n1;
}
}
Now I can have any number of rows and columns
Thanks agin!
You need to draw a line for each segment and resuse an index, i.e. for the first part you'd draw a line for (0,1), (1,2), (2,3) and so on.
Edit:
Suppose you have a 4x5 array (4 lines, 5 vertices per line). You could then calculate the indices like this (pseudo code):
Vertex[] v = new Vertex[20]; // 20 vertices in the grid
for(int row = 0; row < numrows; row++) // numrows = 4
{
int rowoffset = row * numcols ; //0, 4, 8, 12
for(int col = 0; col < (numcols - 1); col++) //numcols = 5
{
addLineIndices(rowoffset + col, rowoffset + col +1); //adds (0,1), (1,2), (2,3) and (3, 4) for the first row
}
}
Then issue the draw call for numrows * (numcols - 1) linesegments (GL_LINES), i.e. 16 in the example. Note that addLineIndices would be a function that adds the index pair for one line segment to an index array which is then supplied to the draw call.