You are to write a program that reads two matrices from files, multiples them, a
ID: 3880357 • Letter: Y
Question
You are to write a program that reads two matrices from files, multiples them, and displays outputs both to the terminal and a result file. To begin, we have a very easy file format to represent a matrix. Consider the following example matrix: 1 2 3 4 5 6 For this program, the corresponding file would have the following contents: 2, 3, {1 2 3 4 5 6} That is, first the number of rows, then the number of columns, and then the contents in row-major order4. Inside the program, we will represent a matrix as an array of arrays of integers. So, the above example could be initialized as… int[][] m = {{1, 2, 3}, {4, 5, 6}}; So the length of the “outer” array is the number of rows, and the length of each “inner” array is the number of columns. To get used to this representation, first complete the canMultiply method, which takes two matrices (in order) and checks if they can be multiplied via their dimensions. Once you are getting the hang of things, move on to readMatrix to create this matrix from a Scanner. With these complete, you’ll be ready for the matrixMultiply method. Your program will then prompt the user for file paths, attempt to open them (providing an error if they don’t), check their dimensions using your method, and then output the results both to the terminal and to the file supplied by the user. Note: the screen and file representations will be different, and you have been supplied methods to perform this output correctly. For example… Enter path for matrix 1: m1.txt Enter path for matrix 2: m2.txt Enter path for result: m3.txt 1 2 3 4 5 6 X 1 1 1 2 2 2 3 3 3 = 14 14 14 32 32 32 In this case assume m1.txt contained the contents described above, and m2.txt contained the following: 3 3 1 1 1 2 2 2 3 3 3 After the program runs, m3.txt will contain the following: 2 3 14 14 14 32 32 32 Your main method should provide appropriate input validation: Enter path for matrix 1: m2.txt Enter path for matrix 2: m1.txt Enter path for result: m3.txt 1 1 1 2 2 2 3 3 3 X 1 2 3 4 5 6 = Bad matrix dimensions Enter path for matrix 1: m_bad.txt Enter path for matrix 2: m2.txt Enter path for result: m3.txt Error opening file(s)
Explanation / Answer
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class PA2c {
/**
* Error to output if can't open any files
*/
public static final String ERR_FILE = "Error opening file(s)";
/**
* Error to output if files open but matrices are of incompatible dimensions for
* multiplication
*/
public static final String ERR_DIMS = "Bad matrix dimensions";
private static void _outputMatrix(PrintWriter out, int[][] m, boolean includeDimensions) {
for (int r = 0; r < m.length; r++) {
if (includeDimensions && r == 0) {
out.printf("%d%n%d%n", m.length, m[0].length);
}
for (int c = 0; c < m[r].length; c++) {
out.printf("%d", m[r][c]);
out.printf((c < m[r].length - 1) ? " " : "%n");
}
}
}
/**
* Prints a matrix to the terminal without dimensions
*
* @param m
* matrix to print
*/
public static void printMatrix(int[][] m) {
_outputMatrix(new PrintWriter(System.out, true), m, false);
}
/**
* Prints a matrix to a file with associated dimensions
*
* @param m
* matrix to print
* @param pw
* open file
*/
public static void printMatrix(int[][] m, PrintWriter pw) {
_outputMatrix(pw, m, true);
}
/**
* Checks if two matrices can be multiplied (i.e. the columns of the first match
* the rows of the second)
*
* @param m1
* matrix 1
* @param m2
* matrix 2
* @return true if m1 x m2 is legal
*/
public static boolean canMultiply(int[][] m1, int[][] m2) {
if (m1[0].length == m2.length) {
return true;
}
return false;
}
/**
* Reads and returns a matrix from a scanner Format: m (# rows) n (# #cols) r0c0
* r0c1 ... r0cn (values in row 0, column-by-column) r1c0 r1c1 ... r1cn (values
* in row 1, column-by-column) ... rmc0 rmc1 ... rmcn (values in last row,
* column-by-column)
*
* Results in... int[][] { {r0c0, r0c1, ... r0cn}, {r1c0, r1c1, ... r1cn}, ...
* {rmc0, rmc1, ... rmcn} }
*
* @param s
* input source
* @return resulting matrix
*/
public static int[][] readMatrix(Scanner s) {
int row = s.nextInt();
int col = Integer.parseInt(s.next().trim());
String matData = s.next().trim(); // Reading {1 2 3 4 5 6}
matData = matData.replaceAll("\{", "").replaceAll("\}", ""); // Stripping curly braces
int mat[][] = new int[row][col];
String[] elements = matData.split(" ");// SPlitting 1 2 3 4 5 6 by space
// Loading into matrix
int index = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
mat[i][j] = Integer.parseInt(elements[index]);
index++;
}
}
System.out.println("Matrix:");
_outputMatrix(new PrintWriter(System.out, true), mat, true);
return mat;
}
/**
* Multiply two matrices and return the result
*
* @param m1
* matrix 1
* @param m2
* matrix 2
* @return result of m1 x m2
*/
public static int[][] matrixMultiply(int[][] m1, int[][] m2) {
int r1 = m1.length;
int c2 = m2[0].length;
int c1 = m1[0].length;
int[][] product = new int[r1][c2];
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
for (int k = 0; k < c1; k++) {
product[i][j] += m1[i][k] * m2[k][j];
}
}
}
return product;
}
/**
* Program to multiply matrices: 1. Ask for paths for 3 files (2 input, 1
* output) 2. Check if inputs can be multiplied 3. If so, multiply! - Output the
* full problem to the console - Output only the result matrix to the file
*
* @param args
* command-line arguments, ignored
* @throws FileNotFoundException
*/
public static void main(String[] args) {
String m1Path, m2Path, outPath;
// Scanner to read stdin inputs
Scanner sc = new Scanner(System.in);
System.out.println("Enter the Matrix 1 file path");
m1Path = sc.nextLine();
System.out.println("Enter the Matrix 2 file path");
m2Path = sc.nextLine();
System.out.println("Enter the Matrix output file path");
outPath = sc.nextLine();
// Necessary vas
Scanner m1Sc = null, m2Sc = null;
int[][] m2 = null;
int[][] m1 = null;
int[][] outMat = null;
try {
m1Sc = new Scanner(new File(m1Path)).useDelimiter(","); // Reading comma separated values. Scanner receives
// a file input which is comma delimited.
m1 = readMatrix(m1Sc);
m2Sc = new Scanner(new File(m2Path)).useDelimiter(","); // Reading comma separated values. Scanner receives
// a file input which is comma delimited.
m2 = readMatrix(m2Sc);
} catch (FileNotFoundException e) {
System.out.println(ERR_FILE);
e.printStackTrace();
} finally {
if (m1Sc != null) {
m1Sc.close();
}
if (sc != null) {
sc.close();
}
if (m2Sc != null) {
m2Sc.close();
}
}
if (m1 != null && m2 != null) {
if (canMultiply(m1, m2)) {
outMat = matrixMultiply(m1, m2);
// Printing the output to console
_outputMatrix(new PrintWriter(System.out, true), outMat, true);
// Writing to a file
BufferedWriter bw;
try {
bw = new BufferedWriter(new FileWriter(outPath));
int row = outMat.length;
int col = outMat[0].length;
bw.write(String.valueOf(row));
bw.write(",");
bw.write(String.valueOf(col));
bw.write(",{");
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
bw.write(String.valueOf(outMat[i][j]));
bw.write(" ");
}
}
bw.write("}");
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println(ERR_DIMS);
}
} else {
System.out.println("Matrix is null. Please validate the read.");
}
}
Program has comments. And following sample is verified.
File1:
2, 3, {1 2 3 4 5 6}
File2:
3, 3, {1 1 1 2 2 2 3 3 3}
OutFIle:
2,3,{14 14 14 32 32 32 }
Console Output:
Enter the Matrix 1 file path
m1.txt
Enter the Matrix 2 file path
m2.txt
Enter the Matrix output file path
m3.txt
Matrix:
2
3
1 2 3
4 5 6
Matrix:
3
3
1 1 1
2 2 2
3 3 3
2
3
14 14 14
32 32 32
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.