Vector Convolution - Calculating the Index of a Neighbour Element - java

I am trying to implement a convolution method taking two vectors: an image; and a kernel. My problem is that i don't know how to calculate the index of the image neighbour element when I "slide" the kernel over the image vector. For example, with two identical vectors {0, 1, 2, 3, 4, 5, 6, 7, 8} I would like to achieve the following result:
My code so far is as follows:
public int[] convolve(int[] image, int[] kernel)
{
int imageValue;
int kernelValue;
int outputValue;
int[] outputImage = new int[image.length()];
// loop through image
for(int i = 0; i < image.length(); i++)
{
outputValue = 0;
// loop through kernel
for(int j = 0; j < kernel.length(); j++)
{
neighbour = ?;
// discard out of bound neighbours
if (neighbour >= 0 && neighbour < imageSize)
{
imageValue = image[neighbour];
kernelValue = kernel[j];
outputValue += imageValue * kernelValue;
}
}
output[i] = outputValue;
}
return output;
}

As i + j - (kernel.length / 2) may be too short for an answer:
public class Convolution
{
public static void main(String[] args)
{
int image[] = { 0,1,2,3,4,5,6,7,8 };
int kernel[] = { 0,1,2,3,4,5,6,7,8 };
int output[] = convolve(image, kernel);
for (int i=0; i<image.length; i++)
{
System.out.printf(output[i]+" ");
}
}
public static int[] convolve(int[] image, int[] kernel)
{
int[] output = new int[image.length];
// loop through image
for(int i = 0; i < image.length; i++)
{
System.out.println("Compute output["+i+"]");
int outputValue = 0;
// loop through kernel
for(int j = 0; j < kernel.length; j++)
{
int neighbour = i + j - (kernel.length / 2);
// discard out of bound neighbours
if (neighbour >= 0 && neighbour < image.length)
{
int imageValue = image[neighbour];
int kernelValue = kernel[j];
outputValue += imageValue * kernelValue;
System.out.println("image["+neighbour+"] and kernel["+j+"]");
}
}
output[i] = outputValue;
}
return output;
}
}
Note that this only works properly when the kernel has an odd length. In fact, what you are doing there is to move the center of the kernel through the image space (this is where the kernel.length/2 comes from). For even length kernels, like 0 1 2 3, you would have to decide whether you wanted to include...
0 1 2 3 4 (image)
3 <- This line and/or ...
2 3
1 2 3
0 1 2 3
0 1 2 3
0 1 2
0 1
0 <- ... this line

Sounds to me like you want something like a slider:
static class Slider implements Iterable<List<Integer>> {
final List<Integer> kernel;
final int imageWidth;
final int center;
public Slider(int imageWidth, int kernelWidth) {
// Build my kernel offsets list.
this.kernel = new ArrayList<>(kernelWidth);
for (int i = 0; i < kernelWidth; i++) {
kernel.add(i, i);
}
// Which kernel cell is in the center.
center = kernelWidth / 2;
// Remember the image width.
this.imageWidth = imageWidth;
}
#Override
public Iterator<List<Integer>> iterator() {
return new Iterator<List<Integer>>() {
int x = 0;
#Override
public boolean hasNext() {
return x < imageWidth;
}
#Override
public List<Integer> next() {
List<Integer> slice = kernel.subList(Math.max(0, center - x), Math.min(kernel.size(), center - x + kernel.size()));
x += 1;
return slice;
}
};
}
}
public void test() {
List<Integer> image = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> kernel = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8);
// Keep track of image position.
int x = 0;
for (List<Integer> slice : new Slider(image.size(), kernel.size())) {
System.out.println(slice);
int outputValue = 0;
int imageValue = image.get(x++);
for (Integer o : slice) {
int kernelValue = kernel.get(o);
outputValue += imageValue * kernelValue;
}
System.out.println("outputValue=" + outputValue);
}
}

Related

Recursion Longest Increasing Path in matrix

