Java – Working with 2 dimensional array and constructor (Beginner) - java

This post is going to be really long, but I would be so glad if the community can help me.
This is a question from a former class test. I have to expect a similar one this time and I'm currently stuck. I'm new to Java and its concepts.
The result of the test should look like this:
The result
I'm facing multiple problems at once. I will try to be as specific as I can. First I will explain the task, which has given conditions that can't be changed.
The task
Create an array field with 2 dimensions. The field should work with various sizes. Besides the size, the array field should contain the following pattern(see picture).
1.) Create an constructor that creates a rectangle array field from the parameter passed in, with to extra conditions.
1.1) If the parameter is less than 5, the field should be forced to appear as a 5/5 field.
1.2) If the paramter is more than 5 it should always appear as an n/n array.
public class Pattern {
char[][] field;
public Pattern(int n) {
// Here goes my code for creating the field
}
2.) Write a method that fills the constructor.
public void fillArray() {
// Here goes my code.
}
My approach so far
public Pattern(int n) {
field = new char[n][n];
int i, j;
if (field.length < 5) {
for (i = 1; i <= 5; i++) {
for (j = 1; j <= 5; j++) {
// ? what to do with the array here?
}
System.out.println();
}
}
public void fillArray() {
// no fu**ing idea...
}
public static void main (String[]args){
Pattern cross = new Pattern(2);
cross.fillArray();
System.out.println(cross);
}
Questions
1.) What value should be returned in the constructor?
2.) How can I access the object in the method and set a for loop, that gets the predefined field size? Should I use this ?
I'm sorry for my bad understanding on how to pass array information and execute these correctly.

public class Pattern {
private final int size;
private final char[][] field;
public Pattern(int n) {
size = Math.max(n, 5);
field = new char[size][size];
}
public void fillArray() {
for (int row = 0, i = size - 1; row < size; row++, i--) {
for (int col = 0, j = size - 1; col < size; col++, j--) {
if (row == col || row == j)
field[row][col] = '*';
else if (col > row)
field[row][col] = col < i ? '1' : '2';
else
field[row][col] = col > i ? '3' : '4';
}
}
}
public void print() {
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++)
System.out.print(field[row][col] == '\0' ? ' ' : field[row][col]);
System.out.println();
}
}
public static void main(String... args) {
Pattern cross = new Pattern(2);
cross.fillArray();
cross.print();
}
}

You are putting what should be in fillArray in the constructor. The constructor should just be this:
public Pattern(int n) {
if (n < 5) {
field = new char[5][5];
} else {
field = new char[n][n];
}
}
And the two for loops should be in the fillArray method:
public void fillArray() {
// you should loop until field.length and field[x].length
for (int x = 0; x < field.length; x++) {
for (int y = 0; y < field[x].length; y++) {
// ...
}
}
}
Try to write your own logic of how to fill in the array.
If you are stuck, here is my solution:
for (int x = 0 ; x < field.length ; x++) {
for (int y = 0 ; y < field[x].length ; y++) {
/*
The '1' area can be represented by these inequalities:
x - y < 0
x + y < array.length - 1
The '2' area can be represented by these inequalities:
x - y < 0
x + y > array.length - 1
The '3' area can be represented by these inequalities:
x - y > 0
x + y > array.length - 1
The '4' area can be represented by these inequalities:
x - y > 0
x + y < array.length - 1
Everywhere that does not satisfy any of the inequalities are *s
*/
int xMinusY = x - y;
int xPlusY = x + y;
if (xMinusY < 0 && xPlusY < field.length - 1) {
field[x][y] = '1';
} else if (xMinusY < 0 && xPlusY > field.length - 1) {
field[x][y] = '2';
} else if (xMinusY > 0 && xPlusY > field.length - 1) {
field[x][y] = '3';
} else if (xMinusY > 0 && xPlusY < field.length - 1) {
field[x][y] = '4';
} else {
field[x][y] = '*';
}
}
}
// ...
// printing the array out:
for (int x = 0 ; x < field.length ; x++) {
for (int y = 0 ; y < field.length ; y++) {
System.out.print(field[x][y]);
}
System.out.println();
}

Answers to your questions:
Constructors does not return anything.
You don't need to use "this" since the 2-dimensional array is a field which can be accessed anywhere in the class Pattern. If you want to access the size of the array, you can use field.length.
Before you fill the array, you should first check if n is less than 5 (if it is, it should be set to 5). This is done in the constructor. Then you create the array.
After that, you have the for loops in which you have to figure out how to create the pattern. This should be done in the fillArray method.

