Time Limit Exception on excercise about finding the largest area in matrix - java

https://judge.telerikacademy.com/problem/29largestareamatrix
That's the exercise.
Write a program that finds the largest area of equal neighbour elements in a rectangular matrix and prints its size.
Input
On the first line you will receive the numbers N and M separated by a single space
On the next N lines there will be M numbers separated with spaces - the elements of the matrix
Output
Print the size of the largest area of equal neighbour elements
Constraints
3 <= N, M <= 1024
Time limit: 0.5s for JAVA
Memory limit: 50MB
And this is my solution.
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static class Node {
private int rowIndex, colIndex;
Node(int rowIndex, int colIndex) {
this.rowIndex = rowIndex;
this.colIndex = colIndex;
}
Node[] getNeighbourNodes(int maxRowIndex, int maxColIndex) {
Node[] nodes = new Node[4];
int[][] indexesToCheck = {
{rowIndex - 1, colIndex},
{maxRowIndex - 1, colIndex},
{rowIndex + 1, colIndex},
{0, colIndex},
{rowIndex, colIndex - 1},
{rowIndex, maxColIndex - 1},
{rowIndex, colIndex + 1},
{rowIndex, 0}
};
for (int i = 0; i < indexesToCheck.length; i += 2) {
int rowIndex = indexesToCheck[i][0], backupRowIndex = indexesToCheck[i + 1][0];
int colIndex = indexesToCheck[i][1], backupColIndex = indexesToCheck[i + 1][1];
if (indexExists(rowIndex, colIndex, maxRowIndex, maxColIndex)) {
nodes[i / 2] = new Node(rowIndex, colIndex);
} else {
nodes[i / 2] = new Node(backupRowIndex, backupColIndex);
}
}
return nodes;
}
private boolean indexExists(int row, int col, int maxRowIndex, int maxColIndex) {
return row >= 0 && col >= 0 && row < maxRowIndex && col < maxColIndex;
}
}
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int n = keyboard.nextInt();
int m = keyboard.nextInt();
int[][] matrix = new int[n][m];
boolean[][] visitedElements = new boolean[n][m];
for (int row = 0; row < n; row++) {
for (int col = 0; col < m; col++) {
matrix[row][col] = keyboard.nextInt();
}
}
int maxCounter = 0;
for (int row = 0; row < n; row++) {
for (int col = 0; col < m; col++) {
if (!visitedElements[row][col]) {
maxCounter = Math.max(maxCounter, countAreaInMatrixDFS(row, col, matrix, visitedElements, n, m));
}
}
}
System.out.println(maxCounter);
}
private static int countAreaInMatrixDFS(int row, int col, int[][] matrix, boolean[][] visitedElements, int maxRowIndex, int maxColIndex) {
Stack<Node> stack = new Stack<>();
stack.push(new Node(row, col));
visitedElements[row][col] = true;
int counter = 1;
while (stack.size() > 0) {
Node currentNode = stack.pop();
row = currentNode.rowIndex;
col = currentNode.colIndex;
Node[] neighboursIndexes = currentNode.getNeighbourNodes(maxRowIndex, maxColIndex);
for (Node node : neighboursIndexes) {
if (!visitedElements[node.rowIndex][node.colIndex] && matrix[row][col] == matrix[node.rowIndex][node.colIndex]) {
stack.push(node);
visitedElements[node.rowIndex][node.colIndex] = true;
counter++;
}
}
}
return counter;
}
}
I tried without Node class and with BufferedReader and I still get Time limit exception.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Stack;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] firstLine = br.readLine().split(" ");
int n = Integer.parseInt(firstLine[0]);
int m = Integer.parseInt(firstLine[1]);
int[][] matrix = new int[n][m];
boolean[][] visitedElements = new boolean[n][m];
for (int row = 0; row < n; row++) {
String[] line = br.readLine().split("\\s");
matrix[row] = Arrays.stream(line).mapToInt(Integer::parseInt).toArray();
}
int maxCounter = 0;
for (int row = 0; row < n; row++) {
for (int col = 0; col < m; col++) {
if (!visitedElements[row][col]) {
maxCounter = Math.max(maxCounter, countAreaInMatrixDFS(row, col, matrix, visitedElements, n, m));
}
}
}
System.out.println(maxCounter);
}
private static int countAreaInMatrixDFS(int row, int col, int[][] matrix, boolean[][] checkedElements, int maxRowIndex, int maxColIndex) {
Stack<Integer[]> stack = new Stack<>();
stack.push(new Integer[]{row, col});
checkedElements[row][col] = true;
int counter = 1;
while (stack.size() > 0) {
Integer[] elementIndexes = stack.pop();
row = elementIndexes[0];
col = elementIndexes[1];
int[][] neighboursIndexes = getNeighbourNodes(row, col, maxRowIndex, maxColIndex);
for (int[] indexes : neighboursIndexes) {
int neighbourRow = indexes[0];
int neighbourCol = indexes[1];
if (!checkedElements[neighbourRow][neighbourCol] && matrix[row][col] == matrix[neighbourRow][neighbourCol]) {
stack.push(new Integer[]{neighbourRow, neighbourCol});
checkedElements[neighbourRow][neighbourCol] = true;
counter++;
}
}
}
return counter;
}
private static int[][] getNeighbourNodes(int rowIndex, int colIndex, int maxRowIndex, int maxColIndex) {
int[][] indexes = new int[4][];
if (indexExists(rowIndex - 1, colIndex, maxRowIndex, maxColIndex)) {
indexes[0] = new int[]{rowIndex - 1, colIndex};
} else {
indexes[0] = new int[]{maxRowIndex - 1, colIndex};
}
if (indexExists(rowIndex + 1, colIndex, maxRowIndex, maxColIndex)) {
indexes[1] = new int[]{rowIndex + 1, colIndex};
} else {
indexes[1] = new int[]{0, colIndex};
}
if (indexExists(rowIndex, colIndex - 1, maxRowIndex, maxColIndex)) {
indexes[2] = new int[]{rowIndex, colIndex - 1};
} else {
indexes[2] = new int[]{rowIndex, maxColIndex - 1};
}
if (indexExists(rowIndex, colIndex + 1, maxRowIndex, maxColIndex)) {
indexes[3] = new int[]{rowIndex, colIndex + 1};
} else {
indexes[3] = new int[]{rowIndex, 0};
}
return indexes;
}
private static boolean indexExists(int row, int col, int maxRowIndex, int maxColIndex) {
return row >= 0 && col >= 0 && row < maxRowIndex && col < maxColIndex;
}
}