I am implementing longest increasing path problem of leetcode.
Given an integer matrix, find the length of the longest increasing path.
From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed).
Example 1:
Input: nums =
[
[9,9,4],
[6,6,8],
[2,1,1]
]
Output: 4
Explanation: The longest increasing path is [1, 2, 6, 9].
So Below is my implementation tries a lot on recursion, but not able to understand why it is not giving correct result why maxDist decreases from 4 to 3 to 2 in this example, as this variable is is global not local.
public class LongestIncreasingPath {
private static final int[][] dirs = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
private int m, n;
int maxDist;
public int longestIncreasingPath(int[][] matrix) {
if (matrix.length == 0)
return 0;
m = matrix.length;
n = matrix[0].length;
int ans = 1;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j) {
dfs(matrix, i, j, 1);
ans = Math.max(ans, maxDist);
}
return ans;
}
private int dfs(int[][] matrix, int i, int j, int dist) {
for (int[] d : dirs) {
int x = i + d[0], y = j + d[1];
if (0 <= x && x < m && 0 <= y && y < n && matrix[x][y] > matrix[i][j]) {
maxDist = Math.max(maxDist, dfs(matrix, x, y, dist+1));
}
}
return dist;
}
public static void main(String[] args) {
int[][] nums = { { 9, 9, 4 }, { 6, 6, 8 }, { 2, 1, 1 } };
LongestIncreasingPath lIP = new LongestIncreasingPath();
System.out.println(lIP.longestIncreasingPath(nums));
}
}
The following is a working version, tested on 2 test cases (only). Please note the comments about bugs and some changes in structure:
public class LongestIncreasingPath {
private static final int[][] dirs = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
private int rows, cols;
//avoid non-volatile class variable that may be updated by more than one thread
//use local variables instead
//private int maxDist;
public int longestIncreasingPath(int[][] matrix) {
if (matrix.length == 0) return 0;
rows = matrix.length;
cols = matrix[0].length;
int maxDist = 0; //retain max found
for (int row = 0; row < rows; ++row) {
for (int col = 0; col < cols; ++col) {
//bug fix: use distance (matrix[row][col]) instead of 1
int distance = dfs(matrix, row, col, matrix[row][col]);
maxDist = Math.max(distance, maxDist);
}
}
return maxDist;
}
private int dfs(int[][] matrix, int row, int newCol, int dist) {
int maxDist = dist;
for (int[]dir : dirs) {
int newRow = row + dir[0], y = newCol + dir[1];
if (0 <= newRow && newRow < rows && 0 <= y && y < cols &&
matrix[newRow][y] > matrix[row][newCol]) {
//bug fix: //add new distance matrix[x][y] instead of 1
maxDist = Math.max(maxDist, dfs(matrix, newRow, y, dist + matrix[newRow][y]));
}
}
return maxDist;
}
public static void main(String[] args) {
LongestIncreasingPath lIP = new LongestIncreasingPath();
int[][] nums = { { 9, 9, 4 },
{ 6, 6, 8 },
{ 2, 2, 1 }
};
//printout test case 1
System.out.println(lIP.longestIncreasingPath(nums));
nums = new int[][]{ { 5, 6, 7 },
{ 4, 9, 8 },
{ 3, 2, 1 }
};
//printout test case 2
System.out.println(lIP.longestIncreasingPath(nums));
}
}

java solution to bridge building not returning right answer