Okay, so here is the solution. To get this kind of patterns draw it first on paper, then just write the columns and rows and search for the Pattern.
The only way you can learn this is by practice.
A constructor is like a method but does not have a return and uses the name of the Class.
The constructor will be always called when you instanciate a new Object of that class.
Example:
Pattern p = new Pattern(3);
Leave the constructor for the things you will need to do when you create an Object of that class. In your case decide the size of your Pattern.
Example:
public Pattern(int fS) { //fS = fieldSize
if (fS < 5)
fS = 5;
field = new char[fS][fS];
}
Then you have the methods, once an Object is created you can use all the methods from his Instance. In your case you will have a method called "fillArray".
Solution:
public void fillArray() {
int fS = field.length;
char c = ' ';
int len = fS - 1;
for (int row = 0; row < fS; row++)
for (int col = 0; col < fS; col++) {
if (row == col || row + col == len) c = '*';// This will make the asterisc cross
if (row < col && row < len - col) c = '1'; //This will do the 1 part
if (row < col && row > len - col) c = '2'; //This will do the 2 part
if (row > col && row > len - col) c = '3';//This will do the 3 part
if (row > col && row < len - col) c = '4';//This will do the 4 part
field[row][col] = c;
}
}
Remember:
In this case your Array will be not filled until you call the method fillArray()
Example:
Pattern p = new Pattern(7);
p.fillArray();
To print your Pattern I recommend you use the toString() method. You will need to Override it.
How to:
#Override //Important
public String toString() {
StringBuilder s = new StringBuilder();
for (char[] row : field) {
for (char col : row)
s.append("\t").append(col);
s.append("\n");
}
return s.toString();
}
Use the "#Override" tag to see if you did any typo writing the mehod toString. Now to print your pattern use:
Pattern p = new Pattern(7);
p.fillArray();
System.out.println(p); //This line
PD: Sorry if I did any grammar mistake my mother language is not english. Hope it helps.

Related

Sorting 2D String Array with BUBBLESORT in java

