Game of Life, java objects - java

On my program for java programming is not running right. My professor had us download a console.java to help use make a console to display our outputs of the program. I think the program is getting stuck when I am calling the update method and checkCells. My professor said that calling matrix.length for both rows and columns is incorrect but I'm stumped on how to call columns if I am not using matrix.length.
Any input is appreciated
import java.util.*;
public class Life {
private int birthLow = 0;
private int birthHigh = 0;
private int liveLow = 0;
private int liveHigh = 0;
private boolean[][] matrix;
public Life(long seed, int rows, int cols, int birthLow2, int birthHigh2, int liveLow2, int liveHigh2) {
boolean initalMatrix[][] = new boolean[rows][cols];
seedArray(initalMatrix, rows, cols, seed);
birthLow = birthLow2;
birthHigh = birthHigh2;
liveLow = liveLow2;
liveHigh = liveHigh2;
matrix = initalMatrix;
if ((rows < 1) && (cols < 1)) {
throw new IllegalArgumentException("Rows must be positive, not " + rows);
}
if ((rows > 9) && (cols < 9)) {
throw new IllegalArgumentException("Rows and cols cant go over 9, not " + rows + cols);
}
if (birthLow < 1 || (birthHigh > 9) || (liveLow < 1) || (liveHigh > 9)) {
throw new IllegalArgumentException("birth rates can not be below 1 or above 9 " + birthLow + birthHigh);
}
}
public boolean[][] world() {
boolean[][] matrixClone = matrix.clone();
for (int row = 0; row < matrix.length; row++) {
matrixClone[row] = matrix[row].clone();
}
return matrixClone;
}
public void update() {
matrix = checkCells(matrix, matrix.length, matrix.length, birthLow, birthHigh, liveLow, liveHigh);
}
public static void seedArray(boolean[][] matrix, int rows, int cols, long seed) {
// generates a random seed to fill the matrix
Random s = new Random(seed);
for (int r = 1; r < rows - 1; r++) {
for (int c = 1; c < cols - 1; c++) {
boolean x = s.nextBoolean();
matrix[r][c] = x;
}
}
}
public static void printBoard(boolean[][] matrix, int rows, int cols) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (matrix[r][c] == false && c == 0) {
System.out.print("- ");
} else if (matrix[r][c] == false && c > 0) {
System.out.print("- ");
} else if (matrix[r][c] == true) {
System.out.print("# ");
}
}
System.out.println();
}
System.out.println();
}
public static boolean[][] checkCells(boolean[][] matrix, int rows, int cols, int birthLow, int birthHigh,
int liveLow, int liveHigh) {
// clones matrix board
boolean[][] matrixClone = matrix.clone();
for (int row = 0; row < matrix.length; row++) {
matrixClone[row] = matrix[row].clone();
}
// determines if the living cell is going to live or die
for (int r = 1; r < rows; r++) {
for (int c = 1; c < cols; c++) {
if (neighbors(matrixClone, r, c) < liveLow || neighbors(matrixClone, r, c) > liveHigh || c == 0
|| r == 0 || c == cols - 1 || r == rows - 1) {
matrix[r][c] = false;
} else if (neighbors(matrixClone, r, c) >= birthLow && neighbors(matrixClone, r, c) <= birthHigh) {
matrix[r][c] = true;
}
}
}
return matrixClone;
}
public static int neighbors(boolean[][] matrixClone, int r, int c) {
int neighbors = 0;
// checks all neighbors for life or death
for (int rn = (r - 1); rn <= (r + 1); rn++) {
for (int cn = (c - 1); cn <= (c + 1); cn++) {
try {
if (matrixClone[rn][cn] == true) {
neighbors++;
}
// catches the array if it checks out the perimeter
} catch (ArrayIndexOutOfBoundsException f) {
continue;
}
}
}
return neighbors;
}
}

Don't use matrix.length for columns. You already know that. The reason is that it gives you the number of rows. Instead, just save the values of row and col and use them.
One way to do that is to make them fields, and initialize them in your constructor.

Do not initialize a random boolean[][] called initialMatrix. Instead, initialize the boolean[][] matrix that you have in the fields up above (matrix = new boolean[rows][cols]). Then for seedArray, call seedArray(matrix, rows, cols, seed).
Finally, in the update() method, do not use matrix.length, but rather rows and cols.

Related

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;
}
}

Minimum time required to rot all oranges

