LinkedList Matrix, Null Pointer Exception when setting value - java

I started with a 2D array matrix program that works entirely ok. I converted most of it to implement a linked list version of the same thing. Currently (using .printStackTrace) I find my null pointer exception is from this line -> matrix.setValue(matrixRow, matrixColumn, value);
which calls setValue and the error is thrown at this -> a[x][y] = value; //error in this line
I hope to have included enough code, let me know if more info is helpful. In need of a coding break for the moment. Many thanks.
else { //matrix creation
matrix = new Node();
int matrixRow = 1;
int matrixColumn = 1;
for (int i = 1; i <= matrixSize; i++) {
//scanner one line at a time
scanner = new Scanner(fileIO.getNextLine());
if (scanner.hasNextDouble()) {
while (scanner.hasNextDouble()) {
value = scanner.nextDouble();
matrix.construct(matrixRow, matrixColumn);
matrix.setValue(matrixRow, matrixColumn, value);
matrixColumn++;
}//while
matrixRow++;
matrixColumn = 1;
}//if
}//for
if (matrix.isSquare()) {
determinant = matrixMaths.determinate(matrix);
fileIO.writeToOutput(matrix.toString());
fileIO.writeToOutput("The determinant is: " + String.valueOf(determinant));
fileIO.writeToOutput("\n\n");
} else {
errorMsg = "\n\nMatrix is not square.\n\n";
fileIO.writeToOutput(errorMsg);
}//else
}//else matrix creation
Node construct(int n, int m) {
Node[][] a = new Node[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
Node ptr = new Node();
ptr.data = a[i][j];
ptr.right = null;
ptr.down = null;
a[i][j] = ptr;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (j != n - 1)
a[i][j].right = a[i][j + 1];
if (i != n - 1)
a[i][j].down = a[i + 1][j];
}
}
return a[0][0];
}
public void setValue(int x, int y, double value) {
a[x][y] = value; //error in this line
if (x > sizeX) {
sizeX = x;
}
if (y > sizeY) {
sizeY = y;
}
}
* Edit *
I had put in system.out statements right before I called setValue to see that I was passing the values of 1 to the array. The method only gets this far until I get the error.
So, setValue(matrixRow, matrixColumn, value) -> setValue(1,1,value); on the first go through the while loop. I changed to this
int matrixRow = 0;
int matrixColumn = 0;
but then get the new error here (last return in the construct method):
return a[0][0];
another arrayOutOfBounds...
I'm going to try to follow the logic again but not sure yet where to make the fix. Help please!
And changing the row/column = 2 also gets the NUllPtr again.
So, made a few changes and am getting further...
} else { //matrix creation
matrix = new Node();
int matrixRow = 0;
int matrixColumn = 0;
System.out.println("\n" + "matrixSize " + matrixSize);
for (int i = 1; i <= matrixSize; i++) {
//scanner one line at a time
scanner = new Scanner(fileIO.getNextLine());
if (scanner.hasNextDouble()) {
while (scanner.hasNextDouble()) {
value = scanner.nextDouble();
System.out.println(matrixRow + " row number");
System.out.println(matrixColumn + " column number");
System.out.println(value + " value");
matrix.construct(matrixRow, matrixColumn, value);
matrixColumn++;
}//while
matrixRow++;
matrixColumn = 1;
}
My input is this...
3
3 -2 4
-1 5 2
-3 6 4
Output gets through matrices size 1 and 2. It gets as far as the third matrix row 3, column 0. At row 3, col 0, I get the ArrayIndexOutOfBounds error again.
I had it working but then ran into trouble setting the values but.... the project is to be a "matrix as a linked list" which is different than the previous assignment "matrix as a 2D array". So perhaps my structures are incorrect to begin with? Also, My Node class is separate (as an ADT implementing an interface). There is a whole 'nother class for finding the determinant. Not worried about that at right now. Also, we are given the "matrix size" the line before the matrix data in the input. And thank you again!
**Can't sleep edit...
This construct works through the entire input file. So now I just need to figure out where to set the values. (Value is not being assigned here so I'll likely delete it unless I can figure out a way around that).
void construct(int n, int m, double value) {
System.out.println("construct " + n + " n " + m + " m " + value + " value");
Node[][] a = new Node[n + 1][m + 1];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
Node ptr = new Node();
ptr.data = a[i][j];
ptr.right = null;
ptr.down = null;
a[i][j] = ptr;
a[i][j].right = a[i][j + 1];
a[i][j].down = a[i + 1][j];
}
}
}

It seems to be an off by one error. If we replace the values:
int matrixRow = 1;
int matrixColumn = 1;
into what is being declared, we see that you are accessing the array at the place a[1][1], but your declaration for the array size is Node[][] a = new Node[1][1]; (when replacing n and m by the value above). This means that the only element accessible for setValue is a[0][0] (because arrays have a length of size - 1.
I suggest you do an array bounds-checking if-statement on the setValue function, you'll be able to catch errors like this with greater ease. Another way to check my theory is to set matrixRow and matrixColumn as 2 and insert a debug print statement for the array at the beginning of the setValue function, and see what is the first element populated.
Edit:
The reason you get an error in your construct function is because you are creating a zero length array, and then trying to access its first element (see Why does Java allow arrays of size 0? for more info on zero length arrays in java)
I don't know the nature of your project, but I suggest you separate the logic of your code. It seems that you are representing your matrix as an array of "Node"s, and that you know the size of the matrix beforehand.
If so, I would suggest representing your matrix as a class, and making the construct method return and instance of that class.
At the very least, I see no reason as to why you should need to create the matrix inside the while loop. Create it beforehand, and populate it with values later.

Related

How can I create a new instance of array dynamically if my array size is full in java

I am working on a java program. where I have taken an input string and I am putting each char from a string in a 4*4 matrix. If the input string length is small than 16 i.e 4*4 matrix, then I am adding padding '#' char.
But Now, suppose the input string length is more than 16 then I want to create a new array and put remaining chars into it. I can't use a vector, set, map. So How can I code now?
here is some code. key=4.
char[][] giveMeNewArray() {
char[][] matrix = new char[key][key];
return matrix;
}
void putCharIntoMatrix() {
int counter = 0;
char[][] myArray = giveMeNewArray();
System.out.println("myArray: " + myArray);
for (int i = 0; i < key; i++) {
for (int j = 0; j < key; j++) {
if (counter >= inputString.length()) {
myArray[i][j] = '#';
} else {
myArray[i][j] = inputString.charAt(key * i + j);
}
counter++;
}
}
for (int i = 0; i < key; i++) {
for (int j = 0; j < key; j++) {
System.out.print(myArray[i][j] + " ");
}
System.out.println();
}
}
So if I'm understanding this question correctly, you want to create a matrix to hold the characters of an input string, with a minimum size of 4*4?
You're probably better off creating a proper matrix rather than expanding it:
Do you want your matrix to always be square?
Get the next-highest (self-inclusive) perfect square using Math.sqrt
int lowRoot = (int)Math.sqrt(inString.length());
int root;
if(lowRoot * lowRoot < inString.length())
root = lowRoot+1;
else
root = lowRoot;
Create your matrix scaled for your input, minimum four
int size = (root < 4) ? 4 : root;
char[][] matrix = new char[size][size];
But if you really want to expand it, you can just create a new matrix of a greater size:
char[][] newMatrix = new char[oldMatrix.length+1][oldMatrix[0].length+1];
And copy the old matrix into the new matrix
for(int i = 0; i < oldMatrix.length; ++i){
for(int j = 0; j < oldMatrix[i].length; ++j){
newMatrix[i][j] = oldMatrix[i][j];
}
}
If you expand by one each time you'll do tons of expands, if you expand by more you might expand too far.
This is really inefficient versus just doing some math at the beginning. Making a properly sized matrix from the start will save you a bunch of loops over your data and regularly having two matrices in memory.
If understand you request correctly, if the string length is bigger than 16 you just create a new array, well how about making a list of array initilized at one array and if there are more than 16 chars just add an array to the list using your method that returns an array.

Array with loops Java

I want to print put the elements in an array that only occur twice. So if, for example, number 2 occurs 3 or 4 times, it should not be printed. The code I've written so far is below.
The issue in my code is with the loop. For example, for the number 2, since j=i+1 is the initialization condition, the inner loop won't read the elements before the jth location- since there is a 2 at index 6, it won't count the 2s before it, making the required condition true and displaying the 2. Is there a way to fix this?
public class Problem2 {
public static void exactlytwice(int[] x) {
int count, j;
for (int i = 0; i < x.length; i++) {
count = 0;
for (j = i + 1; j < x.length; j++) {
if (x[i] == x[j])
count++;
}
if (count == 1) System.out.print(x[i] + " ");
}
}
public static void main(String[] args) {
int[] x = new int[15];
x[0] = 2;
x[1] = 2;
x[2] = 2;
x[3] = 13;
x[4] = 44;
x[5] = 44;
x[6] = 2;
x[7] = 63;
x[8] = 63;
x[9] = 90;
x[10] = 1;
x[11] = 2;
x[12] = 150;
x[13] = 150;
x[14] = 180;
exactlytwice(x);
}
}
aside from the issue you wrote, the bigger problem I see with your code is that its inefficient. You are doing a loop inside a loop here, which is very slow (o(n^2)).
My suggestion is to keep a map of numbers->count, and then only take the ones that appear only twice in the map:
public static void exactlytwice(int[] x) {
Map<Integer, Integer> counter = new HashMap<>();
for (int i = 0; i < x.length; i++) {
if (counter.contains(i)) {
counter.put(i,1);
} else {
counter.put(i,counter.get(i)+1);
}
}
for (Integer i : counter.keyset()) {
if (counter.get(i) == 2) {
System.out.println(i);
}
}
}
Think about maintaining a seperate array/list which keeps track of all the elements that has been counted/printed by which you could just skip the same number that shows again down the array.
Or you could sort the array and then perform the whole logic to check for duplicates.
Just for completeness, there is a solution without extra-map. It's still O(n^2), but uses no extra memory. And It uses kind of fun idea.
First, we only need to output first occurence of a number, every other one is not relevant, because we either have more than 2 of them, or we've already output the first one.
Second, we can then indeed continue, from i+1 element, because at this point, there are no elements equal to ith, that are earlier in array.
public static void exactlytwice(int[] x) {
int count, j;
TOP:
for (int i = 0; i < x.length; i++) {
count = 0;
for (j = 0; j < i; j++) {
if (x[j] == x[i])
// had this number earlier, so go to the next one.
continue TOP;
}
for (j = i+1; j < x.length; j++) {
if (i != j && x[i] == x[j])
count++;
}
if (count == 1) System.out.print(x[i] + " ");
}
}
In addition to the answers provided, there are two more ways you could go about this:
If array modification is permitted, change elements already encountered to a dummy value, and skip the value if encountered. This reduces the time complexity to O(n) from O(n^2), but destroys the original array. Of course, this assumes that the acceptable integers are restricted to a certain set (thanks to #Dzmitry Paulenka for reminding me that I hadn't stated this explicitly). To keep the array, you could make a copy (although then the space complexity becomes O(n) ).
If any integer is acceptable, then create an encountered boolean array, all intialized to false. Change the locations of elements encountered in the original array to true in the encountered boolean array, and if the value is already true, it can be skipped. Again, time complexity O(n), but O(n) space complexity, and unlike in the second method of 1., does not require the permissible range of numbers (ints) to be restricted.
Alternately, simply make the initialization of j as j=0, and then ensure that only those numbers which don't have that number appearing before them are printed, i.e., that the number is printed only if it occurs at j>=i (thanks to #Nir Levy for pointing the j>=i requirement out). This is (slightly) more inefficient than the code already written, but the time complexity remains the same O(n^2).
With Java 8 you can achieve this using streams like this :
public static void main(String[] args)
{
List<Integer> list = Stream.of(12,1,3,4,2,3,7,6,7,3,1,8,4,12,33,45,78,36,8)
.collect(Collectors.groupingBy(x->x, Collectors.summingInt(x->1)))
.entrySet().stream().filter(x->x.getValue()==2)
.collect(ArrayList<Integer>::new,(x,y)->x.add(y.getKey()),ArrayList<Integer>::addAll);
System.out.println(list);
}
The result is :
[1, 4, 7, 8, 12]
Code:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class Writer {
private int counter;
private Random generator = new Random();
private List<Integer> data = new ArrayList<Integer>();
private Map<Integer,Integer> map = new HashMap<Integer,Integer>();
public Writer(int n){
populate(n);
}
private final void populate(int n){
for(int i = 0; i != n; i++){
data.add(generator.nextInt(10));
}
}
private final void reset(){
this.counter = 0;
}
public final void occurence(){
for(int dp : data){
for(int i = 0; i < data.size(); i++){
if(dp == data.get(i)){
counter += 1;
}
}
map.put(dp, counter);
reset();
}
}
public final void filter(int d){
for(int key : map.keySet()){
if(map.get(key) == d){
System.out.println("Key: " + key + " Value: " + map.get(key));
}
}
}
public void rawData(){
System.out.println(data.toString());
}
public void output(){
System.out.println(map.toString());
}
Initiate:
// Create instance of Writer class and generate '100' random numbers
Writer writer = new Writer(100);
// Output raw data
writer.rawData();
// Process data
writer.occurence();
// Filter numbers with occurence '10'
writer.filter(10);
// Output processed data
writer.output();
Output (from from calling filter(10)):
Key: 3 Value: 10
Key: 8 Value: 10

Finding plateau in Java Array

I having a really hard time finding a plateau within an array. What I'm looking for is length and location of the longest sequence of equal values where the numbers on both sides are smaller. Now I know there could be two or more valid plateaus with same length ideally I would like to print the plateau with a higher value.
I have created an array[40] and a Random obj. To fill the array, once I have filled it I know I will need a loop to check the indexes. But thats where the confusion comes in. I have tried using a for loop to find the plateau but my results would just increase the value stored within the index.
Any points in the right direction I would greatly appreciate it.
import java.util.Random;
public class Plateau {
public static void main(String[]args)
{
int[] array1 = new int[40];
Random genrator = new Random();
for (int i = 0; i < array1.length; i++)
{
array1[i] = genrator.nextInt(21 - 1);
}
for(int i = 0; i < array1.length; i++)
{
System.out.print(array1[i] + " ");
}
System.out.println("\n");
for (int i = 0; i < array1.length; i++)
{
if (array1[i] < array1[i] + 1)
{
System.out.println(array1[i] + " ");
}
}
}
}
In pseudo-code:
V value=first value
P position=1
L length=0
Scan the values from position Q=2
Compare current value C to V
If C is less than V
if this sequence Q-P is longer than L
save length as L
save P as location R
update V and P to current value
If C is greater than V
update V and P to current value
I don't have a compiler for pseudo-code so it might not be exactly right, but it should be a start.

Simulating deadlock using multi-dimensional array

I am attempting to code a deadlock detection algorithm. I must use a 7x7 array filled with w's, x's, and n's. w = waiting for resource, x = exclusively holding a resource, and n = no need for the resource. The rows represent jobs or processes and the columns represent resources. I will give a test case array:
String [][] grid = {{"w","n","x","x","x","n","n"},
{"x","w","n","n","n","x","n"},
{"n","x","w","n","n","n","n"},
{"n","n","n","n","n","n","x"},
{"n","n","n","n","n","n","n"},
{"n","n","w","n","n","n","w"},
{"w","w","w","w","w","w","w"}};
As you can see the deadlock is among Row 0, 1 and 2. R0 is waiting forC0 (resource 1), but R1 is holding it. R1 is waiting for C1 (resource 2) but R2 is holding it. R2 is waiting for C2 (resource 3), but R0 is holding it. Visually, it is a cycle.
My algorithm searches the rows for w's and the columns for x's and places them in a single dimensional array. That part works. The array should read w x w x w x...until the end.
To check if we have completed a cycle I keep track of the index of the rows where w's and x's are found and place them into another single dimensional array. So in this example, the first array would read w x w x w x... and the the second array would read 0 1 1 2 2 0...
Once the single dimensional arrays reach a size of 4 (determined by count variable) I would check the first index (array[0]) and the last index (array[count-1]). If array[0] is 'w' and array[count-1] is 'x' and if the row indexes are equal then a deadlock is detected.
My algorithm works on paper, but somehow my math is wrong with my second array (WHI) The indexes print out correctly the first time ( 0 1 1 2 2 0...) but if I print out WHI[0] (which should always be 0) it gives me 1 2 5 5 6 6 6 6 ...
public void printSingleArrays()
{
String [] WH = new String[14];
int [] WHI = new int[14];
int count = 0;
for (int a = 0; a < WH.length && a < WHI.length; a += 2)
for (int i = 0; i < array.length ; i++)
for (int j = 0; j < array[i].length ; j++)
{
if (array[i][j].equals("w"))
{
WH[a] = array[i][j];
WHI[a] = i;
count++;
System.out.print(WH[a] + " ");
System.out.println(WHI[a] + " ");
for (int k = 0; k < array.length; k++)
{
if (array[k][j].equals("x"))
{
WH[a+1] = array[k][j];
WHI[a+1] = k;
System.out.print(WH[a+1] + " ");
System.out.print(WHI[a+1] + " ");
count++;
if (count >= 4)
{
System.out.print("Count is: " + count); // used for debugging
System.out.print(", First letter is: " + WH[0]);
System.out.println(", Index is: " + WHI[0]);
}
else
System.out.println();
}
}
}
}
for (int m = 0; m < WH.length; m++)
{
System.out.print(WH[m] + " ");
}
System.out.println();
for (int n = 0; n < WH.length; n++)
{
System.out.print(WHI[n] + " ");
}
}
Obviously, constructors and a client class are needed. I would just like to know how my array WHI changes when I print out WHI[0]?? Let me know if you need more resources or instruction the the problem!
Here is example of solving problem using graph.
First construct graph by iterating through grid
First iterating through all rows(j) for each column(i), it will find acquirer node who has "x" and waiting nodes who has "w".
Then add acquirer node into list of acquires of each waiting nodes.
Now we have graph ready, just find cycle by iterating over graph by dfs and see if node has been visited, if any of node was visited previously then it's a cycle, it means it is a deadlock.
Now in this case, graph can be disconnected graph means all node may not reach one or more node. In that case we may need to keep track of which nodes have been visited while detecting cycle and look for cycle for the node which was not visited.
Here is the code:
package example;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class DeadlockDetection {
static String [][] grid = {{"w","n","x","x","x","n","n"},
{"x","w","n","n","n","x","n"},
{"n","x","w","n","n","n","n"},
{"n","n","n","n","n","n","x"},
{"n","n","n","n","n","n","n"},
{"n","n","w","n","n","n","w"},
{"w","w","w","w","w","w","w"}};
public static void main(String[] args) {
System.out.println(isDeadlock());
}
public static class Node{
int id;
List<Node> acquirerNodes = new ArrayList<Node>();
public Node(int id){
this.id=id;
}
}
public static boolean isDeadlock(){
List<Node> nodes = new ArrayList<Node>();
//Construct Graph
for(int i=0; i< grid.length; i++){
nodes.add(new Node(i));
}
for(int i=0; i<grid.length; i++){
List<Node> waitingNodes = new ArrayList<Node>();
Node acquirer = null;
for(int j=0; j<grid.length; j++){
if(grid[j][i].equals("w") ){
waitingNodes.add(nodes.get(i));
} else if(grid[j][i].equals("x") ){
acquirer = nodes.get(i);
}
if(acquirer != null)
for(Node n: waitingNodes)
n.acquirerNodes.add(acquirer);
}
}
//In case of non-strongly disconnected graph, we may need to traverse through all nodes.
HashSet<Node> nodesFoundInGraph = new HashSet<Node>();
for(int i=0; i< grid.length; i++){
if(!nodesFoundInGraph.contains(nodes.get(i))){
HashSet<Node> visited = new HashSet<Node>();
if(isCycle(nodes.get(i), visited))
return true;
nodesFoundInGraph.addAll(visited);
}
}
return false;
}
public static boolean isCycle(Node node, Set<Node> visited){
if(visited.contains(node)){
return true;
}
visited.add(node);
for(Node n: node.acquirerNodes){
if(isCycle(n, visited)){
return true;
}
}
return false;
}
}

Adding elements to last array position

Im trying to add an element to an array at its last position in Java, but I am not able to...
Or rather, I don't know how to. This is the code at the moment:
String[] values = split(line, ",");
int[][] coordinates = new int[2][values/2];
for(int i = 0; i < values.length; i++) {
if(i % 2 == 0) { //THIS IS EVEN VALUES AND 0
coordinates[0][coordinates[0].length] = values[i];
} else { //THIS IS ODD VALUE
coordinates[1][coordinates[1].length] = values[i];
}
}
EDITED VERSION:
String[] values = split(line, ",");
int[][] coordinates = new int[2][values/2];
int x_pos = 0;
int y_post = 0;
for(int i = 0; i < values.length; i++) {
if(i % 2 == 0) { //THIS IS EVEN VALUES AND 0
coordinates[0][x_pos] = values[i];
x_pos++;
} else { //THIS IS ODD VALUE
coordinates[1][y_pos] = values[i];
y_pos++;
}
}
values is being read from a CSV file. My code is I believe wrong, since it will try to add the values always at the maximum array size for coordinates[] in both cases.
How would I go around adding them at the last set position?
Thanks!
/e: Would the EDITED VERSION be correct?
Your original code has two problems:
it addresses the array badly, the las element in a Java array is at position length-1, and this would result in an ArrayOutOfBoundsException
even if you'd correct it by subtracting 1, you would always overwrite the last element only, as the length of a Java array is not related to how many elements it contains, but how many elements it was initialised to contain.
Instead of:
coordinates[0][coordinates[0].length] = values[i];
You could use:
coordinates[0][(int)Math.round(i/2.0)] = values[i];
(and of course, same with coordinates[1]...)
EDIT
This is ugly of course:
(int)Math.round(i/2.0)
but the solution I'd use is far less easy to understand:
i>>1
This is a right shift operator, exactly the kind of thing needed here, and is quicker than every other approach...
Conclusion: this is to be used in a live scenario:
Use
coordinates[0][i>>1] = values[i];
EDIT2
One learns new things every day...
This is just as good, maybe a bit slower.
coordinates[0][i/2] = values[i];
If you know you'll definitely have an even number of values you can do
for(int i = 0; i < values.length / 2; i++) {
coordinates[0][i] = values[2*i];
coordinates[1][i] = values[2*i + 1];
}
You have to store the last position somewhere. .length gives you the size of the array.
The position in the array will always be the half of i (since you put half of the elements in one array and the other half in the other).
String[] values = split(line, ",");
int[][] coordinates = new int[2][values/2];
for(int i = 0; i < values.length; i++) {
if(i % 2 == 0) { //THIS IS EVEN VALUES AND 0
coordinates[0][ i / 2] = values[i];
} else { //THIS IS ODD VALUE
coordinates[1][ i / 2 + 1 ] = values[i];
}
}
The array index for java is from "0" to "array length - 1".
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
Each item in an array is called an element, and each element is accessed by its numerical index. As shown in the above illustration, numbering begins with 0. The 9th element, for example, would therefore be accessed at index 8.
why not:
String[] values = split(line, ",");
int[][] coordinates = new int[2][values/2];
for(int i = 0; i < values.length; i+=2) {
coordinates[0][i/2] = values[i];
coordinates[1][i/2] = values[i+1];
}

Categories

Resources