I am having issues with my code it is returning 1 when it should be returning 2. The pairs I have are: new CityPairs(6, 2), new CityPairs( 4, 3 ), new CityPairs( 2, 6) , new CityPairs( 1, 5 ). Which it should return 2 bridges but is returning 1. Below is my code.
class CityPairs {
int north, south;
public CityPairs(int north, int south){
this.north = north;
this.south = south;
}
}
class CityPairsDriver {
// function to find the maximum number
// of bridges that can be built
static int maxBridges(CityPairs values[], int n) {
int lis[] = new int[n];
for (int i = 0; i < n; i++)
lis[i] = 1;
Arrays.sort(values, new Comparator<CityPairs>() {
#Override
public int compare(CityPairs a, CityPairs b) {
if (a.south == b.south)
if (a.north < b.north)
return -1;
else
return 1;
else {
if (a.south < b.south)
return 1;
else
return 1;
}
}
});
// logic of longest increasing subsequence
// applied on the northern coordinates
for (int i = 1; i < n; i++)
for (int j = 0; j < i; j++)
if (values[i].north >= values[j].north && lis[i] < 1 + lis[j])
lis[i] = 1 + lis[j];
int max = lis[0];
for (int i = 1; i < n; i++)
if (max < lis[i])
max = lis[i];
// required number of bridges
// that can be built
return max;
}
// Driver program to test above
public static void main(String args[]) {
CityPairs values[] = { new CityPairs(6, 2), new CityPairs( 4, 3 ), new CityPairs( 2, 6) , new CityPairs( 1, 5 ) };
int n = 4;
System.out.println("Maximum number of bridges = " + maxBridges(values, n));
}
}
I based my answer off of this:
https://www.geeksforgeeks.org/dynamic-programming-building-bridges/
you have 3 return that return the same value i think you need to change the last one
so your problem is in the compare function

Algorithmic Puzzle About Using Two Rectangles To Enclose Points

