I am working on writing a matrix, but unfortunately I am stuck with the output.
Instead of showing a matrix, it shows me something like:
actual matrix is
Matrix#512fb063
I need to convert the matrix to a string so that the output will look like this:
expected the matrix:
3 8 72
4 6 60
253 2 1
the code that I've written is this:
import java.util.Random;
final public class Matrix {
private final int size1; // number of rows
private final int size2; // number of columns
private final int[][] data; // M-by-N array
// create size1-by-size2 matrix of 0's
public Matrix(int size1, int size2) {
this.size1 = size1;
this.size2 = size2;
data = new int[size1][size2];
}
// create matrix based on 2d array
public Matrix(int[][] data) {
size1 = data.length;
size2 = data[0].length;
this.data = new int[size1][size2];
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
this.data[i][j] = data[i][j];
}
// creates and returns a random size1-by-size1 matrix with values between 0 and 255
public String toString(int size1, int size2) {
Matrix A = new Matrix(size1, size2);
String str = " ";
final int white = 0;
final int black = 255;
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
{
A.data[i][j] = white + (int)(Math.random() * ((black ) ));
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
if (i==size1 &&j==size2) str = (A.data[i][j]+"\n");
}
return str;
}
You need to override the public String toString() function. What you are doing now is creating a new function called String toString(int size1, int size2).
Your new function is not called when writing:
System.out.println(myMatrix);
You could either do:
System.out.println(myMatrix.toString(2, 2));
or override the default toString() function.
So the following code should work:
#Override
public String toString() {
Matrix A = new Matrix(size1, size2);
String str = " ";
final int white = 0;
final int black = 255;
for (int i = 0; i < size1; i++)
for (int j = 0; j < size2; j++)
{
A.data[i][j] = white + (int)(Math.random() * ((black ) ));
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
if (i==size1 &&j==size2) str = (A.data[i][j]+"\n");
}
return str;
}
where size1 and size2 are variables in the class.
Your output of actual matrix is Matrix#512fb063 is actually the memory address in Java that your instance of the class Matrix sits in. That's because your program doesn't know how to "print" this class - it doesn't magically know that you want a row/column representation of it.
You've got a number of options:
Your toString(int size1, int size2) is perfect. So when you want to print your matrix, you can go System.out.println(someMatrix.toString(2,2)) will work where someMatrix is an instance of your Matrix class.
If you want it to work properly by you just going System.out.println(someMatrix) then you will need to overwrite your Matrix class' toString() function. You -almost- did that in your toString(int size1, int size2) function but it didn't work because it needs to match exactly the parameters, ie: toString() should take 0 parameters. You will need to write a toString() method which can then call your toString(int size1, int size2)
Somehow you get the hashcode. Maybe you can use http://math.nist.gov/javanumerics/jama/doc/ matrix implementation.
I think this line is not working
str = (A.data[i][j]+"\t"+A.data[i][j+1]);
Don't you get an IndexOutOfBoundexception? Anyway A.data[i][j+1] is always empty within the loop. By the way, Variables in Java are always lower case.
You can simply do :
#Override
public String toString()
{
return toString(size1,size2);
}
Edit : If you want to reflect the real content of your current Matrix :
#Override
public String toString()
{
StringBuilder sbResult = new StringBuilder();
for(int i = 0; i < size1;i++)
{
for(int j = 0; j < size2;j++)
{
sbResult.append(A.data[i][j]);
sbResult.append("\t");
sbResult.append(A.data[i][j+1]);
if(i == size1 && j == size2)
{
sbResult.append("\n");
}
}
}
return sbResult.toString();
}
Related
I have some code for a 2D array but I don't want spaces at the end of each row before I start a new row. For some reason, I can't find where I'm messing up because a space is being put at the end of each row. Basically what I'm trying to do is input a 2D array and the output should make it look the same as the input, except for the {}'s and it'll be a string. For example,
Input:
{1, 2, 3},
{4, 5, 6};
Output:
1 2 3
4 5 6
public class Matrix {
// the dimensions of the matrix
private int numRows;
private int numColumns;
// the internal storage for the matrix elements
private int data[][];
/**
* #param d - the raw 2D array containing the initial values for the Matrix.
*/
public Matrix(int d[][])
{
// d.length is the number of 1D arrays in the 2D array
numRows = d.length;
if(numRows == 0)
numColumns = 0;
else
numColumns = d[0].length; // d[0] is the first 1D array
// create a new matrix to hold the data
data = new int[numRows][numColumns];
// copy the data over
for(int i=0; i < numRows; i++)
for(int j=0; j < numColumns; j++)
data[i][j] = d[i][j];
}
/**
* Returns a String representation of this Matrix.
*/
#Override // instruct the compiler that we intend for this method to override the superclass' (Object) version
public String toString() {
// TODO: replace the below return statement with the correct code.
String arrString = "";
for(int i = 0; i < data.length; i++) {
for(int j = 0; j < data[i].length; j++) {
arrString += data[i][j] + " ";
}
arrString += "\n";
}
return arrString;
}
Next time please post a runnable example.
Your problem was that you always added a space after the item, no matter if it was the last one in the line. I now check that with a conditional + (j == data[i].length - 1 ? "" : " ");
Hint: It's not good to concatenate Strings. Use StringBuilder for better performance an memory usage. I added a second method toString2() to show how it's done.
package stackoverflow;
public class Matrix {
// the dimensions of the matrix
private final int numRows;
private int numColumns;
// the internal storage for the matrix elements
private final int data[][];
/**
* #param d - the raw 2D array containing the initial values for the Matrix.
*/
public Matrix(final int d[][]) {
// d.length is the number of 1D arrays in the 2D array
numRows = d.length;
if (numRows == 0)
numColumns = 0;
else
numColumns = d[0].length; // d[0] is the first 1D array
// create a new matrix to hold the data
data = new int[numRows][numColumns];
// copy the data over
for (int i = 0; i < numRows; i++)
for (int j = 0; j < numColumns; j++)
data[i][j] = d[i][j];
}
/**
* Returns a String representation of this Matrix.
*/
#Override // instruct the compiler that we intend for this method to override the superclass' (Object) version
public String toString() {
// TODO: replace the below return statement with the correct code.
String arrString = "";
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
arrString += data[i][j] + (j == data[i].length - 1 ? "" : " ");
}
arrString += "\n";
}
return arrString;
}
public String toString2() {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
sb.append(data[i][j] + (j == data[i].length - 1 ? "" : " "));
}
sb.append("\n");
}
return sb.toString();
}
public static void main(final String[] args) {
final int[][] arr = new int[2][3];
arr[0][0] = 4;
arr[0][1] = 6;
arr[0][2] = 8;
arr[1][0] = 8;
arr[1][1] = 16;
arr[1][2] = 23;
final Matrix m = new Matrix(arr);
System.out.println("Matrix:\n" + m);
System.out.println("Matrix 2:\n" + m.toString2());
}
}
Output:
Matrix:
4 6 8
8 16 23
Matrix 2:
4 6 8
8 16 23
The Answer by JayC667 seems to correctly address your Question.
Stream, lambda, & method reference
For fun, here is an alternative approach using stream, lambda, and method reference.
Define the array.
int[][] input = { { 1 , 2 , 3 } , { 4 , 5 , 6 } }; // Declaration, initialization.
Make a stream where each element is a row, an array of int values, from your two-dimensional array.
For each of those rows, each being a int[], make a stream of its int primitive values (an IntStream), convert each primitive to an Integer object (boxing), call each Integer object’s toString method to generate a piece of text. Collect those pieces of text by joining them into a longer String with a SPACE character as a delimiter.
So we have transformed each row into a String. Collect all those strings together, with a LINE FEED character as the delimiter. Then, we are done, with a single String object as a result.
All that work, in a single line of code!
String result =
Arrays
.stream( input ) // A series of integer arrays, etc element being a int[].
.map( // Convert each integer array into something else, a `String` object.
( int[] row ) -> Arrays.stream( row ).boxed().map( Object :: toString ).collect( Collectors.joining( " " ) )
)
.collect( Collectors.joining( "\n" ) ); // Join each row of text with the next, using Linefeed as delimiter.
Results.
1 2 3
4 5 6
Here is one way to return a formatted 2D array based on the anticipated width of the values.
%nd - specifies a field width of n digits, right aligned.
%-nd - specifies a field width of n digits, left aligned (would have spaces at end of line).
fields will be filled in with spaces where necessary.
public class TwoDtoString {
int[][] mat = { { 11, 222, 3333 }, { 433, 53, 633 }, { 73, 8, 9333 } };
static String FORMAT = "%5d"; // 5 digit field, right aligned.
public static void main(String[] args) {
TwoDtoString tos = new TwoDtoString();
System.out.println(tos.toString());
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (int[] row : mat) {
sb.append(FORMAT.formatted(row[0]));
for (int i = 1; i < row.length; i++) {
sb.append(FORMAT.formatted(row[i]));
}
sb.append("\n");
}
return sb.toString();
}
}
prints
11 222 3333
433 53 633
73 8 9333
Edit: I am trying to pass the values of wG1...wG5, which are in the Main class, to rarityType(), which is expecting five parameters. I want these passed parameters to be used in int[], which defines the weight of the items in the rare[].
Hard-coding the values into the function (line 3) works as intended:
public String rarityType() {
String rare[] = {"Common", "Uncommon", "Rare", "Epic", "Legendary"};
int[] a = {64, 32, 24, 4, 1};
int sum = 0;
for (int i : a)
sum += i;
int s = r.nextInt(sum);
int prev_value = 0;
int current_max_value;
int found_index = -1;
for (int i = 0; i < a.length; i++) {
current_max_value = prev_value + a[i];
boolean found = (s >= prev_value && s < current_max_value);
if (found) {
found_index = i;
break;
}
prev_value = current_max_value;
}
rarityType() is not instanced in Main, it's value is retrieved via getter:
Weapon weapon = new Weapon();
String weaponRarity = weapon.getWeaponRarity();
And in the class:
private String weaponRarity = rarityType();
But I want to be able to modify those values from Main.
.
I am trying to set parameters in Main for a class that returns a weighted random string. When I have the parameters hard coded in the class, it works as expected.
The exception is telling me that the random generator returned null because it was not passed any parameters. I tried to create setters in the class and define them in Main, to no avail. My question is, how can I pass parameters to the function in the class that I instantiate in Main? Thank you for any guidance!
Note: I cannot have a constructor for this class in Main because their are other functions in the class that rely on the returned string from this function.
Main code snippet:
Weapon weapon = new Weapon();
weapon.wG1 = 1;
weapon.wG2 = 1;
weapon.wG3 = 1;
weapon.wG4 = 1;
weapon.wG5 = 1000;
Class code snippet:
public class Weapon {
public int wG1,wG2,wG3,wG4,wG5;
private Random r = new Random();
private String weaponRarity = rarityType(wG1,wG2,wG3,wG4,wG5);
public String rarityType(int w1, int w2, int w3, int w4, int w5) {
String rare[] = {"Common", "Uncommon", "Rare", "Epic", "Legendary"};
int[] a = {w1, w2, w3, w4, w5};
int sum = 0;
for (int i : a)
sum += i;
int s = r.nextInt(sum); //line 100
int prev_value = 0;
int current_max_value;
int found_index = -1;
for (int i = 0; i < a.length; i++) {
current_max_value = prev_value + a[i];
boolean found = (s >= prev_value && s < current_max_value);
if (found) {
found_index = i;
break;
}
prev_value = current_max_value;
}
String selection = "unknown";
if (found_index != -1) {
selection = rare[found_index];
}
return selection;
}
This version of the code throws an exception:
Caused by: java.lang.IllegalArgumentException: n <= 0: 0 at
net.zingrook.mobiloot.Weapon.rarityType(Weapon.java:100)
I think it happens because rarityType method is executed when you create weapon object but wG1,wG2,wG3,wG4,wG5 are not instantiated yet:
Weapon weapon = new Weapon();
probably it will make sense to create a constructor with all these parameters. Please let me know if you have any questions.
I want to program a pacmanstyle maze game in Java.
for the maze i am using a property file, in which coordinates are stored (i.e. x=1, y=5 -> wall) as strings in following format: 79,13=0 79,12=0 79,11=0.
I want to create the mazegrid using a 2d array: int [][] maze.
i know how to load in a property file. My problem however is, I have no idea how to first extract the string variables out of the property and second the proper way to fill the array.
public final class Labyrinth {
private int i;
private int j;
private static int [][] maze;
private String p;
private String l;
public void setMaze(int x, int y){
x = this.i;
y = this.j;
}
public static int[][] getMaze(){
return maze;
}
public Labyrinth(int rows, int cols) throws IOException{
try (FileInputStream in = new FileInputStream("level.properties")) {
Properties p1 = new Properties();
p1.load(in);
p = p1.getProperty("Height");
l = p1.getProperty("Width");
cols = parseInt(p);
rows = parseInt(l);
maze = new int[rows][cols];
for (i=0; i < rows; i++){
for(j=0; j < cols; j++){
setMaze(parseInt(p1.getProperty('ValueX,ValueY')),
parseInt(p1.getProperty('ValueX,ValueY')));
}
}
}
}
}
Any helpfull thought will be highly appreciated!
i have no idea how to first extract the string variables out of the .property and second the proper way to fill the array.
What do you mean by extracting string variables? A property file is simply a list of key-value pairs. In your case, the key is x,y and the value is apparently indicating some object in the maze.
You could try reading the keys like this:
for (i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
int value = parseInt(p1.getProperty(i + "," + j); // Get the value of (i,j)
maze[i][j] = value; // Assign the value to the maze
}
}
I am supposed to write a method that accepts 3 2-D arrays of This method should determine whether one of the matrices is the result of matrix addition of the other two.
public class Matrix {
public static void main(String[]args){
int [][] a = {{5,2,3},{4,1,6},{0,7,2}};
int [][] b = {{1,2,3},{4,5,6},{0,1,2}};
int [][] t = {{6,4,6},{8,6,12},{0,8,4}};
System.out.println(add(a,b));
System.out.println(check(a,b,t));
}
public static int [][] add(int[][]a,int[][]b){
int i=0;
int j=0;
int[][] r = new int [3][3];
while (i<a.length){
r[i][j] = a[i][j] + b[i][j];
i++;
j++;
}
return r;
}
public static boolean check(int[][]a,int[][]b,int[][]t){
int i = 0;
int j = 0;
while(i<t.length){
if(t==add(a,b))
return true;
}
return false;
}
}
add returns an array. Arrays in Java are objects, but they do not override the toString() method. When printing, you'd print their default toString() call, which is implemented by Object as return getClass().getName() + "#" + Integer.toHexString(hashCode());.
Luckily, Java provides a utility in the form of java.util.Arrays.deepToString(Ojbect[]) to generate a more readable string output:
System.out.println(Arrays.deepToString(add(a,b)));
EDIT:
Your add method is also wrong. Your code iterates i and j together, so it only sums the elements along the matrix's diagonal instead of adding all of them. You should use a nested loop instead:
public static int [][] add(int[][]a, int[][]b) {
int[][] r = new int [3][3];
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
r[i][j] = a[i][j] + b[i][j];
}
}
return r;
}
Your check method, by the way, is also wrong - it attempts to compare the array itself instead of is elements:
public static boolean check(int[][]a, int[][]b, int[][]t) {
int[][] r = add(a, b);
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (r[i][j] != t[i][j]) {
return false;
}
}
}
return true;
}
I'm currently trying to figure out how to redifine my toString method so that it will display the matrix. Here's the code..
import java.util.Random;
public class TextLab09st
{
public static void main(String args[])
{
System.out.println("TextLab09\n\n");
Matrix m1 = new Matrix(3,4,1234);
Matrix m2 = new Matrix(3,4,1234);
Matrix m3 = new Matrix(3,4,4321);
System.out.println("Matrix m1\n");
System.out.println(m1+"\n\n");
System.out.println("Matrix m2\n");
System.out.println(m2+"\n\n");
System.out.println("Matrix m3\n");
System.out.println(m3+"\n\n");
if (m1.equals(m2))
System.out.println("m1 is equal to m2\n");
else
System.out.println("m1 is not equal to m2\n");
if (m1.equals(m3))
System.out.println("m1 is equal to m3\n");
else
System.out.println("m1 is not equal to m3\n");
}
}
class Matrix
{
private int rows;
private int cols;
private int mat[][];
public Matrix(int rows, int cols, int seed)
{
this.rows = rows;
this.cols = cols;
mat = new int[rows][cols];
Random rnd = new Random(seed);
for (int r = 0; r < rows; r ++)
for (int c = 0; c < cols; c++)
{
int randomInt = rnd.nextInt(90) + 10;
mat[r][c] = randomInt;
}
}
public String toString()
{
return ("[" + mat + "]");
}
public boolean equals(Matrix that)
{
return this.rows == (that.rows)&&this.cols == that.cols;
}
}
I know how to display it and how to redifine the equals method, I feel like it's just late and I'm missing something silly. Sorry for any inconvience!
EDIT: Sorry, I forgot to specify that it had to be shown as a 2 dimensional row x column display.
EDIT2: Now I'm having trouble redefining the equals method, as it is required for my assignment. I rewrote it to this:
public boolean equals(Matrix that)
{
return this.mat == that.mat;
}
and it still outputs:
m1 is not equal to m2
m1 is not equal to m3
Is there any easy way to fix this?
You'd have to make a nested loop for each cell in your matrix.
public String toString()
{
String str = "";
for (int i = 0 ; i<this.rows ; i ++ ){
for (int j = 0 ; j < this.cols ; j++){
str += mat[i][j]+"\t";
}
str += "\n";
}
return str;
}
As for the "equal" method, I'm not quite sure what is the criteria.
Does your application consider two matrixes to be equal if they both have the same number of rows and cols?
P.S.
Overriding the equal method is a very good practice, but it is a better practice to override the "hashCode" method as well.
Might not be relevant to your app, but it is important.
Hope that would help :)
Use Arrays.deepToString:
public String toString()
{
return Arrays.deepToString(mat);
}