In this code snippet,
if (!visitedElements[node.rowIndex][node.colIndex] && matrix[row][col] == matrix[node.rowIndex][node.colIndex]) {
visitedElements[row][col] = true;
counter++;
stack.push(node);
}
you are doing visitedElements[row][col] = true; which is actually making the current index itself true again. So, it's neighbours are never getting a chance to be true and adding each other all the time. Hence, it's a time limit exceeded(as your code looks accurate).
Change visitedElements[row][col] = true; to visitedElements[node.rowIndex][node.colIndex] = true;

Related

Given a matrix find all adjacent same elements

I have a 2D matrix, now I want to pick an element e and see all adjacent elements (i+1,j), (i-1,j) , (i,j+1), (i,j-1) and navigate if they are same as e and count how many are matching like that. Now find the maximum count that is possible.
example:
1 2 3 4
1 2 4 4
4 2 4 5
6 9 4 7
Output: 5.
as 4 is the element that repeats 5 times and all are adjacents, whereas 1 appears only 2 times and 2 appears only 3 times.
How to solve this program? I tried with BFS but got stuck on how to maintain the count here?
static class pair {
int first, second;
public pair(int first, int second) {
this.first = first;
this.second = second;
}
}
static int ROW = 4;
static int COL = 4;
// Direction vectors
static int dRow[] = { -1, 0, 1, 0 };
static int dCol[] = { 0, 1, 0, -1 };
// Function to check if a cell
// is be visited or not
static boolean isValid(boolean vis[][], int row, int col) {
// If cell lies out of bounds
if (row < 0 || col < 0 || row >= ROW || col >= COL)
return false;
// If cell is already visited
if (vis[row][col])
return false;
// Otherwise
return true;
}
static void BFS(int grid[][], boolean vis[][], int row, int col) {
// Stores indices of the matrix cells
Queue<pair> q = new LinkedList<>();
// Mark the starting cell as visited
// and push it into the queue
q.add(new pair(row, col));
vis[row][col] = true;
// Iterate while the queue
// is not empty
int max = 0;
while (!q.isEmpty()) {
pair cell = q.peek();
int x = cell.first;
int y = cell.second;
int v = grid[x][y];
System.out.print(grid[x][y] + " ");
// Go to the adjacent cells
for (int i = 0; i < 4; i++) {
int adjx = x + dRow[i];
int adjy = y + dCol[i];
if (isValid(vis, adjx, adjy)) {
if (grid[adjx][adjx] == v) {
q.add(new pair(adjx, adjy));
vis[adjx][adjy] = true;
}
}
}
}
public static void main(String[] args) {
// Given input matrix
int grid[][] = { .... };
ROW = grid.length;
COL = grid[0].length;
// Declare the visited array
boolean[][] vis = new boolean[ROW][COL];
BFS(grid, vis, 0, 0);
}
You need to iterate over the grid to identify the starting point of each BFS. Also, you need to initialize a new count at the start of each BFS and increment it each time you visit a neighboring cell. Then take the max of each such count.
static int max(int[][] grid)
{
int rows = grid.length;
int cols = grid[0].length;
Queue<Pos> q = new LinkedList<>();
boolean[][] visited = new boolean[rows][cols];
int max = 0;
for(int r=0; r<rows; r++)
{
for(int c=0; c<cols; c++)
{
if(!visited[r][c])
{
q.add(new Pos(r, c));
visited[r][c] = true;
int count = 0;
while(!q.isEmpty())
{
Pos p = q.poll();
count += 1;
for(int d=0; d<4; d++)
{
int i = p.r + dRow[d];
int j = p.c + dCol[d];
if(i >= 0 && i < rows && j >= 0 && j < cols && !visited[i][j] && grid[i][j] == grid[r][c])
{
q.add(new Pos(i, j));
visited[i][j] = true;
}
}
}
max = Math.max(max, count);
}
}
}
return max;
}
Test:
int[][] grid = {{1,2,3,4},
{1,2,4,4},
{4,2,4,5},
{6,9,4,7}};
System.out.printf("Max = %d%n", max(grid));
Output:
Max = 5
Bi Simple!
public static int findMaxAdjacentCount(int[][] grid) {
boolean[][] visited = createVisitGrid(grid);
int res = 0;
for (int row = 0; row < grid.length; row++)
for (int col = 0; col < grid[row].length; col++)
if (!visited[row][col])
res = Math.max(res, dfs(grid, visited, grid[row][col], row, col));
return res;
}
private static int dfs(int[][] grid, boolean[][] visited, int expected, int row, int col) {
if (row < 0 || row >= grid.length)
return 0;
if (col < 0 || col >= grid[row].length)
return 0;
if (visited[row][col] || grid[row][col] != expected)
return 0;
visited[row][col] = true;
int depth = 1;
depth += dfs(grid, visited, expected, row, col - 1);
depth += dfs(grid, visited, expected, row, col + 1);
depth += dfs(grid, visited, expected, row - 1, col);
depth += dfs(grid, visited, expected, row + 1, col);
return depth;
}
private static boolean[][] createVisitGrid(int[][] grid) {
boolean[][] visit = new boolean[grid.length][];
for (int row = 0; row < grid.length; row++)
visit[row] = new boolean[grid[row].length];
return visit;
}

Rotten Oranges LeetCode

I'm trying to solve this problem: https://leetcode.com/problems/rotting-oranges/
The link explains better than I can with the visuals, but basically you have to make every orange that's next to a "rotten" one (value 2) rotten as well.
I'm approaching this using a BFS. I start by making a queue for all the rotten oranges, then I pass that to my bfs function which checks if going (up/down/left/right) is possible and if it is then adds that to the queue and changes the value to show the node has already been visited.
My solution is not giving me the right answer and I'm not sure where the logical misstep is.
class Solution {
public int orangesRotting(int[][] grid) {
//get all 2's into a queue
//iterate over 2 making all oranges rotten
//iterate grid again --> anything that's not 2, return -1
//else return count
Queue<String> q = new LinkedList<>();
for(int i = 0; i < grid.length; i++) {
for(int j = 0; j < grid[i].length; j++) {
if(grid[i][j] == 2) {
q.add("" + i + j);
}
}
}
int count = getMinutes(grid, q);
for(int i = 0; i < grid.length; i++) {
for(int j = 0; j < grid[i].length; j++) {
if(grid[i][j] == 1) {
return -1;
}
}
}
return count;
}
public static int getMinutes(int[][] grid, Queue<String> q) {
Queue<String> rotten = new LinkedList<>();
int count = 0;
final int[][] SHIFTS = {
{1,0},
{-1,0},
{0,1},
{0,-1}
};
while(true) {
while(!q.isEmpty()) {
String s = q.remove();
int i = Integer.parseInt(s.substring(0, s.length() - 1));
int j = Integer.parseInt(s.substring(s.length() - 1));
for(int[] points : SHIFTS) {
int tempI = i + points[0];
int tempJ = j + points[1];
if(isValidMove(grid, tempI, tempJ)) {
rotten.add("" + tempI + tempJ);
grid[tempI][tempJ] = 2; //it's visited
}
}
}
if(rotten.isEmpty()) {
return count;
}
count++;
q = rotten;
}
}
public static boolean isValidMove(int[][] grid, int i, int j) {
if(i < 0 || i >= grid.length || j < 0 || j >= grid[i].length || grid[i][j] != 1) {
return false;
}
return true;
}
}
I suggest you don't do this : q.add("" + i + j); How would you distinguish between {11,2} and {1, 12}, both give the same string "112"? Just use q.add( new int[]{i, j} ) it shouldn't cause too much of a performance problem they are just ints. In fact its the other way around. It should be faster.
Now coming to the main issue, your algorithm is almost correct except for the fact that you need to initialize a new Queue inside while ( true ) because you have to start with a new queue every time you flush your current queue. The idea is you start with a queue of already rotten oranges. Rot their neighboring oranges and build a new queue consisting of the newly rotten oranges. Then repeat until your new queue of newly rotten oranges is empty. So it has to be a new queue everytime you start with already rotten oranges.
The modified getMinutes with the correction of the main issue is :
public static int getMinutes(int[][] grid, Queue<String> q) {
int count = 0;
final int[][] SHIFTS = {
{1,0},
{-1,0},
{0,1},
{0,-1}
};
while(true) {
Queue<String> rotten = new LinkedList<>();
while(!q.isEmpty()) {
String s = q.remove();
int i = Integer.parseInt(s.substring(0, s.length() - 1));
int j = Integer.parseInt(s.substring(s.length() - 1));
for(int[] points : SHIFTS) {
int tempI = i + points[0];
int tempJ = j + points[1];
if(isValidMove(grid, tempI, tempJ)) {
rotten.add("" + tempI + tempJ);
grid[tempI][tempJ] = 2; //it's visited
}
}
}
if(rotten.isEmpty()) {
return count;
}
count++;
q = rotten;
}
}
Looks pretty good!
My guess is that your solution is missing return 0 for if there is no freshOranges early.
This is similarly a Breadth First Search algorithm, crammed into one function though for laziness purposes ( ˆ_ˆ ):
public class Solution {
private static final int[][] directions = new int[][] {
{1, 0},
{ -1, 0},
{0, 1},
{0, -1}
};
public static final int orangesRotting(
int[][] grid
) {
final int rows = grid.length;
final int cols = rows > 0 ? grid[0].length : 0;
if (rows == 0 || cols == 0) {
return 0;
}
Queue<int[]> queue = new LinkedList<>();
int freshOranges = 0;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (grid[row][col] == 2) {
queue.offer(new int[] {row, col});
} else if (grid[row][col] == 1) {
freshOranges++;
}
}
}
if (freshOranges == 0) {
return 0;
}
int count = 0;
while (!queue.isEmpty()) {
count++;
final int size = queue.size();
for (int i = 0; i < size; i++) {
final int[] cell = queue.poll();
for (int[] direction : directions) {
final int row = cell[0] + direction[0];
final int col = cell[1] + direction[1];
if (
row < 0 ||
col < 0 ||
row >= rows ||
col >= cols ||
grid[row][col] == 0 ||
grid[row][col] == 2
) {
continue;
}
grid[row][col] = 2;
queue.offer(new int[] {row, col});
freshOranges--;
}
}
}
return freshOranges == 0 ? count - 1 : -1;
}
}