I've been working on this problem for two days, and the best I can do is a brute force solution which is not efficient enough.
You are given a bunch of positive coordinate points ranging from (0, 0) to (1 billion, 1 billion). You must enclose all of the points with only two rectangles with the smallest possible total area. Rectangles must have sides parallel to the x-axis and y-axis. The rectangles cannot overlap, sharing the same boundary counts as overlapping. You **can** have a 0 by 0 rectangle of area zero. The sum of the areas of the two rectangles is **X**
You also have to find a single rectangle of the smallest possible area that encloses all of the points. This area is **Y**
You are trying to find **Y** - **X**.
For the following example, the answer **Y** - **X** = 107.
(4, 2), (8, 10), (1, 1), (9, 12), (14, 7), (2, 3)
Providing code would be very appreciated, if you do then please use Java or C++ if possible.
I do not want to spoil the game.
Start with the large rectangle. Then you can split on every x or y of a point.
Sort the points once by x, once by y.
Split vertically:
#######
#######
#######
#######
Split horizonally:
##
## ####
####
####
Splitting at a coordinate yields two sets of point where both rectangle halves are easily reduced.
Added a solution because of comment
As Point class I actually use int[2] so the x/y choice can be made as for-index. On the other hand, I had to make a class AreaCollector, where a simple Rectangle would suffice.
The rectangle points I have collected too; without them the code would become a bit smaller.
static private class AreaCollector {
private final int[] lwb = new int[] { Integer.MAX_VALUE, Integer.MAX_VALUE };
private final int[] upb = new int[] { Integer.MIN_VALUE, Integer.MIN_VALUE };
public void add(int[] point) {
if (point[0] < lwb[0]) {
lwb[0] = point[0];
}
if (point[1] < lwb[1]) {
lwb[1] = point[1];
}
if (point[0] > upb[0]) {
upb[0] = point[0];
}
if (point[1] > upb[1]) {
upb[1] = point[1];
}
}
public int getArea() {
if (upb[0] == Integer.MIN_VALUE) { /// Zero points added.
return 0;
}
return (upb[0] - lwb[0]) * (upb[1] - lwb[1]);
}
}
public int solve(int[][] points) {
AreaCollector ac = new AreaCollector();
for (int[] point : points) {
ac.add(point);
}
final int y = ac.getArea();
final int n = points.length;
// Best solution sofar:
int[][] ascPoints = Arrays.copyOf(points, n);
int[][] descPoints = new int[0][];
int bestX = y + 0;
for (int direction = 0; direction < 2; ++direction) {
final int dir = direction;
Arrays.sort(points, Comparator.comparingInt((pt) -> pt[dir]));
int[] ascAreas = new int[n];
AreaCollector ascAC = new AreaCollector();
for (int i = 0; i < n; ) {
int[] point = points[i];
int coord = point[direction];
for (int j = i; j < n && points[j][direction] == coord; ++j) {
ascAC.add(points[j]);
}
int area = ascAC.getArea();
for (int j = i; j < n && points[j][direction] == coord; ++j) {
ascAreas[j] = area;
++i;
}
}
int[] descAreas = new int[n];
AreaCollector descAC = new AreaCollector();
for (int i = n - 1; i >= 0; ) {
int[] point = points[i];
int coord = point[direction];
for (int j = i; j >= 0 && points[j][direction] == coord; --j) {
descAC.add(points[j]);
}
int area = descAC.getArea();
for (int j = i; j >= 0 && points[j][direction] == coord; --j) {
descAreas[j] = area;
--i;
}
}
int bestI = -1;
for (int i = 0; i < n- 1; ++i) {
if (points[i][direction] != points[i + 1][direction]) {
int x = ascAreas[i] + descAreas[i + 1];
if (x < bestX) {
bestX = x;
bestI = i;
}
}
}
if (bestI != -1) {
ascPoints = Arrays.copyOfRange(points, 0, bestI + 1);
descPoints = Arrays.copyOfRange(points, bestI + 1, n);
}
}
return y -bestX;
}
As Comparator I used java 8 terse notation. As you see the complexity of the hand-coded part is O(N) superseeded by Arrays.sort O(N.log N).
Here's a solution in Java. After calculating area Y, it first sorts the coordinates by X coordinates and then calculates the area of the rectangles by splitting the array into two halves at each X coordinate (with a special handling if two coordinates have the same X value). Then it does the same for the Y coordinates. The minimum rectangle area is the resulting X area.
import java.util.Arrays;
import java.util.Comparator;
public class Puzzle {
public static void main(String[] args) {
int[][] COORDINATES_1 = { { 4, 2 }, { 8, 10 }, { 1, 1 }, { 9, 12 }, { 14, 7 }, { 2, 3 } };
int[][] COORDINATES_2 = { { 2, 1 }, { 2, 2 }, { 3, 1 }, { 3, 3 }, { 4, 3 }, { 5, 3 }, { 5, 4 }, { 6, 4 } };
int[][] COORDINATES_3 = { { 4, 2 } };
solve(COORDINATES_1);
solve(COORDINATES_2);
solve(COORDINATES_3);
}
public static void solve(int[][] coordinates) {
int size = coordinates.length;
int y = calcMinRectArea(coordinates, 0, size);
// sort by x coordinates
Arrays.sort(coordinates, new Comparator<int[]>() {
#Override
public int compare(int[] o1, int[] o2) {
return o1[0] - o2[0];
}
});
int x = y;
for (int i = 1; i < size; i++) {
if (coordinates[i][0] == coordinates[i - 1][0])
continue; // several coordinates with the same x coordinates
x = Math.min(calcMinRectArea(coordinates, 0, i) + calcMinRectArea(coordinates, i, size - i), x);
}
// sort by y coordinates
Arrays.sort(coordinates, new Comparator<int[]>() {
#Override
public int compare(int[] o1, int[] o2) {
return o1[1] - o2[1];
}
});
for (int i = 1; i < size; i++) {
if (coordinates[i][1] == coordinates[i - 1][1])
continue; // several coordinates with the same y coordinates
x = Math.min(calcMinRectArea(coordinates, 0, i) + calcMinRectArea(coordinates, i, size - i), x);
}
System.out.printf("Y = %d, X = %d, Y - X = %d\n", y, x, y - x);
}
private static int calcMinRectArea(int[][] coords, int start, int length) {
if (length == 0)
return 0;
int minX = coords[start][0];
int maxX = minX;
int minY = coords[start][1];
int maxY = minY;
for (int i = start + 1; i < start + length; i++) {
int x = coords[i][0];
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
int y = coords[i][1];
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
}
return (maxX - minX) * (maxY - minY);
}
}