Similar questions have been asked but never about 2D String Arrays, therefore after trying for a long time I couldn't find what I wanted. I'm trying to sort a 2D String Array in java using BubbleSort.
As input, I receive a two-dimensional array (a table) of Strings and the index of the “column” you should sort. I should sort the rows by the values in the indicated column.
You can see the first index as a row index, and the second index as a column index. For example, the following Java array and table correspond with each other:
String[][] table = {
{"a", "b"},
{"c", "d"}
};
-
0 1
+---+---+
0 | a | b |
+---+---+
1 | c | d |
+---+---+
To continue on this example, table[0][1] will yield the value "b", since it’s the item in row 0 and column 1.
IMPORTANT: I am not allowed to use any sorting algorithm from the Java library, for example Arrays.sort.
This is what I've tried so far:
class Solution {
public static void stableSort(String[][] table, int column) {
int i;
int j;
String temp = null;
for (i = 0; i < table.length - 1; i++) {
for (j = 0; j < table.length - 1 - i; j++) {
if (table[i][j].compareTo(table[i][j + 1]) > 0) {
temp = table[i][j];
table[i][j] = table[i][j + 1];
table[i][j + 1] = temp;
}
}
}
}
}
I get an Index out of Bounds error and also it is not working as the test expects a different result in table[0][0]
Thanks for your help.
public static String[][] stableSort(String[][] table, int column) {
int i=0,j=0;
String[] temp = null;
boolean swap=true;
while(swap)
for (i = 0; i < table.length - 1; i++) {
swap=false;
if(table[i][column].compareTo(table[i+1][column]) > 0){
temp = table[i];
table[i] = table[i+1];
table[i+1]=temp;
swap=true;
}
}
return table;
}
It keeps applying the bubblesort until no more swaps are performed. At that point,the condition while(swap) is no longer satisfied and the method returns.
Tried in a main and it works (if I understand what you meant):
public static void main(String[] args) {
String[][] table = {
{"z", "b", "v"},
{"s", "w", "a"},
{"r", "c", "h"}
};
table = stableSort(table,1);
for(int i = 0; i < table.length; i++){
for(int j = 0; j < table[0].length; j++){
System.out.printf("%5s ", table[i][j]);
}
System.out.println();
}
}
this outputs:
z b v
r c h
s w a
to start, make it a 1d array
or at least 1d indexable
much easier
formula:
x = (int)index/(int)rows
y = index % rows
with that you can use 1 variable index
and index a 2d array
and this is a bubblesort
def sort(self):
for passnum in range(len(self.array)-1,0,-1):
for i in range(passnum):
if self.array[i]>self.array[i+1]:
temp = self.array[i]
self.array[i] = self.array[i+1]
self.array[i+1] = temp
EDIT: Working and no errors
If I take your exact sort but add a if statement for the switching of rows, add an exterior loop to run through the 2D array the length times the width and change the for loop control to '<=' then I get the following
for(int z = 0; z < table.length * table.length; z++) // exterior for loop to run through the loop multiple times
{
for (i = 0; i <= table.length - 1; i++) {
for (j = 0; j <= table.length - 1; j++) {
if(j == table.length -1 && i == table.length-1) // If we are at the end then we can continue either to the next iteration or to the end of program
continue;
if(j == table.length -1) // If you are ate the end of the row compare to the next row
{
if (table[i][j].compareTo(table[i+1][0]) > 0) {
temp = table[i][j];
table[i][j] = table[i+1][0];
table[i+1][0] = temp;
}
}
else if (table[i][j].compareTo(table[i][j + 1]) > 0) {
temp = table[i][j];
table[i][j] = table[i][j + 1];
table[i][j + 1] = temp;
}
}
}
}
I saw what you were trying to do by minimizing the number of checks when you put
table.length - 1 - i
That is good for efficiency but first attempt to get the sorting working. then trim it down to preform better.
Also I don't have a compiler in-front of me so code could have some errors
My working solution:
import java.util.Arrays;
public class MySolution {
public static void stableSort(String[][] table, int column) {
String[] temp = null;
int rows = table.length;
for (int i = 0; i < rows; i++) {
for (int j = 1; j < (rows - i); j++) {
if (table[j - 1][column].compareTo(table[j][column]) > 0) {
temp = table[j - 1];
table[j - 1] = table[j];
table[j] = temp;
}
}
}
}
public static void main(String[] args) {
String[][] table = { { "c", "d" }, { "a", "b" } };
printTable(table);
stableSort(table, 1);
printTable(table);
}
private static void printTable(String[][] table) {
System.out.println("table:");
for (int i = 0; i < table.length; i++) {
System.out.println(Arrays.toString(table[i]));
}
}
}
some notes for you:
use meaningful names (rows is easier to understand than table.length)
bubble sort loops were a bit off, there are plenty of examples of how to do it online
as mentioned, you should start by doing it for 1d array and then "generalize" it
one big issue you had: using j (which should be the index of the row to compare to) as the column (and ignoring column)
another big issue is only substituting the element (instead of the rows)
I hope this helps you!
EDIT: I just noticed you've also switched between row and column in your code (in your explanation the first index denotes the row, in your code it seems like the opposite is correct)

How would I change an object's value when calling a static method from a different class?

In this practice problem, a square matrix filled with 0s and 1s is instantiated. You can flip over values (ex: 0 becomes 1 and 1 becomes 0) in a rectangle of any size, as long as the topmost corner of the rectangle is [0, 0] in the matrix. The end goal is to find how many times you must flip values over to get all the values of the matrix as 0.
If you want a longer explanation, go to http://usaco.org/index.php?page=viewproblem2&cpid=689, but that's the basic outline.
This is my code:
import java.io.*;
import java.util.*;
public class CowTip {
static int[][] mat;
public static void main( String[] args) throws IOException, InterruptedException{
Scanner scan = new Scanner(new File("cowtip.in"));
int n = scan.nextInt();
scan.nextLine();
mat = new int[n][n];
for (int x = 0; x < n; x++) {
String str = scan.nextLine();
for (int y = 0; y < n; y++) {
mat[x][y] = Integer.parseInt(str.substring(y,y+1));
}
}
Checker c = new Checker(n-1, n-1);
int count = 0;
while (true) {
c.check();
for (int x = 0; x <= c.row; x++) {
for (int y = 0; y <= c.col; y++) {
if (mat[x][y] == 0) {
mat[x][y] = 1;
}
else if (mat[x][y] == 1) {
mat[x][y] = 0;
}
}
}
count++;
c.check();
if (c.row == -1 && c.col == -1) {
break;
}
}
System.out.println(count);
}
static class Checker {
int row;
int col;
public Checker(int r, int c) {
row = r;
col = c;
}
public Checker check() {
Checker check = new Checker(-1, -1);
for (int x = mat.length-1; x >= 0; x--) {
for (int y = mat[x].length-1; y >= 0; y--) {
if (mat[x][y] == 1) {
check = new Checker(x, y);
break;
}
}
if (check.row != -1 && check.col != -1) {
break;
}
}
return check;
}
}
}
and this is the input file (named cowtip.in) :
3
001
111
111
I've excluded my current debugging code, but the problem is that the row and col values inside my check() method are the correct values, but whenever I call the check() method in my main, the values reverts back to the default and doesn't give me the correct answer, which in turn makes the loop infinite.
Any ideas on how to fix this?
EDIT: I've figured it out, but thanks guys! It was actually extremely simple (c = c.ckeck() instead of c.check()) and honestly, I was pretty frustrated considering I spent around two hours trying to debug this...
Replace c.check() with c = c.check();