How to escape infinite loop in this recursive code?

I am implementing N-Queen problem solver with backjumping algorithm and I have caught infinite loop error in recursive call.
I have mainly caused trouble in returning function.I think I have error in designing recursive calls.
package Backjumping;
import org.python.google.common.primitives.Ints;
import java.util.*;
public class Backjumping {
int size;
List<Integer> columns;
int numberofplaces;
int numberofbacktracks;
HashMap<Integer, List<Integer>> conflict;
boolean noBreak = true;
Backjumping(int size) {
this.size = size;
columns = new ArrayList();
conflict = new HashMap<>(size);
for (int i = 0; i < size; i++) {
conflict.put(i, new ArrayList<>());
}
}
List place(int startRow) {
if (columns.size() == size) {
System.out.println("Solution Found! The board size was :" + size);
System.out.println(numberofplaces + " total nodes assigned were made.");
System.out.println(numberofbacktracks + " total backtracks were executed.");
return this.columns;
} else {
for (int row = 0; row < size; row++) {
if (isSafe(columns.size(), row)) {
if (indexExists(columns, columns.size()))
columns.set(columns.size(), row);
else
columns.add(columns.size(), row);
numberofplaces += 1;
return place(startRow);
}
}
if (noBreak) {
List<Integer> max_check = conflict.get(columns.size());
int lastRow = Collections.min(max_check);
numberofbacktracks += 1;
conflict.replace(columns.size(), new ArrayList<>());
int previous_variable = columns.remove(lastRow);
return place(previous_variable);
}
}
return this.columns;
}
private boolean isSafe(int cols, int rows) {
for (int threatrow : columns) {
int threatcol = columns.indexOf(threatrow);
if (rows == threatrow || cols == columns.indexOf(threatrow)) {
(conflict.get(cols)).add(threatcol);
return false;
} else if ((threatrow + threatcol) == (rows + cols) || (threatrow - threatcol) == (rows - cols)) {
(conflict.get(cols)).add(threatcol);
return false;
}
}
return true;
}
public boolean indexExists(final List list, final int index) {
return index >= 0 && index < list.size();
}
public static void main(String[] args) {
System.out.println("Enter the size of board");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Backjumping bj = new Backjumping(n);
double start = System.currentTimeMillis();
List cols = bj.place(0);
double end = System.currentTimeMillis();
System.out.println("Time to solve in second = " + (end - start) * 0.001 + " s");
System.out.print("Ths solution is : ");
cols.forEach(i -> System.out.print(((int) i + 1) + ", "));
System.out.println("\n\nPlotting CSP result on N_Queens board");
System.out.println("......................................\n");
bj.getBoardPic(n, cols);
}
public void getBoardPic(int size, List columns) {
int[] cols = Ints.toArray(columns);
int[][] matrix = new int[size][size];
for (int a = 0; a < size; a++) {
int j = cols[a];
matrix[a][j] = 1;
}
for (int a = 0; a < size; a++) {
for (int b = 0; b < size; b++) {
if (matrix[b][a] == 1)
System.out.print(" Q ");
else
System.out.print(" - ");
}
System.out.println();
}
}
}
The main errors are that when I assign row=0 in for (int row = 0; row < size; row++) the input size of n=6 goes wrong and other values are right.
When I assign row=startrow in for (int row = startrow; row < size; row++) the input size of n=6 goes right and other values are wrong.