Given a matrix of dimension r*c where each cell in the matrix can have values 0, 1 or 2 which has the following meaning:
0 : Empty cell
1 : Cells have fresh oranges
2 : Cells have rotten oranges
So, we have to determine what is the minimum time required to rot all oranges. A rotten orange at index [i,j] can rot other fresh orange at indexes [i-1,j], [i+1,j], [i,j-1], [i,j+1] (up, down, left and right) in unit time. If it is impossible to rot every orange then simply return -1.
Input:
The first line of input contains an integer T denoting the number of test cases. Each test case contains two integers r and c, where r is the number of rows and c is the number of columns in the array a[]. Next line contains space separated r*c elements each in the array a[].
Here is the Code I have written
class GFG {
public static boolean isSafe(int[][] M, boolean[][] visited, int i, int j) {
int R = M.length;
int C = M[0].length;
return (i >= 0 && i < R && j >= 0 && j < C && (!visited[i][j]) && M[i][j] != 0);
}
public static int findMinDist(int[][] M, boolean[][] visited, int i, int j, int dist) {
if (M[i][j] == 2)
return dist;
int[] x_pos = { 1, -1, 0, 0 };
int[] y_pos = { 0, 0, -1, 1 };
visited[i][j] = true;
int min = Integer.MAX_VALUE;
for (int k = 0; k < 4; k++) {
if (isSafe(M, visited, i + x_pos[k], j + y_pos[k]))
min = Math.min(min, findMinDist(M, visited, i + x_pos[k], j + y_pos[k], dist + 1));
}
return min;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
for (int t = 0; t < T; t++) {
int R = sc.nextInt();
int C = sc.nextInt();
int[][] M = new int[R][C];
boolean[][] visited = new boolean[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
M[i][j] = sc.nextInt();
}
}
int[][] time = new int[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (M[i][j] == 1)
time[i][j] = findMinDist(M, new boolean[R][C], i, j, 0);
}
}
int maxTime = Integer.MIN_VALUE;
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
maxTime = Math.max(time[i][j], maxTime);
}
}
System.out.println(maxTime == Integer.MAX_VALUE ? -1 : maxTime);
}
}
}
I am trying to find minimum distance of 2 from each 1.
It is not working for test case
Input:
1
2 5
1 1 1 1 1 0 2 1 1 1
Its Correct output is:
4
And My Code's output is:
6
Please suggest what's wrong with the code.
Start by creating a matrix to store the times the oranges rot. You can initialize all slots with -1. You will use BFS but you won't need a "marked" matrix, because the times the oranges rot will already be enough to tell you if a slot has been visited or not.
Iterate through the original matrix. When you find a value 2, do a BFS starting there to rot the fresh oranges. This BFS should also state the time when each orange is rot and you must always keep the smallest time. If the orange being looked at the moment was already rotten at time t1 and you've just got there in time t2, where t2 < t1, pretend this orange is fresh and put it into the BFS queue like so.
After finishing it, iterate through the matrix of times and return the biggest value found.
class Pair {
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
public int x;
public int y;
}
public class Solution {
public static boolean isSafe(int x, int y, int r, int c) {
return (x >= 0) && (x < r) && (y >= 0) && (y < c);
}
public static boolean isFreshOrageLeft(int[][] grid) {
int r = grid.length;
int c = grid[0].length;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (grid[i][j] == 1)
return true;
}
}
return false;
}
public static int orangesRotting(int[][] grid) {
int r = grid.length;
int c = grid[0].length;
int count = 0;
boolean flag = false;
Queue<Pair> q = new LinkedList<>();
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (grid[i][j] == 2)
q.add(new Pair(i, j));
}
}
q.add(new Pair(-1, -1));
while (!q.isEmpty()) {
while (q.peek().x != -1 && q.peek().y != -1) {
Pair p = q.poll();
int leftX = p.x - 1;
int leftY = p.y;
if (isSafe(leftX, leftY, r, c) && grid[leftX][leftY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[leftX][leftY] = 2;
q.add(new Pair(leftX, leftY));
}
int rightX = p.x + 1;
int rightY = p.y;
if (isSafe(rightX, rightY, r, c) && grid[rightX][rightY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[rightX][rightY] = 2;
q.add(new Pair(rightX, rightY));
}
int upX = p.x;
int upY = p.y + 1;
if (isSafe(upX, upY, r, c) && grid[upX][upY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[upX][upY] = 2;
q.add(new Pair(upX, upY));
}
int downX = p.x;
int downY = p.y - 1;
if (isSafe(downX, downY, r, c) && grid[downX][downY] == 1) {
if (!flag) {
count++;
flag = true;
}
grid[downX][downY] = 2;
q.add(new Pair(downX, downY));
}
}
flag = false;
q.poll();
if (!q.isEmpty())
q.add(new Pair(-1, -1));
}
return isFreshOrageLeft(grid)?-1:count;
}
public static void main(String[] args) {
int[][] grid = {{2,2,0,1}};
System.out.println(orangesRotting(grid));
}
}

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.

algorithm for largest island in a given matrix

Given a 2 X 2 matrix, return different island sizes that is possible
For example, the following matrix should return [5, 7].
1 0 0 0 1
1 1 1 1 1
0 0 0 0 0
1 1 1 1 1
This is fairly straightforward problem. I am using a boolean visited matrix of same size and traverse the matrix in DFS fashion. I have implemented it here. for some reason, I am getting output as [1]. I tried debugging but my mind stopped working now. I am missing something silly I believe.
public class IslandConnectedCell {
public static void main(String[] args) {
int[][] input = {
{1,0,0,0,1},
{1,1,1,1,1},
{0,0,0,0,0},
{1,1,0,1,1}
};
dfsIsland(input);
}
public static void dfsIsland(int[][] input) {
int rows = input.length;
int cols = input[0].length;
List<Integer> countList = new ArrayList<>();
boolean visited[][] = new boolean[rows][cols];
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; cols++) {
if (input[row][col] == 1 && !visited[row][col]) {
int count = mark(row, col, input, visited, rows, cols, 0);
countList.add(count);
}
}
}
System.out.println(countList);
}
public static int mark(int row, int col, int[][] input, boolean[][] visited, int rows, int cols, int count) {
if (row >= rows || row < 0 || col >= cols || col < 0) {
return 0;
}
if (input[row][col] == 0 || visited[row][col]) {
return 0;
}
visited[row][col] = true;
count+=1;
for (int i = row - 1; i <= row + 1; i++) {
for (int j = col - 1; j <= col + 1; j++) {
if (i != row || j != col) {
mark(i, j, input, visited, rows, cols, count);
}
}
}
return count;
}
}
There are two errors in your code.
See comment by Mick for first error:
One obvious problem in dfsIsland() is at least that for (int col = 0; col < cols; cols++) should probably be for (int col = 0; col < cols; col++) instead (maybe even better to use the common i and j for the row/col indices).
Second error is your use of count in the mark method, most glaringly the lack of using the return value in the recursive call. Remember, Java is pass-by-value.
Hint: I suggest you remove count as a parameter.
Once you fix the errors, output will be:
[7, 2, 2]
public class IslandConnectedCell {
public static void main(String... args) {
int[][] board = { {1,0,0,0,1},
{1,1,1,1,1},
{0,0,0,0,0},
{1,1,0,1,1} };
System.out.println(new IslandConnectedCell(board).getIslandSizes());
}
private final int[][] board;
private final int rows;
private final int cols;
public IslandConnectedCell(int[][] board) {
this.board = board;
this.rows = board.length;
this.cols = board[0].length;
}
public List<Integer> getIslandSizes() {
boolean visited[][] = new boolean[this.rows][this.cols];
List<Integer> countList = new ArrayList<>();
for (int row = 0; row < this.rows; row++)
for (int col = 0; col < this.cols; col++)
if (this.board[row][col] == 1 && ! visited[row][col])
countList.add(mark(row, col, visited));
return countList;
}
private int mark(int row, int col, boolean[][] visited) {
if (row >= this.rows || row < 0 || col >= this.cols || col < 0 || this.board[row][col] == 0 || visited[row][col])
return 0;
visited[row][col] = true;
int count = 1;
for (int r = -1; r <= 1; r++)
for (int c = -1; c <= 1; c++)
if (r != 0 || c != 0)
count += mark(row + r, col + c, visited);
return count;
}
}
UPDATE
To get the desired output of [7, 4] (original question), the board would need to use horizontal wraparound, so the two small islands on the bottom line becomes a single larger island.
That is easily accomplished by modifying one line of code to wraparound the column index using the % modulus operator:
count += mark(row + r, (col + c + this.cols) % this.cols, visited);

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