Replacing values of a two dimensional array

I have a given two dimensional array of doubles, called imgMatrix and I'm trying to make a new two dimensional array of integers either 1 or 0, depending on the values of the doubles in imgMatrix (value <= 0.5 makes a 0 in the new array; value > 0.5 makes a 1 in the new array).
Here's the code I have so far:
int[][] newMatrix = new int[imgMatrix.length][];
for (a=0; a <= imgMatrix.length; a++) {
for (b=0; b <= imgMatrix[a].length; b++) {
for (c=0; c <= imgMatrix[a].length; c++) {
if (imgMatrix[a][c] <= 0) {
newMatrix[a][c] = 0;
}
else {
newMatrix[a][c] = 1;
}
}
}
}
Obviously something is wrong. Can anybody help me correct this?
do following changes into your code,
int[][] newMatrix = new int[imgMatrix.length][];
for (int a=0; a < imgMatrix.length; a++) { // remove = from older code
newMatrix[a] = new int[imgMatrix[a].length];
for (int b=0; b < imgMatrix[a].length; b++) { // remove = from older code
//remove : for (c=0; c <= imgMatrix[a].length; c++) {
if (imgMatrix[a][b] <= 0.5) {
newMatrix[a][b] = 0;
}
else {
newMatrix[a][b] = 1;
}
// remove : }
}
}

Multi-dimensional array, how can I check all adjacent tiles that are IN bounds to certain cells?

I've created a 12x12 grid, and within this grid I have created 'infected' tiles, when one infected tile is surrounded by other infected tiles, the surrounded cell becomes a diseased tile. I was wondering if there was a nice way of checking adjacent, in bounds cells for their value?
public static void diseaseTiles() {
int i, j;
for(i = 0; i < 12; i++) {
for(j = 0; j < 12; j++) {
if(myGrid[i][j] == 'I'){
int left, right, up, down;
if(i == 0) {
left = 1;
}
if(i == 11) {
right = 1;
}
if(j == 0) {
up = 1;
}
if(j == 11) {
down = 1;
}
//this is where I've gotten stuck
//I was going to use the above int's to determine
//whether or not the adjacent tile in that direction
//should be checked (they're the border of the grid)
}
}
}
}
You can check if a cell is infected by taking advantage of short-circuited evaluation:
boolean leftInfected = (i!=0) && myGrid[i-1][j]=='I';
boolean rightInfected = (i!=11) && myGrid[i+1][j]=='I';
boolean topInfected = (j!=0) && myGrid[i][j-1]=='I';
boolean bottomInfected = (j!=11) && myGrid[i][j+1]=='I';
After that, you could check if all four are infected:
if (leftInfected && rightInfected && topInfected && bottomInfected) {
myGrid[i][j] = 'D';
}
You might consider padding your array with a boundary one cell deep around each edge, so your 12x12 would become a 14x14. Make each cell in the boundary infected. You can then loop over the interior cells (ie rows 1:12, cols 1:12) without having to check that the cell is at the edge all the time.
I believe a better option is to define a helper array that defines the valid neighbors and iterate using it. Advantage of my approach is that it makes it very easy to change which are the valid neighbors(say you want to have 8 neighbors allowing to go by diagonal instead of only 4):
int moves[][] = {{-1,0}, {0, -1}, {1, 0}, {0, 1} };
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
for (int l = 0; l < 4 /* moves.length */; ++l) {
int ti = i + move[l][0];
int tj = j + move[l][1];
if (ti <= 0 || ti >= 12 || tj < 0 || tj >= 12) {
continue;
}
// cell (ti, tj) is valid neighbor do something with it.
}
}
}