Knight's Tour code runs into infinite loop, does not reach a solution

My Recursive Backtracking approach to Knight's Tour runs into an infinite loop. At first, I thought the problem might be taking this much time in general but some solutions do it in an instant. Please tell what is wrong with my code.
package io.github.thegeekybaniya.InterviewPrep.TopTopics.Backtracking;
import java.util.Arrays;
public class KnightsTour {
private static int counter=0;
public static void main(String[] args) {
knightsTour(8);
}
private static void knightsTour(int i) {
int[][] board = new int[i][i];
for (int[] arr :
board) {
Arrays.fill(arr, -1);
}
board[0][0] = 0;
knightsTour(board,0,1);
}
private static boolean knightsTour(int[][] board, int cellno, int stepno) {
if (stepno == board.length * board.length) {
printBoard(board);
return true;
}
int[][] dirs = {
{1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1}, {-2, 1}, {-2, -1}
};
int row = cellno / board.length, col = cellno % board.length;
for (int i = 0; i < dirs.length; i++) {
int r = dirs[i][0] + row;
int c = dirs[i][1] + col;
if (isSafe(board, r, c)&&board[r][c]==-1) {
int ncell = r * board.length + c;
board[r][c] = stepno;
if (knightsTour(board, ncell, stepno + 1)) {
return true;
} else {
board[r][c] = -1;
}
}
}
return false;
}
private static boolean isSafe(int[][] board, int r, int c) {
return r >= 0 && c >= 0 && r < board.length && c < board.length;
}
private static void printBoard(int[][] board) {
System.out.println(++counter);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
System.out.print(board[i][j]+" ");
}
System.out.println();
}
}
}
There's no bug in your code, it's just that the brute force approach is slow because the search space is enormous. You can speed up the search by implementing Warnsdorf's Rule. This is a heuristic for choosing the next move, where you always try the move that results in the fewest available moves for the next move after that. It can be done in a couple of simple loops:
int row = cellno / board.length, col = cellno % board.length;
// find move with fewest moves available for the next move:
int minMovesAvailable = 8;
int minMovesDir = 0;
for (int i = 0; i < dirs.length; i++) {
int r = dirs[i][0] + row;
int c = dirs[i][1] + col;
if (isSafe(board, r, c)&&board[r][c]==-1)
{
board[r][c] = stepno;
int movesAvailable = 0;
for (int j = 0; j < dirs.length; j++) {
int r2 = dirs[j][0] + r;
int c2 = dirs[j][1] + c;
if (isSafe(board, r2, c2)&&board[r2][c2]==-1)
{
movesAvailable++;
}
}
board[r][c] = -1;
if(movesAvailable < minMovesAvailable)
{
minMovesAvailable = movesAvailable;
minMovesDir = i;
}
}
}
// now recurse this move first:
// int r = dirs[minMovesDir][0] + row;
// int c = dirs[minMovesDir][1] + col;