Waffle Stacking Algorithm needs improvement

I am working on a problem called Waffle Stacking. I am aware that a question already exists but the post needed to know where to start but I already have most of it done. The problem can be seen here: http://www.hpcodewars.org/past/cw16/problems/Prob20--WaffleStacking.pdf
My algorithm calculates the 120 permutations (5!) of the String "12345". I then place then row by row and make sure that they match the side clues. Then I check if it so far matches the top side. (Meaning that I go through the tiles that I currently have and I find the tallest stack and I look for the unused stacks and check if they are higher than the current highest stack and then I can see if I use the unused stacks they will match the clue). Using the example, my algorithm is very flawed. It produces only 4 rows and only one is correct. I believe it is due to checking the column. Any help is apprectated with checking the top and bottom sides.
package HP2013;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
public class WaffleStacking
{
public static String t[];
public static String l[];
public static String r[];
public static String b[];
public static void getInput()
{
try{
Scanner keyb = new Scanner(new File("src/HP2013/WaffleStacking.dat"));
t = keyb.nextLine().split(" ");
l = new String[5];
r = new String[5];
for (int i = 0; i < 5; i++)
{
String a[] = keyb.nextLine().split(" ");
l[i] = a[0];
r[i] = a[1];
}
b = keyb.nextLine().split(" ");
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static ArrayList<String> perms = new ArrayList<String>();
public static void getPerms(String s)
{
getPerms("", s);
}
public static void getPerms(String pfx, String s)
{
int n = s.length();
if (n == 0)
perms.add(pfx);
else
{
for (int i = 0; i < s.length(); i++)
getPerms(pfx + s.charAt(i) + "", s.substring(0, i) + s.substring(i + 1));
}
}
public static void solve()
{
int mat[][] = new int[5][5];
for (int r = 0; r < 5; r++)
{
String row = "";
for (int p = 0; p < perms.size(); p++)
{
if (goodRow(perms.get(p), r))
{
row = perms.get(p);
for (int c = 0; c < row.length(); c++)
mat[r][c] = Integer.valueOf(row.charAt(c) + "");
if (uniqueCol(mat, r + 1) && goodCol(mat, r + 1))
break;
else
{
mat[r] = new int[] {0, 0, 0, 0, 0}.clone();
}
}
}
}
for (int m[] : mat)
System.out.println(Arrays.toString(m));
}
public static boolean uniqueCol(int mat[][], int rStop)
{
for (int c = 0; c < mat.length; c++)
{
ArrayList<Integer> col = new ArrayList<Integer>();
for (int r = 0; r < rStop; r++)
col.add(mat[r][c]);
Collections.sort(col);
for (int i = 0; i < col.size() - 1; i++)
if (col.get(i) == col.get(i + 1))
return false;
}
return true;
}
public static boolean goodRow(String row, int index)
{
int left = 0;
int max = -1;
for (int i = 0; i < row.length(); i++)
{
int stack = Integer.valueOf(row.charAt(i) + "");
if (stack > max)
{
left++;
max = stack;
}
}
int right = 0;
max = -1;
for (int i = row.length() - 1; i >= 0; i--)
{
int stack = Integer.valueOf(row.charAt(i) + "");
if (stack > max)
{
right++;
max = stack;
}
}
if (left == Integer.valueOf(l[index]) && right == Integer.valueOf(r[index]))
return true;
return false;
}
public static boolean goodCol(int mat[][], int rStop)
{
return checkTop(mat, rStop);
}
public static boolean checkTop(int mat[][], int rStop)
{
for (int c = 0; c < 5; c++)
{
int left = Integer.valueOf(t[c] + "");
int max = -1;
String used = "";
for (int r = 0; r < rStop; r++)
{
int stack = mat[r][c];
used += stack;
if (stack > max)
{
max = stack;
left--;
}
}
ArrayList<Integer> leftovers = new ArrayList<Integer>();
for (int n = 1; n <= 5; n++)
{
if (!used.contains(n + ""))
leftovers.add(n);
}
for (int j = 0; j < leftovers.size(); j++)
{
if (leftovers.get(j) > max)
{
max = leftovers.get(j);
left--;
}
}
if (left > 0)
return false;
}
return true;
}
public static void main(String args[])
{
getInput();
getPerms("12345");
solve();
}
}
Input:
2 2 3 2 1
4 1
1 4
3 2
2 2
3 2
3 2 1 3 4
Output:
[1, 3, 2, 4, 5]
[5, 1, 4, 3, 2]
[2, 4, 1, 5, 3]
[3, 2, 5, 1, 4]
[0, 0, 0, 0, 0]
So the first problem I see is no way to jump out when you've found a good answer. You're loops are probably continuing on after they've found the correct answer and unrolling to a point where you're losing the last row because of your else clause for a bad match.
Bottom side checking was not the problem, I overthought it; It should be very similar to top side checking. The solve method was very faulty and I switched to a recursive solution which ended up solving the problem. That way I can try several possibilities of valid rows while maintaining unique columns and then check if the columns were valid as well. If they weren't I can continue trying different possibilities.

Multiplying two matrices in Java

I am currently developing a class to represent matrices, it represents any general mxn matrix. I have worked out addition and scalar multiplication but I am struggling to develop the multiplication of two matrices. The data of the matrix is held in a 2D array of doubles.
The method looks a little bit like this:
public Matrix multiply(Matrix A) {
////code
}
It will return the product matrix. This is multiplication on the right. So, if I called A.multiply(B) then it would return the matrix AB, with B on the right.
I don't yet need to worry about checking whether the multiplication is defined on the given matrices, I can assume that I will be given matrices of the correct dimensions.
Does anyone know of an easy algorithm, possibly even in pseudocode to carry out the multiplication process?
Mathematically the Product of Matrices A (l x m) and B (m x n) is defined as a Matrix C (l x n) consisting of the elements:
m
c_i_j = ∑ a_i_k * b_k_j
k=1
So if you're not too much up for speed you might be happy with the straight forward O(n^3) implementation:
for (int i=0; i<l; ++i)
for (int j=0; j<n; ++j)
for (int k=0; k<m; ++k)
c[i][j] += a[i][k] * b[k][j]
If instead you're up for speed you might want to check for other alternatives like Strassen algorithm (see: Strassen algorithm).
Nevertheless be warned - especially if you're multiplying small matrices on modern processor architectures speed heavily depends on matrix data and multiplication order arranged in a way to make best use of in cache lines.
I strongly doubt there will be any chance to influence this factor from withing a vm, so I'm not sure if this is to be taken into consideration.
Java. Matrix multiplication.
Here is the "code to carry out the multiplication process". Tested with matrices of different size.
public class Matrix {
/**
* Matrix multiplication method.
* #param m1 Multiplicand
* #param m2 Multiplier
* #return Product
*/
public static double[][] multiplyByMatrix(double[][] m1, double[][] m2) {
int m1ColLength = m1[0].length; // m1 columns length
int m2RowLength = m2.length; // m2 rows length
if (m1ColLength != m2RowLength) return null; // matrix multiplication is not possible
int mRRowLength = m1.length; // m result rows length
int mRColLength = m2[0].length; // m result columns length
double[][] mResult = new double[mRRowLength][mRColLength];
for (int i = 0; i < mRRowLength; i++) { // rows from m1
for (int j = 0; j < mRColLength; j++) { // columns from m2
for (int k = 0; k < m1ColLength; k++) { // columns from m1
mResult[i][j] += m1[i][k] * m2[k][j];
}
}
}
return mResult;
}
public static String toString(double[][] m) {
String result = "";
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
result += String.format("%11.2f", m[i][j]);
}
result += "\n";
}
return result;
}
public static void main(String[] args) {
// #1
double[][] multiplicand = new double[][]{
{3, -1, 2},
{2, 0, 1},
{1, 2, 1}
};
double[][] multiplier = new double[][]{
{2, -1, 1},
{0, -2, 3},
{3, 0, 1}
};
System.out.println("#1\n" + toString(multiplyByMatrix(multiplicand, multiplier)));
// #2
multiplicand = new double[][]{
{1, 2, 0},
{-1, 3, 1},
{2, -2, 1}
};
multiplier = new double[][]{
{2},
{-1},
{1}
};
System.out.println("#2\n" + toString(multiplyByMatrix(multiplicand, multiplier)));
// #3
multiplicand = new double[][]{
{1, 2, -1},
{0, 1, 0}
};
multiplier = new double[][]{
{1, 1, 0, 0},
{0, 2, 1, 1},
{1, 1, 2, 2}
};
System.out.println("#3\n" + toString(multiplyByMatrix(multiplicand, multiplier)));
}
}
Output:
#1
12.00 -1.00 2.00
7.00 -2.00 3.00
5.00 -5.00 8.00
#2
0.00
-4.00
7.00
#3
0.00 4.00 0.00 0.00
0.00 2.00 1.00 1.00
In this answer, I created a class named Matrix, and another class is known as MatrixOperations which defines the various operations that can be performed on matrices (except for row operations of course). But I will extract the code for multiplication from MatrixOperations. The full project can be found on my GitHub page here.
Below is the definition of the Matrix class.
package app.matrix;
import app.matrix.util.MatrixException;
public class Matrix {
private double[][] entries;
public void setEntries(double[][] entries) {
this.entries = entries;
}
private String name;
public double[][] getEntries() {
return entries;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public class Dimension {
private int rows;
private int columns;
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getColumns() {
return columns;
}
public void setColumns(int columns) {
this.columns = columns;
}
public Dimension(int rows, int columns) {
this.setRows(rows);
this.setColumns(columns);
}
#Override
public boolean equals(Object obj) {
if(obj instanceof Dimension){
return (this.getColumns() == ((Dimension) obj).getColumns()) && (this.getRows() == ((Dimension) obj).getRows());
}
return false;
}
}
private Dimension dimension;
public Dimension getDimension() {
return dimension;
}
public void setDimension(Dimension dimension) {
this.dimension = dimension;
}
public Matrix(int dimension, String name) throws MatrixException {
if (dimension == 0) throw new MatrixException(ZERO_UNIT_DIMENSION);
else this.setEntries(new double[Math.abs(dimension)][Math.abs(dimension)]);
this.setDimension(new Dimension(dimension, dimension));
this.setName(name);
}
public Matrix(int dimensionH, int dimensionV, String name) throws MatrixException {
if (dimensionH == 0 || dimensionV == 0) throw new MatrixException(ZERO_UNIT_DIMENSION);
else this.setEntries(new double[Math.abs(dimensionH)][Math.abs(dimensionV)]);
this.setDimension(new Dimension(dimensionH, dimensionV));
this.setName(name);
}
private static final String OVERFLOW_ITEMS_MSG = "The values are too many for the matrix's specified dimensions";
private static final String ZERO_UNIT_DIMENSION = "Zero cannot be a value for a dimension";
public Matrix(int dimensionH, int dimensionV, String name, double... values) throws MatrixException {
if (dimensionH == 0 || dimensionV == 0) throw new MatrixException(ZERO_UNIT_DIMENSION);
else if (values.length > dimensionH * dimensionV) throw new MatrixException(Matrix.OVERFLOW_ITEMS_MSG);
else this.setEntries(new double[Math.abs(dimensionH)][Math.abs(dimensionV)]);
this.setDimension(new Dimension(dimensionH, dimensionV));
this.setName(name);
int iterator = 0;
int j;
for (int i = 0; i < dimensionH; i++) {
j = 0;
while (j < dimensionV) {
this.entries[i][j] = values[iterator];
j++;
iterator++;
}
}
}
public Matrix(Dimension dimension) throws MatrixException {
this(dimension.getRows(), dimension.getColumns(), null);
}
public static Matrix identityMatrix(int dim) throws MatrixException {
if (dim == 0) throw new MatrixException(ZERO_UNIT_DIMENSION);
double[] i = new double[dim * dim];
int constant = dim + 1;
for (int j = 0; j < i.length; j = j + constant) {
i[j] = 1.0;
}
return new Matrix(dim, dim, null, i);
}
public String toString() {
StringBuilder builder = new StringBuilder("Matrix \"" + (this.getName() == null ? "Null Matrix" : this.getName()) + "\": {\n");
for (int i = 0; i < this.getDimension().getRows(); i++) {
for (int j = 0; j < this.getDimension().getColumns(); j++) {
if (j == 0) builder.append("\t");
builder.append(this.entries[i][j]);
if (j != this.getDimension().getColumns() - 1)
builder.append(", ");
}
if (i != this.getDimension().getRows()) builder.append("\n");
}
builder.append("}");
return builder.toString();
}
public boolean isSquare() {
return this.getDimension().getColumns() == this.getDimension().getRows();
}
}
and here is the code method for matrix multiplication from MatrixOperations
public static Matrix multiply(Matrix matrix1, Matrix matrix2) throws MatrixException {
if (matrix1.getDimension().getColumns() != matrix2.getDimension().getRows())
throw new MatrixException(MATRIX_MULTIPLICATION_ERROR_MSG);
Matrix retVal = new Matrix(matrix1.getDimension().getRows(), matrix2.getDimension().getColumns(), matrix1.getName() + " x " + matrix2.getName());
for (int i = 0; i < matrix1.getDimension().getRows(); i++) {
for (int j = 0; j < matrix2.getDimension().getColumns(); j++) {
retVal.getEntries()[i][j] = sum(arrayProduct(matrix1.getEntries()[i], getColumnMatrix(matrix2, j)));
}
}
return retVal;
}
and below again are the codes for methods sum, arrayProduct, and getColumnMatrix
private static double sum(double... values) {
double sum = 0;
for (double value : values) {
sum += value;
}
return sum;
}
private static double[] arrayProduct(double[] arr1, double[] arr2) throws MatrixException {
if (arr1.length != arr2.length) throw new MatrixException("Array lengths must be the same");
double[] retVal = new double[arr1.length];
for (int i = 0; i < arr1.length; i++) {
retVal[i] = arr1[i] * arr2[i];
}
return retVal;
}
private static double[] getColumnMatrix(Matrix matrix, int col) {
double[] ret = new double[matrix.getDimension().getRows()];
for (int i = 0; i < matrix.getDimension().getRows(); i++) {
ret[i] = matrix.getEntries()[i][col];
}
return ret;
}
Try this code for multiple any dimensional array and print it. Think this is more simple and anyone can understand this.
public class Test {
public static void main(String[] args) {
int[][] array1 = {
{1, 4, -2},
{3, 5, -6},
{4, 5, 2}
};
int[][] array2 = {
{5, 2, 8, -1},
{3, 6, 4, 5},
{-2, 9, 7, -3}
};
Test test = new Test();
test.printArray(test.multiplication(array1, array2));
}
private int[][] multiplication(int[][] array1, int[][] array2) {
int r1, r2, c1, c2;
r1 = array1.length;
c1 = array1[0].length;
r2 = array2.length;
c2 = array2[0].length;
int[][] result;
if (c1 != r2) {
System.out.println("Error!");
result = new int[0][0];
} else {
result = new int[r1][c2];
for (int i = 0; i < r1; i++) { //2
for (int j = 0; j < c2; j++) { //4
for (int k = 0; k < c1; k++) {
result[i][j] += array1[i][k] * array2[k][j];
}
}
}
}
return result;
}
private void printArray(int[][] array) {
for (int[] arr : array) {
for (int element : arr) {
System.out.print(element + " ");
}
System.out.println();
}
}
}

Categories

Resources