I am trying to implement a matrix using a hash map but I think I am doing something wrong somewhere.
If I type the following matrix:
4 3
2 1
I get
0 3
0 0
Here's my code:
package matrix;
import java.util.HashMap;
public class SparseMatrix extends AbstractMatrix{
private int x=0; // nr of rows
private int y=0; // nr of columns
private int hashvalue = 0;
public void Index (final int x, final int y)
{
this.x=x;
this.y=y;
hashvalue=((x+"")+(y+"")).hashCode();
}
public boolean equals (final Object obj)
{
if (obj instanceof Index)
{
Index index = (Index) obj;
return ((x==index.x) && (y==index.y));
}
else
return false;
}
public int hashCode()
{
return hashvalue;
}
private int rows;
private int columns;
private HashMap<Index,Double> values;
private boolean validIndex (final int row, final int column)
{
return (row>=0 && row<rows && column>=0 && column<columns);
}
public SparseMatrix(double[][] contents) throws MatrixException {
this(contents.length,contents[0].length);
for (int i=0; i<contents.length; i++)
for (int j=0; j<contents[0].length; j++)
setElement(i,j,contents[i][j]);
}
public SparseMatrix(int rows, int columns) throws MatrixException {
if (rows<1 || columns<1)
throw new MatrixException("Number of rows and columns cannot be less than 1");
this.rows=rows;
this.columns=columns;
this.values=new HashMap<Index,Double>();
}
#Override
public int getNumberOfRows() {
return rows;
}
#Override
public int getNumberOfColumns() {
return columns;
}
#Override
public double getElement(int row, int column) throws MatrixException {
if (!validIndex(row,column))
throw new MatrixException (row,column);
Index index = new Index (row,column);
if (values.containsKey(index))
return values.get(index);
else
return 0;
}
#Override
public void setElement(int row, int column, double value) throws MatrixException {
if (!validIndex(row,column))
throw new MatrixException (row,column);
Index index = new Index(row,column);
if (value==0)
{
if (values.containsKey(index))
values.remove(index);
}
else
values.put(index,value);
}
}
and my main function:
a2 = new SparseMatrix(2,2);
a1.setElement(0,0,4);
a1.setElement(0,1,3);
a1.setElement(1,0,2);
a1.setElement(1,1,1);
for (int i=0; i<a2.getNumberOfRows(); i++)
{
for (int j=0; j<a2.getNumberOfColumns(); j++)
System.out.print (a2.getElement(i, j)+ " ");
System.out.println();
}
Any ideas what I am doing wrong?
public void Index (final int x, final int y)
It looks like this was supposed to be a constructor of the Index class, but instead it's a method, and I don't see the Index class declared anywhere.
You are assigning an instance of SparseMatrix to a2, but call setElement for a1 :
a2 = new SparseMatrix(2,2);
a1.setElement(0,0,4);
a1.setElement(0,1,3);
a1.setElement(1,0,2);
a1.setElement(1,1,1);
I tried your code, fixing all the compilation errors and not relying on the AbstractMatrix super class (by removing the #Override from all the overridden method and by changing the code at the top of your class into a nested class named Index), and got the desired output :
4.0 3.0
2.0 1.0
Here's the nested Index class I used :
static class Index {
private int x=0; // nr of rows
private int y=0; // nr of columns
private int hashvalue = 0;
public Index (final int x, final int y)
{
this.x=x;
this.y=y;
hashvalue=((x+"")+(y+"")).hashCode();
}
public boolean equals (final Object obj)
{
if (obj instanceof Index)
{
Index index = (Index) obj;
return ((x==index.x) && (y==index.y));
}
else
return false;
}
public int hashCode()
{
return hashvalue;
}
}
I think your constructor should refer to contents[i] instead of contents[0]
public SparseMatrix(double[][] contents) throws MatrixException {
this(contents.length,contents[0].length);
for (int i=0; i<contents.length; i++)
for (int j=0; j<contents[i].length; j++)
setElement(i,j,contents[i][j]);
}
Related
I was solving past exams for my java class and I'm struggling with one of them. I keep getting wrong result and I think its because all of classes and instance variables are static. How do I avoid making them static? Also this question basically wants you to find same letters of the location given in args[1] and convert them to the "S" if they are near of the given location (Args are "K,K,K,Y-K,Y,M,M-K,Y,Y,Y 2,1 S" if you need)
public class MatrixRefill {
public static String[][] matrix;
public static int rows;
public static int cols;
public static String enemy;
public static String target;
public static void main(String[] args) {
target = args[2];
rows = Integer.parseInt(args[1].substring(0,1));
cols = Integer.parseInt(args[1].substring(2));
matrix = matrixCreator(args[0]);
enemy = matrix[rows][cols];
recursive(rows, cols, target);
printer(matrix);
}
public static String[][] matrixCreator(String mx) {
int ro = 0;
int co = 0;
for (int i = 0; i < mx.length(); i++) {
if (mx.substring(i,i+1).equals(","))
co++;
if (mx.substring(i,i+1).equals("-"))
ro++;
}
String[][] matriks = new String[ro+1][co/3+1];
ro = 0;
co = 0;
for (int j = 0; j < mx.length(); j++) {
if (mx.substring(j,j+1).equals(","))
co++;
else if (mx.substring(j,j+1).equals("-")) {
ro++;
co = 0;
}
else
matriks[ro][co] = mx.substring(j,j+1);
}
return matriks;
}
public static void recursive(int row, int col, String target) {
if (valid(row,col)) {
recursive(row+1,col, target);
recursive(row,col+1, target);
recursive(row,col-1, target);
recursive(row-1,col, target);
matrix[row][col] = target;
}
}
public static boolean valid(int row, int col) {
boolean result = false;
if (row >= 0 && row < matrix.length && col >= 0 && col < matrix[row].length)
if (matrix[row][col] == enemy)
result = true;
return result;
}
public static void printer(String[][] owo) {
for(int i = 0; i < owo.length; i++) {
for(int j = 0; j < owo[i].length; j++) {
System.out.print(owo[i][j]);
if(j < owo[i].length - 1)
System.out.print(" ");
}
System.out.println();
}
}
}
Remove the static keyword from your methods and instance fields. But to call them from within main you need to create an instance of the containing class (in this case the one that contains the main method) and use that to call the other methods. What I do sometimes is to create an instance method (i.e. non-static) and call that to start the process. Then everything that would be in main I would put in that method. Here is an example.
public static void main(String[] args) {
MatrixRefill mr = new MatrixRefill();
mr.start();
}
public void start() {
target = args[2];
rows = Integer.parseInt(args[1].substring(0,1));
cols = Integer.parseInt(args[1].substring(2));
matrix = matrixCreator(args[0]);
enemy = matrix[rows][cols];
recursive(rows, cols, target);
printer(matrix);
}
// rest of code here
}
By putting what was in main in the start method you can call the other instance methods and access instance fields without qualifying them with a reference to the class (i.e. in this case prefixing with mr.)
In my program I have a pair class:
class Pair {
public int ind = 0;
public String letter = "";
public Pair(int a, String b) {
ind = a; //index
letter = b;
}
}
how do I set the index (ind) of an element in an arraylist of Pairs? I have tried
RightMotor.ind.set(j, i);
and
LeftMotor.set(j, i).ind;
but they don't seem to work.
First you need to 'get' the Pair instance, like:
Pair pair = LeftMotor.get(i);
then you can change its fields:
pair.ind = j;
This can also be done in one line:
LeftMotor.get(i).ind = j;
Hint 1: this is not changing the index (position) of the instance in the list, LeftMotor.get(i) will still return the same element. i and ind are two completely disjunct values.
Hint 2: normally it is better to have private fields and have a method (setter) to change the fields (encapsulation):
class Pair {
private int ind = 0;
private String letter = "";
public Pair(int a, String b) {
ind = a; //index
letter = b;
}
public void setInd(int newInd) {
ind = newInd;
}
}
Hint 3: just to be clear, just because it is called ind it is not the index (position) of the list. It is a whole different question if you want to change the order of the elements in the list.
You want to make those instance variables private, then getters/setters to access/modify them. This allows you to safely and securely manipulate the data with a reduced chance of bleedover (which can crash your program or cause unintended consequences).
Within your class:
class Pair {
private int ind = 0;
private String letter = "";
public Pair(int index, String letter) {
ind = index;
letter = letter;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public String getLetter() {
return this.letter;
}
public void setLetter(String letter) {
this.letter = letter;
}
public void setIndexAndLetter(int index, String letter) {
this.index = index;
this.letter = letter;
}
}
Elsewhere in your program:
Pair rightMotor = new Pair(1, "a");
Pair leftMotor = new Pair(2, "b");
Pair middleMotor = new Pair(0, "");
rightMotor.setInd(3);
leftMotor.setLetter("d");
middleMotor.setIndAndLetter(rightMotor.getInd() + leftMotor.getInd(), "z");
You have to create a Pair instance using the Pair constructor before adding it to the ArrayList:
RightMotor.add(new Pair(i,j)); // assuming i is an int and j is a String
If you want to replace the Pair stored in a given index use:
RightMotor.set(index,new Pair(i,j));
If you want to change an existing Pair stored in the ArrayList:
RightMotor.get(index).setInd(newValue);
This will require a setter method in your Pair class:
public void setInd (int i) {
ind = i;
}
So I think that you could solve this in a couple of different ways... however I think I know what you are trying to do.... I feel like you are trying to keep the ArrayList and the Pair index synchronized... either way you will need a helper method to accomplish this. I agree with hendripd that you should use private variables and utilize the getters and setters. However this is my solution.
Pair:
public class Pair implements Comparable<Pair> {
private int index = 0;
private String letter = "";
public Pair(int index, String letter) {
this.index = index;
this.letter = letter;
}
public Pair(Pair pair) {
this.index = pair.getIndex();
this.letter = pair.getLetter();
}
#Override
public int compareTo(Pair pair) {
if (this.index > pair.index) {
return 1;
} else if (this.index < pair.index) {
return -1;
} else {
return 0;
}
}
#Override
public String toString() {
return this.index + " " + this.letter;
}
public int getIndex() {
return this.index;
}
public String getLetter() {
return this.letter;
}
public void setIndex(int index) {
this.index = index;
}
public void setLetter(String letter) {
this.letter = letter;
}
}
Main:
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static ArrayList<Pair> rightMotor;
public static void main(String[] args) {
rightMotor = new ArrayList<Pair>();
rightMotor.add(new Pair(0, "a"));
rightMotor.add(new Pair(1, "b"));
setIndex(rightMotor, 0, 1);
// If you choose to go with the second option utilizing Comparable<Pair>
// Collections.sort(rightMotor);
for (Pair pair : rightMotor) {
System.out.println(pair.toString());
}
}
public static void setIndex(ArrayList<Pair> motor, int oldIndex, int newIndex) {
Pair tempPair = new Pair(motor.get(oldIndex));
if (oldIndex < newIndex) {
for (int i = oldIndex; i < newIndex; i++) {
motor.set(i, motor.get(i + 1));
motor.get(i).setIndex(i);
}
} else if (oldIndex > newIndex) {
for (int i = oldIndex; i > newIndex; i--) {
motor.set(i, motor.get(i - 1));
motor.get(i).setIndex(i);
}
}
tempPair.setIndex(newIndex);
motor.set(newIndex, tempPair);
}
}
Note that the Pair class implements comparable... you could use Collections.Sort(rightMotor) which then you would only need to fix the indexes of the instances... i.e.
public static void setIndex(ArrayList<Pair> motor, int oldIndex, int newIndex) {
motor.get(oldIndex).setIndex(newIndex);
if (oldIndex < newIndex) {
for (int i = oldIndex; i < newIndex; i++) {
motor.get(i + 1).setIndex(i);
}
} else if (oldIndex > newIndex) {
for (int i = oldIndex; i > newIndex; i--) {
motor.get(i - 1).setIndex(i);
}
}
}
Or... you can use the original one I posted which also handles the sorting at the same time. This keeps your Arraylist in numerical order by index either way.
Test casing:
rightMotor.add(new Pair(0, "a"));
rightMotor.add(new Pair(1, "b"));
rightMotor.add(new Pair(2, "c"));
rightMotor.add(new Pair(3, "d"));
rightMotor.add(new Pair(4, "e"));
rightMotor.add(new Pair(5, "f"));
setIndex(rightMotor, 0, 1);
setIndex(rightMotor, 3, 1);
setIndex(rightMotor, 4, 3);
outputs this result:
0 b
1 d
2 a
3 e
4 c
5 f
I have a problem in implementing those methods(min, max, and average ) in my generic class. I have already specified the return type as E but it seems hard to get it to work. if anyone has an example for implementing those methods I would really appreciate it.
public E ave() {
int total = 0;
for (int i = 0; i < size(); i++) {
total = (total + bag[i]);
}
int ave = (total / size());
return ave;
}
public int minimum() {
int min = bag[0];
for (int a = 1; a < size(); a++) {
if (bag[a] < min) {
min = bag[a];
}
}
return min;
}
First define some interface with int method that will be used by your math class.
public interface IntHolder {
int getIntValue();
}
Add contraint to generic E such that E extends IntHolder i. e. only IntHolder implementations can be added in GenericArrayMath. Since all objects are guarenteed to be of IntHolder type, now you can use in your math methods getIntValue() of given object.
Note, unconstrained E can by anything so it is impossible to predict by compiler object fields/methods. The only thing that you can be sure about E is, that it extends Object (as all classes extends Object by default), thus you can only use Object's methods.
public class GenericArrayMath<E extends IntHolder> {
private final E[] bag;
public GenericArrayMath(Class<E> clazz, int length) {
bag = (E[]) Array.newInstance(clazz, length)
}
public void set(int i, E e) { bag[i] = e; }
public int min() {
int min = Integer.MAX_VALUE;
for (int i = 0; i < bag.length; i++) {
if (bag[i] == null) { continue; } // skip
if (bag[i] < min) { min = bag[i]; }
}
return min;
}
public int max() {
int max = Integer.MIN_VALUE;
for (int i = 0; i < bag.length; i++) {
if (bag[i] == null) { continue; } // skip
if (bag[i] > max) { max = bag[i]; }
}
return max;
}
public double avg() {
double sum = 0;
int nonNullCount = 0;
for (int i = 0; i < bag.length; i++) {
if (bag[i] == null) { continue; } // skip
sum += bag[i].getIntValue();
nonNullCount++;
}
return sum / nonNullCount;
}
}
Example of IntHolder implementation:
public class Person extends IntHolder {
public final String name;
public final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
#Override
public int getIntValue() { return age; }
}
and finally GenericArrayMath usage:
GenericArrayMath<Person> gam = new GenericArrayMath<>(Person.class, 3);
gam.set(0, new Person("a", 20));
gam.set(1, new Person("b", 30));
gam.set(2, new Person("c", 40));
int minAge = gam.min();
int maxAge = gam.max();
double avgAge = gam.avg();
Hope it helps.
I have been trying to troubleshoot this java program from hours now and has not been able to find what is wrong with the execution. I think that the main class is not defined correctly.
It compiles successfully but the output is blank which should not be the case right? I intially tried to call the main class using the objects but still no luck. Any suggestions will work.
The original program:It compiles successfully on adding the main method but the output is blank.
import java.lang.Math; // headers MUST be above the first class
// one class needs to have a main() method
public class OrdSetSimple
{
// arguments are passed using the text field below this editor
public static void main(String[] args){
OrdSetSimple obj = new OrdSetSimple(10);
System.out.print("Success");
}
private int _set_size;
private int _set[];
private int _last;
public OrdSetSimple(int size) {
int k;
_set_size=size;
_set = new int[_set_size];
for(k=0; k<_set_size; k++)
_set[k]=0;
_last=-1;
}
private int make_a_free_slot(int val) {
int pos, i, j;
pos = binSearch(val);
if (pos >= 0)
return -1;
for (i=0; i<=_last; i++) {
if (_set[i] > val)
break;
}
if ((i<=_last)||(_last==-1)) {
for (j=_last; j>=i; j--)
_set[j+1] = _set[j];
pos = i;
} else {
pos = _last+1;
}
_last++;
return pos;
}
public void addElement(int n) {
int pos;
if (n<0) {
System.out.println("Addition of a negative integer impossible\n");
return;
}
if (_last+1>=_set_size) {
System.out.print("Addition of " + n);
System.out.println(" impossible since the array is already full");
System.out.println("The array is: " + toString());
} else {
pos = make_a_free_slot(n);
if (pos>=0)
_set[pos]=n;
}
return;
}
public int getSize() {
return _last+1;
}
public int getElementAt(int i) {
if ((i<0)||(i>_last))
return -1;
else
return _set[i];
}
private int binSearch(int x) {
int i=0;
int j=_last-1;
int m=0;
if (_last==-1)
return -1;
while(i<j) {
m= (i+j)/2;
if (x>_set[m])
i=m+1;
else
j=m;
}
if (x == _set[i]) return i;
else return -1;
}
public OrdSetSimple difference(OrdSetSimple s2) {
OrdSetSimple s1 = this;
int size1=s1.getSize();
int size2=s2.getSize();
OrdSetSimple set=new OrdSetSimple(size2);
int k;
for(k=0; k<size1; k++)
if (s2.binSearch(s1.getElementAt(k)) < 0)
set.addElement(s1.getElementAt(k));
return set;
}
public String toString() {
int k = 0;
String s="";
for (k=0; k<=_last; k++)
s += _set[k] + " ";
return s;
}
}
Your very first statement is wrong.
OrdSetSimple obj = new OrdSetSimple();//This will call the default constructor which will not initialize anything. This constructor will be added to your program by compiler, hence you don't get any compilation error.
Correct it like
OrdSetSimple obj = new OrdSetSimple(100);
I made a map by arraylist, and trying to swap the index(not the value) of arraylist.
For example, the swapRow(1,2) changes the position of row 1 and 2.
This works at the first time, but if I do it again, an error comes out.(Same problem with the swapCol() part.)
Stuck in this problem and need help...
In addition, can anyone help me out making the swapValue() method.
Changing the value is simple, though I also want to move the index, not the value.
import java.text.DecimalFormat;
import java.util.ArrayList;
public class IntMap {
class Data {
private int data_;
public Data(int data)
{
setData(data);
}
public void setData(int data)
{
if(data<0)data=0;
if(data>99)data=99;
data_=data;
}
public int getData()
{
return data_;
}
}
class Index {
private int index_;
public Index(int index)
{
setIndex(index);
}
public void setIndex(int index)
{
if(index < 0) index=0;
index_=index;
}
public int getIndex()
{
return index_;
}
}
private ArrayList<ArrayList<Data>> datas_;
private ArrayList<Index> cols_;
private ArrayList<Index> rows_;
public IntMap(int rowCount, int colCount)
{
if(rowCount < 0) rowCount = 1;
if(rowCount < 0) colCount = 1;
cols_ = new ArrayList<Index>();
rows_ = new ArrayList<Index>();
datas_ = new ArrayList<ArrayList<Data>>();
for(int i=0 ; i<rowCount ; ++i) rows_.add(new Index(i));
for(int i=0 ; i<colCount ; ++i) cols_.add(new Index(i));
for(int i=0 ; i< rowCount ; ++i)
{
ArrayList<Data> temp = new ArrayList<Data>();
datas_.add(temp);
for(int j=0 ; j<colCount ; ++j)
{
temp.add(new Data(0));
}
}
}
public int getValue(int row, int col)
{
int rIndex = getRowIndex(row);
int cIndex = getColIndex(col);
return datas_.get(rIndex).get(cIndex).getData();
}
public void setValue(int row, int col, int value)
{
int rIndex = getRowIndex(row);
int cIndex = getColIndex(col);
datas_.get(rIndex).get(cIndex).setData(value);
}
public void setRandomValue()
{
for(int row=0 ; row < datas_.size() ; ++row)
{
ArrayList<Data> temp = datas_.get(row);
for(int col=0; col <temp.size() ; ++col)
{
Data data = temp.get(col);
data.setData((int)(Math.random()*100));
}
}
}
public void log()
{
DecimalFormat df = new DecimalFormat("00");
for(int row=0; row<rows_.size(); ++row)
{
for(int col=0; col<cols_.size(); ++col)
{
int value = getValue(row, col);
System.out.print(df.format(value));
if(col<cols_.size()-1)
System.out.print(", ");
}
System.out.println();
}
System.out.println();
}
private int getColIndex(int col)
{
if(col <0 || col>=cols_.size())
{
System.out.println("[error][IntMap][getColIndex] - col is"+col);
return 0;
}
for(int i =0; i<cols_.size(); ++i)
{
if(cols_.get(i).getIndex()==col)
return i;
}
System.out.println("[error][IntMap][getColIndex] - unknown error");
return 0;
}
private int getRowIndex(int row)
{
if(row <0 || row>=rows_.size())
{
System.out.println("[error][IntMap][getRowIndex] - row is"+row);
return 0;
}
for(int i =0; i<rows_.size(); ++i)
{
if(rows_.get(i).getIndex()==row)
return i;
}
System.out.println("[error][IntMap][getRowIndex] - unknown error");
return 0;
}
public void swapValue(int a, int b, int c, int d)
{
//
}
public void swapCol(int a, int b)
{
int col1=a;
int col2=b;
int t=a;
cols_.get(col1).setIndex(col2);
cols_.get(col2).setIndex(t);
}
public void swapRow(int a, int b)
{
int t=a;
rows_.get(a).setIndex(b);
rows_.get(b).setIndex(t);
}
public static void main(String[] args)
{
System.out.println("start!");
IntMap map =new IntMap(3,4);
System.out.println("Init map 3x4");
map.log();
System.out.println("random map");
map.setRandomValue();
map.log();
System.out.print("get map[0][1]= ");
System.out.println(map.getValue(0,1));
System.out.println("set map[2][1]=50");
map.setValue(2, 1 ,50);
map.log();
System.out.println("swap(0,1 <-> 2,1)");
map.swapValue(0,1,2,1);
map.log();
System.out.println("swapRow(0 <-> 2)");
map.swapRow(0,2);
map.log();
System.out.println("swapRow(1 <-> 2)");
map.swapRow(1,2);
map.log();
System.out.println("swapCol(0 <-> 3)");
map.swapCol(0,3);
map.log();
}
}
I think you got confused the index of rows_ arrayList and your Index type. your swapRow(a,b) should check rows_ list and find out the element (Index Object) .getIndex = a and b, then swap the two Index elements, not just like what you did in your method. If you change the method into followings, it should work. you could do some error handling, e.g. what happend parameter a or b invalid. I just set themt to 0.
public void swapRow(int a, int b) {
int ai = 0, bi = 0;
for (final Index i : rows_) {
if (i.getIndex() == a) {
ai = rows_.indexOf(i);
}
if (i.getIndex() == b) {
bi = rows_.indexOf(i);
}
}
final Index aidx = rows_.get(ai);
rows_.set(ai, rows_.get(bi));
rows_.set(bi, aidx);
}
and, i don't know your exact requirment. but from the design point of view, there might be room to improve.