Gaussian Elimination Java

I have this example matrix:
[4,1,3]
[2,1,3]
[4,-1,6]
and i want to solve exuotions:
4x1+1x2+3x3=v
2x1+1x2+2x3=v
4x1-1x2+6x3=v
x1+x2+x3=1
it will be: 4x1+1x2+3x3 = 2x1+1x2+2x3 = 4x1-1x2+6x3
-2x1+x2-5x3 =0
and I use the code:
import java.util.*;
public class GaussianElimination {
// This is the problem we solved in class
private static double[][] problem1 = {
// x = 1, y = 2, z = 3
{ 1, 2, 3, 14 }, // 1x + 2y + 3z = 14
{ 1, -1, 1, 2 }, // 1x - 1y + 1z = 2
{ 4, -2, 1, 3 } // 4x - 2y + 1z = 3
};
public static void solve(double[][] c, int row) {
int rows = c.length;
int cols = rows + 1;
// 1. set c[row][row] equal to 1
double factor = c[row][row];
for (int col=0; col<cols; col++)
c[row][col] /= factor;
// 2. set c[row][row2] equal to 0
for (int row2=0; row2<rows; row2++)
if (row2 != row) {
factor = -c[row2][row];
for (int col=0; col<cols; col++)
c[row2][col] += factor * c[row][col];
}
}
public static void solve(double[][] c) {
int rows = c.length;
for (int row=0; row<rows; row++)
solve(c,row);
}
public static void print(double[][] c) {
int rows = c.length;
int cols = rows + 1;
for (int row=0; row<rows; row++) {
for (int col=0; col<cols; col++)
System.out.printf("%5.1f ",c[row][col]);
System.out.println();
}
System.out.println();
}
public static void printSolution(double[][] c) {
int rows = c.length, cols = rows + 1;
char variable = (char)((rows > 3) ? ('z' - (rows-1)) : 'x');
System.out.println("Solution:\n");
for (int row=0; row<rows; row++)
System.out.printf(" %c = %1.1f\n",(char)variable++,c[row][cols-1]);
System.out.println();
}
public static void doProblem(double[][] problem, String description) {
System.out.printf("******* %s ********\n",description);
System.out.println("Original Equations:");
print(problem);
solve(problem);
System.out.println("Solved (reduced row echelon form):");
print(problem);
printSolution(problem);
}
public static void main(String[] args) {
doProblem(problem1,"Problem 1 (from class)");
}
}
How do I set the matrix in private static double[][] problem1 so that I get x1,x2,x3?
I don't really understand your question or problem. However I see some bugs in the row reduction echelon form solving method. I recently wrote this method as well. Mine works. Since I don't suspect this to be a Java homework assignment but rather an interest in programming mathematical algorithms, I will just throw in my code. I recommend taking a look at how the rref method is actually defined in the world of maths.
The bug I spotted is that the factor you use is wrong. Take a look at my code (note that it doesn't put zero rows to the bottom of the matrix):
public static double[][] rref(double[][] mat)
{
double[][] rref = new double[mat.length][mat[0].length];
/* Copy matrix */
for (int r = 0; r < rref.length; ++r)
{
for (int c = 0; c < rref[r].length; ++c)
{
rref[r][c] = mat[r][c];
}
}
for (int p = 0; p < rref.length; ++p)
{
/* Make this pivot 1 */
double pv = rref[p][p];
if (pv != 0)
{
double pvInv = 1.0 / pv;
for (int i = 0; i < rref[p].length; ++i)
{
rref[p][i] *= pvInv;
}
}
/* Make other rows zero */
for (int r = 0; r < rref.length; ++r)
{
if (r != p)
{
double f = rref[r][p];
for (int i = 0; i < rref[r].length; ++i)
{
rref[r][i] -= f * rref[p][i];
}
}
}
}
return rref;
}
The following code adapted from Rosettacode.org takes into account moving rows up/down as well:
static public void rref(double [][] m)
{
int lead = 0;
int rowCount = m.length;
int colCount = m[0].length;
int i;
boolean quit = false;
for(int row = 0; row < rowCount && !quit; row++)
{
print(m);
println();
if(colCount <= lead)
{
quit = true;
break;
}
i=row;
while(!quit && m[i][lead] == 0)
{
i++;
if(rowCount == i)
{
i=row;
lead++;
if(colCount == lead)
{
quit = true;
break;
}
}
}
if(!quit)
{
swapRows(m, i, row);
if(m[row][lead] != 0)
multiplyRow(m, row, 1.0f / m[row][lead]);
for(i = 0; i < rowCount; i++)
{
if(i != row)
subtractRows(m, m[i][lead], row, i);
}
}
}
}
// swaps two rows
static void swapRows(double [][] m, int row1, int row2)
{
double [] swap = new double[m[0].length];
for(int c1 = 0; c1 < m[0].length; c1++)
swap[c1] = m[row1][c1];
for(int c1 = 0; c1 < m[0].length; c1++)
{
m[row1][c1] = m[row2][c1];
m[row2][c1] = swap[c1];
}
}
static void multiplyRow(double [][] m, int row, double scalar)
{
for(int c1 = 0; c1 < m[0].length; c1++)
m[row][c1] *= scalar;
}
static void subtractRows(double [][] m, double scalar, int subtract_scalar_times_this_row, int from_this_row)
{
for(int c1 = 0; c1 < m[0].length; c1++)
m[from_this_row][c1] -= scalar * m[subtract_scalar_times_this_row][c1];
}
static public void print(double [][] matrix)
{
for(int c1 = 0; c1 < matrix.length; c1++)
{
System.out.print("[ ");
for(int c2 = 0; c2 < matrix[0].length-1; c2++)
System.out.print(matrix[c1][c2] + ", ");
System.out.println(matrix[c1][matrix[c1].length-1] + " ]");
}
}
static public void println()
{
System.out.println();
}

Categories