Sudoku Checker 2d array Java

So im having a bit of problem with my code.. It's suppose to cross check rows and columns for same integers.
this is what i have so far.. but when i run it, it only seems to check the first integer only. (for example the first line of the sudoku board reads. 1 2 2 2 2 2 2 2 2 2) it wont detect the obvious multiple 2's but if i change the input to 1 1 2 2 2 2 2 2 2 the error will come up of multiple 1's in this case. the multiple any suggestions to tweak my loops to make it go through the columns?
public static void validate(final int[][] sudokuBoard) {
int width = sudokuBoard[0].length;
int depth = sudokuBoard.length;
for (int i = 0; i < width; i++) {
int j = i;
int reference = sudokuBoard[i][j];
while (true) {
if ((j >= width) || (j >= depth)) {
break;
}
else if (i == j){
// do nothing
}
else if (j < width) {
int current = sudokuBoard[i][j];
if (current == reference) {
System.out.print("Invalid entry found (width)" + "\n");
System.out.print(current + "\n");
// invalid entry found do something
}
} else if (j < depth) {
// note reversed indexes
int current = sudokuBoard[j][i];
if (current == reference) {
System.out.print("Invalid entry found (depth)" + "\n");
System.out.print(current + "\n");
// invalid entry found do something
}
}
j++;
}
Your code is more complex than it should be. Why put everything in one single function when you could split in several different functions?
public static void Validate(final int[][] sudokuBoard)
{
int width = sudokuBoard[0].length;
int depth = sudokuBoard.length;
for(int i = 0; i < width; i++)
if(!IsValidRow(sudokuBoard, i, width))
{
//Do something - The row has repetitions
}
for(int j = 0; j < height; j++)
if(!IsValidColumn(sudokuBoard, j, width))
{
//Do something - The columns has repetitions
}
}
static bool IsValidRow(int[][] sudokuBoard, int referenceRow, int width)
{
//Compare each value in the row to each other
for(int i = 0; i < width; i++)
{
for(int j = i + 1; j < width; j++)
{
if(sudokuBoard[referenceRow][i] == sudokuBoard[referenceRow][j])
return false
}
}
return true;
}
static bool IsValidColumn(int[][] sudokuBoard, int referenceColumn, int height)
{
//Compare each value in the column to each other
for(int i = 0; i < height; i++)
{
for(int j = i + 1; j < height; j++)
{
if(sudokuBoard[i][referenceColumn] == sudokuBoard[j][referenceColumn])
return false
}
}
return true;
}
That way, your code is much more easily maintainable/readable. This code above hasn't been tested, but it should be about right.
I suggest debugging this code step by step to really understand what's going on, if that's not clear for you.
Given the constraints of sudoku (a row of n cells must contain the numbers 1-n only) you don't need an order n^2 search (per row or column), you can do it order n by keeping a bit array indicating which numbers you've seen. Here's the pseudo-code for checking rows, do the same for columns:
for i in 0 to depth-1 // rows
boolean seen[] = new seen[width];
for j in 0 to width-1 // columns
if seen[board[i][j]-1] == true
duplicate number
else
seen[board[i][j]-1] = true
I would break the functionality into smaller boolean checks. This way, you can validate row by row, column by column, and square by square. For instance
private boolean isValidRow(int[] row) {
// Code here to check for valid row (ie, check for duplicate numbers)
}
private boolean isValidColumn(int[] column) {
// Code here to check for valid column
}
private boolean isValidSquare(int[][] square) {
// Code here to check for valid square
}
Note that rows and columns only need to be passed a 1 dimensional array. Squares are a 2 dimensional array as you need to check a 3x3 area. You can also treat these methods as static as their functionality is independent of the Sudoku board instance.
Edit: A suggestion on row/column/square validation is to use a HashSet. Sets can only have 1 element of a certain value, so you can add elements and look for a failure. For example:
HashSet<Integer> hs = new HashSet<Integer>();
for(int i = 0; i < 9; i++) {
if(!hs.add(integerArray[i])) // HashSet.add returns 'false' if the add fails
// (ie, if the element exists)
return false;
}
return true;

Categories