First post here, thanks in advance for any help.
I have made a 10*10 grid in Java and am trying to get the row numbers to appear on the left side of the grid, after many attempts at different print formats and options I am now here for a little help. Any pointers will be greatly appreciated.
public class ArrayTest {
public final static int SIZE =10;
final static char[][] GRID = new char[SIZE][SIZE];
public static void main(String[] args){
setGrid();
printGrid();
}
public static void setGrid(){
for( int row = 0; row< SIZE;row++){
for(int column = 0; column<SIZE; column++){
GRID[row][column]= ' ';
}
}
}
public static void printGrid(){
System.out.println(" 10 x 10 Grid");
System.out.println(" 0 1 2 3 4 5 6 7 8 9");
System.out.println(" +---+---+---+---+---+---+---+---+---+---+");
for(int row = 0; row< SIZE; row++){
for(int column = 0; column<SIZE; column++){
System.out.print(" |" + GRID[row][column] + "");
}
System.out.println(" | " + row );
System.out.println(" +---+---+---+---+---+---+---+---+---+---+");
}
}
}
for(int row = 0; row< SIZE; row++){
System.out.print( " " + row + " | ");
for ( int column = 0; column<SIZE; column++){
... <print column values for this row here>
}
System.out.println("");
}
Don't forget to add extra spaces when you print out the column numbers at the top, to account for the space used up by the row number indicators.
Your algorithm is a good point to start. Anyway I would like to broaden your perspective on extended use-cases and the usage of existing (reliable and customizable) text-based tabular-formatting libraries.
Use this extended solution and optimize
It is based on your approach. I added following features:
customizable grid-size (width, height as parameters)
utility functions: padRight, padLeft, repeatChar
You can further optimize that, for example:
left or right alignment of headers/data
calculation of the maximum cell-space need (max length of grid-data)
Source (minimal Java 8 streaming used)
Find source below or online where you can test & download on Ideone.
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class GridDataToTextTable {
public static final int WIDTH = 10;
public static final int HEIGHT = 10;
public static void main(String[] args) {
System.out.printf("%d x %d Grid%n", WIDTH, HEIGHT);
String[][] generateGrid = generateGrid(WIDTH, HEIGHT);
printGrid(WIDTH, HEIGHT, generateGrid);
}
public static String[][] generateGrid(int width, int height) {
String[][] gridData = new String[height][width];
for (int row = 0; row < height; row++) {
for (int column = 0; column < width; column++) {
gridData[row][column] = " ";
}
}
return gridData;
}
public static String padRight(String s, int n) {
return String.format("%-" + n + "s", s);
}
public static String padLeft(String s, int n) {
return String.format("%" + n + "s", s);
}
public static String repeatChar(char c, int n) {
return IntStream.range(0, n).mapToObj(i -> String.valueOf(c)).collect(Collectors.joining(""));
}
public static void printGrid(int width, int height, String[][] gridData) {
int lengthOfMaxRowNum = String.valueOf(height - 1).length();
// TODO: can be calculated as max length over Strings in gridData
int maxCellWidth = 4;
System.out.print(padRight(" ", lengthOfMaxRowNum));
for (int column = 0; column < width; column++) {
System.out.print(padLeft(String.valueOf(column), maxCellWidth + 1));
}
System.out.println();
printHorizontalLine(width, lengthOfMaxRowNum, maxCellWidth);
System.out.println();
for (int row = 0; row < height; row++) {
// TODO: alignment of headers (col-numbers) could be customizable
System.out.print(padLeft(String.valueOf(row), lengthOfMaxRowNum));
for (int column = 0; column < width; column++) {
// TODO: alignment of cell-data could be customizable
System.out.print("|" + padLeft(gridData[row][column], maxCellWidth));
}
System.out.println("|");
printHorizontalLine(width, lengthOfMaxRowNum, maxCellWidth);
System.out.println();
}
}
private static void printHorizontalLine(int width, int lengthOfMaxRowNum, int maxCellWidth) {
String line = repeatChar('-', maxCellWidth);
System.out.print(padLeft(" ", lengthOfMaxRowNum));
for (int column = 0; column < width; column++) {
System.out.printf("+" + line);
}
System.out.printf("+");
}
}
Use Text-Formatting libraries
To print out data text-based in tabular or grid format see this answer.
Maybe you can use one of following libraries:
Java Text Tables library from iNamik's GitHub project
WAGU data-in-table-view library from thedathoudarya's GitHub project
Related
We all know how useful matrix transposition is, and writing a general algorithm for sequential use is no problem. However, I am having some trouble doing the same for multithreaded purposes, and have only gotten this small case for 4 x 4 to work properly.
My approach is to assign equal parts of a double[][] structure, in this case 2 x 2, to each out of four threads. In this case, that means starting positions of 0,0 & 0,2 & 2,0 & 2,2. This is passed in with "kol" and "rad".
However, I cannot get this to work on larger matrices, so any help would be appreciated. The closest answer to this problem I've found is here: How to to parallelize the matrix transpose?
This is also my inspiration for splitting the double[][] structure into four parts. My (working) 4 x 4 code can be found below, so how can I modify it to work for four threads?
Cheers!
public double[][] transponerMatrise(double[][] matrise, int rad, int
kol, int id)
{
if((id != 2))
{
for (int i = rad; i < n/2 + rad; i++)
{
for (int j = kol+1; j < n/2 + kol; j++)
{
System.out.println("Traad " + id + " bytter " + i + "," + j + " med " + j + "," + i);
System.out.println("Value is " + matrise[i][j] + ", " + matrise[j][i]);
element = matrise[i][j];
matrise[i][j] = matrise[j][i];
matrise[j][i] = element;
}
}
}
else
{
for (int i = rad; i < n/2 + rad-1; i++)
{
for (int j = kol; j < n/2 + kol; j++)
{
System.out.println("Traad " + id + " bytter " + i + "," + j + " med " + j + "," + i);
System.out.println("Value is " + matrise[i][j] + ", " + matrise[j][i]);
element = matrise[i][j];
matrise[i][j] = matrise[j][i];
matrise[j][i] = element;
}
}
}
return matrise;
}
PS: I know the code works properly, because I have a checking method against a working sequential variant.
This is an a priori lost fight against O(N^2) costs-function
If I may turn your attention to a smarter approach, having an almost O(1) ( constant ) cost, the trick would help you start working in a way more promising direction.
May try to add one thin abstraction layer above the high-performance tuned ( cache-lines friendly "raw"-storage of the matrix elements. This abstracted layer will help to access the "raw"-storage ( using indexing-axes, index-striding and slicing tricks - the very same way as HPC FORTRAN libraries have inspired the well-known numpy and it's striding tricks) and this way the .T-method will do nothing expensive ( alike bulldozing N^2 memory locations, swapping there and back ) but simply swap axes-parameters in the abstract layer, responsible for the indirection mapper, taking a few tens of nanoseconds for whatever large matrise[N,N]; where N = 10, 100, 1000, 10000, 100000, 1000000, 10000000+ still a few [ns].
There is nothing faster in doing this or other, more complex, matrix operations and both the FORTRAN and numpy, performance polished, methods are a proof per-se of such observation.
Maybe it could be an simple idea to use a thread to swap a row to col but therefore you need twice the memory for you matrix which could be a problem on huge matrices. also if you have a 6 Core CPU i think there is not much benefit from using 100 thread so my thread pool is very small. And as #user3666197 mentioned its a still a expensive solution - but paralell ;-)
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MatrixTransposition {
public static void main(final String[] args) throws InterruptedException {
final MatrixTransposition transposition = new MatrixTransposition();
final int[][] source = transposition.create(32);
final int[][] transposed = transposition.solve(source);
System.out.println("Compare source and transpositon = " + transposition.compare(source, transposed));
final int[][] result = transposition.solve(transposed);
System.out.println("Compare source and double transpositon = " + transposition.compare(source, result));
transposition.print(source);
transposition.print(transposed);
}
public boolean compare(final int[][] a, final int[][] b) {
for (int r = 0; r < a.length; r++) {
for (int c = 0; c < a[0].length; c++) {
if (a[r][c] != b[r][c]) return false;
}
}
return true;
}
public int[][] create(final int size) {
final int[][] result = new int[size][size];
for (int r = 0; r < size; r++) {
for (int c = 0; c < size; c++) {
result[r][c] = r * size + c;
}
}
return result;
}
public void print(final int[][] input) {
final int size = input.length;
final int maxNr = size * size;
final int digits = new String(maxNr + "").length();
final String cellFormat = "%0" + digits + "d ";
for (int r = 0; r < input.length; r++) {
final int[] row = input[r];
for (final int c : row) {
System.out.print(String.format(cellFormat, c));
}
System.out.println("");
}
System.out.println("");
}
public int[][] solve(final int[][] input) throws InterruptedException {
final int width = input.length;
final int height = input[0].length;
final int[][] result = new int[width][height];
final CountDownLatch latch = new CountDownLatch(width);
for (int r = 0; r < width; r++) {
final int row = r;
threadPool.execute(() -> {
solvePart(result, input, row);
latch.countDown();
});
}
latch.await();
return result;
}
private void solvePart(final int[][] result, final int[][] input, final int r) {
System.out.println("Solve row " + String.format("%02d", r) + " in thread " + Thread.currentThread().getName());
final int[] row = input[r];
for (int c = 0; c < row.length; c++) {
result[c][r] = row[c];
}
}
private final ExecutorService threadPool = Executors.newFixedThreadPool(6);
}
based on the aproach of user3666197 you could do something like that:
public class Matrix {
private class Index {
Index(final int row, final int col) {
super();
this.row = row;
this.col = col;
}
int col;
int row;
}
public Matrix(final int rows, final int cols) {
this.rows = rows;
this.cols = cols;
data = new int[rows][cols];
}
public int get(final int row, final int col) {
return get(getIndex(row, col));
}
public void set(final int row, final int col, final int value) {
set(getIndex(row, col), value);
}
public void transpose() {
transpositioned = !transpositioned;
}
private int get(final Index index) {
return data[index.row][index.col];
}
private Index getIndex(final int row, final int col) {
return transpositioned ? new Index(col, row) : new Index(row, col);
}
private void set(final Index index, final int value) {
data[index.row][index.col] = value;
}
private final int cols;
private final int[][] data;
private final int rows;
private boolean transpositioned;
}
I'm trying to erase every X in a .txt file. When a coordinate is chosen, if it is an X is should be replaced with a 0 then also every X that is touching it (except diagonally) should be replaced until there are no more X's that can be touched. I'm not getting these results with my current code.
I'm getting this error java.lang.ArrayIndexOutOfBoundsException: 9 when I input in 0 for getCoord(grid.length, "row") and 2 for getCoord(grid[0].length, "column") in main().
thank you for your help.
image1.txt
00X000000
0XXXXXXX0
0X00000XX
0X0X000XX
0X00000X0
0XXXXXXX0
XXXX00XX0
000XX0000
eraseImage.java
import java.io.*;
import java.util.StringTokenizer;
/**
* eraseImage.java
*
* Your Name Goes Here!
*
* will dimension and load a 2-dimensional array of Strings
* from a text file. The first line of the file will contain
* the dimensions of the grid. Each additional line will have
* String made up of 'X's and '0's (that's zeros) to represent
* part of an image (X) or a non-image cell(0).
*/
public class eraseImage
{
public static void main(String[] args) throws IOException
{
String[][] grid = load();
display(grid);
do
{
int targetRow = getCoord(grid.length, "row");
int targetCol = getCoord(grid[0].length, "column");
rubOut(grid, targetRow, targetCol);
display(grid);
}
while(again());
}
/**
* Please provide documentation here
*/
public static String[][] load() throws IOException
{
BufferedReader innie = new BufferedReader(new FileReader("/Users/laxgoalie1996/Desktop/image1.txt"));
String str = innie.readLine();
StringTokenizer tokens = new StringTokenizer(str);
int rows = Integer.parseInt(tokens.nextToken());
int cols = Integer.parseInt(tokens.nextToken());
String[][] image = new String[rows][cols];
for(int row = 0; row < rows; row++)
{
str = innie.readLine();
for(int col = 0; col < str.length(); col++)
image[row][col] = str.substring(col, col+1);
System.out.println(str);
}
return image;
}
/**
* Please provide documentation here
*/
public static void display(String[][] g)
{
System.out.println("\nHere is the current image...\n");
for (int row = 0; row < g.length; row++) {
for (int column = 0; column < g[row].length; column++) {
System.out.print(g[row][column] + " ");}
System.out.println();}
System.out.println();
}
/**
* Please provide documentation here
*/
public static void rubOut(String[][] g, int tRow, int tCol)
{
String str = g[tRow][tCol];
System.out.println(str);
if(str.equals("0"))
return;
g[tRow][tCol] = "0";
rubOut(g, tRow, tCol + 1);
rubOut(g, tRow, tCol - 1);
rubOut(g, tRow + 1, tCol);
rubOut(g, tRow - 1, tCol);
return;
}
/**
* Please provide documentation here
*/
public static int getCoord(int max, String prompt)
{
java.util.Scanner scan = new java.util.Scanner(System.in);
System.out.print("Enter the " + prompt + " number (0 to " + (max-1) + ") -> ");
int coord = scan.nextInt();
while(coord < 0 || coord >= max)
{
System.out.print("HEY! The " + prompt + " number needs to be between 0 and " + (max-1) + " -> ");
coord = scan.nextInt();
}
return coord;
}
/**
* Please provide documentation here
*/
public static boolean again()
{
return false;
}
}
You need to add bounds checks to your rubOut function:
public static void rubOut(String[][] g, int tRow, int tCol)
{
if((tRow < 0) || (tRow >= g.length))
return;
if((tCol < 0) || (tCol >= g[tRow].length))
return;
...
}
Even though your initial indices of row = 0 and column = 2 are within bounds, you are going to go out of bounds when you call rubOut(g, tRow - 1, tCol); because tRow will then be -1.
Use this for loop for replace X over 0
public static void main(String [] args){
String[][] str ={{"0","0","X","0","0","0","0","0","0"},
{"0","X","X","X","X","X","X","X","0"},{"0","X","0","0","0","0","0","X","X"},
{"0","X","0","X","0","0","0","X","X"},{"0","X","0","0","0","0","0","X","0"},};
for (int i=0; i<str.length; i++) {
for(int j=0; j<str[i].length; j++){
System.out.print(str[i][j]);
}
System.out.println();
}
System.out.println();
for (int i=0; i<str.length; i++) {
for(int j=0; j<str[0].length; j++){
if(i==j){
str[i][j]="0";
}
System.out.print(str[i][j]);
}
System.out.println();
}
}
This will replace X over 0
I have to write a program that will read a picture and then print out the number of blocks inside it.
I have to read the picture as a binary matrix of the size r × c (number of rows times number of
columns).
The blocks are groups of one or more adjacent elements with the value 1.
Blocks are built exclusively of elements with value 1
Each element with value 1 is a part of some block
Adjacent elements with value 1 belong to the same block.
We only take into account the horizontal and vertical adjacency but not diagonal.
INPUT:
In the first line of the input we have the integers r and c, separated with one space.
Then we have the r lines, where each contains s 0's and 1's.
The numbers inside the individual lines are NOT separated by spaces.
The OUTPUT only print the number of blocks in the picture.
For example:
EXAMPLE 1
INPUT:
7 5
01000
00010
00000
10000
01000
00001
00100
OUTPUT:
6
EXAMPLE 2:
INPUT:
25 20
00010000000000000000
00010000000000000000
00010000000000000100
00000000000000000100
00011111111000000100
00000000000000000100
00000000000000000100
00000000000000000100
00000000000000000100
01111111111000000100
00000000000000000100
00000000000000100100
00000000000000100100
00000000000000100100
01000000000000100000
01000000000000100000
01000000000000100000
01000000000000100000
00000000000000100000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00011111111111100000
00000000000000000000
OUTPUT:
7
THE PROBLEM:
The problem that I have is that my program only works for inputs such as in example 1.
So pictures that only consist of blocks of size 1. But it doesnt work if there are multiples 1's in a picture, such as EXAMPLE 2.
In example 2 where the output should be 7(Blocks are elements of 1.They can either be vertial or horizontal).... my programs output is 30.
I don't know how to adjust the program in a correct manner so it will give me the correct input.
Thank you for your help in advance, here is my code that I am posting bellow.
import java.util.Scanner;
class Blocks{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int rowNum=sc.nextInt();
int columnNum=sc.nextInt();
char[][] matrix = new char[rowNum][columnNum];
int nbrOfBlocks = 0;
for (int a = 0; a < rowNum; a++) {
matrix[a] = sc.next().toCharArray();
int index = 0;
while (index < matrix[a].length) {
if (matrix[a][index] == '1') {
++nbrOfBlocks;
while (index < matrix[a].length && matrix[a][index] == '1') {
++index;
}
}
++index;
}
}
System.out.println(nbrOfBlocks);
}
}
EDIT: Ok, here is a solution that will work for complex shapes
public class BlockCounter {
public static void main(String[] args) {
Board board = null;
try {
board = new Board("in3.txt");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
System.out.println("Block count: " + board.getBlockCount());
}
}
class Board {
ArrayList<String> data = new ArrayList<>();
boolean[][] used;
int colCount = 0;
public Board(String filename) throws FileNotFoundException, IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
data.add(line);
colCount = Math.max(colCount, line.length());
}
}
}
public int getBlockCount() {
used = new boolean[data.size()][colCount];
int count = 0;
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
used[row][col] = peek(row, col) == '1';
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
if (used[row][col]) {
fill(row, col);
count++;
}
used = null;
return count;
}
public char peek(int row, int col) {
if (row < 0 || row >= data.size() || col < 0)
return '0';
String rowData = data.get(row);
if (col >= rowData.length())
return '0';
return rowData.charAt(col);
}
public void fill(int row, int col) {
if (used[row][col]) {
used[row][col] = false;
if (row > 0 && used[row - 1][col])
fill(row - 1, col);
if (col > 0 && used[row][col - 1])
fill(row, col - 1);
if (col < colCount - 1 && used[row][col + 1])
fill(row, col + 1);
if (row < data.size() - 1 && used[row + 1][col])
fill(row + 1, col);
}
}
public int getRowCount() {
return data.size();
}
public int getColCount() {
return colCount;
}
}
Explanation:
When Board.getBlockCount() is called if creates a temporary array of booleans to work with so the original board is not messed up. Then it searches the entire board for "trues" (which correspond to '1's on the board). Every time a "true" is found, a flood fill algorithm clears the entire shape to which it is connected.
If you need more performance and less memory usage (specially stack) for larger boards, you can use another flood fill algorithm like in the example that follows. The big advantage here is that it doesn't use the stack for every pixel like the one above. It is considerably more complex though.
public class BlockCounter2 {
public static void main(String[] args) {
Board2 board = null;
try {
board = new Board2("in4.txt");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
System.out.println("Block count: " + board.getBlockCount());
}
}
class Board2 {
ArrayList<String> data = new ArrayList<>();
boolean[][] used;
Deque<Point> pointStack = new LinkedList<>();
int colCount = 0;
public Board2(String filename) throws FileNotFoundException, IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
data.add(line);
colCount = Math.max(colCount, line.length());
}
}
}
public int getBlockCount() {
used = new boolean[data.size()][colCount];
int count = 0;
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
used[row][col] = peek(row, col) == '1';
for (int row = 0; row < data.size(); row++)
for (int col = 0; col < colCount; col++)
if (used[row][col]) {
fill(row, col);
count++;
}
used = null;
return count;
}
public char peek(int row, int col) {
if (row < 0 || row >= data.size() || col < 0)
return '0';
String rowData = data.get(row);
if (col >= rowData.length())
return '0';
return rowData.charAt(col);
}
public void fill(int row, int col) {
pointStack.push(new Point(col, row));
Point p;
while (pointStack.size() > 0) {
p = pointStack.pop();
fillRow(p.y, p.x);
}
}
private void checkRow(int row, int col, int minCol, int maxCol) {
boolean uu = false;
for (int x = col; x < maxCol; x++) {
if (!uu && used[row][x])
pointStack.add(new Point(x, row));
uu = used[row][x];
}
uu = true;
for (int x = col; x > minCol; x--) {
if (!uu && used[row][x])
pointStack.add(new Point(x, row));
uu = used[row][x];
}
}
private void fillRow(int row, int col) {
int lx, rx;
if (used[row][col]) {
for (rx = col; rx < colCount; rx++)
if (used[row][rx])
used[row][rx] = false;
else
break;
for (lx = col - 1; lx >= 0; lx--)
if (used[row][lx])
used[row][lx] = false;
else
break;
if (row > 0)
checkRow(row - 1, col, lx, rx);
if (row < data.size() - 1)
checkRow(row + 1, col, lx, rx);
}
}
public int getRowCount() {
return data.size();
}
public int getColCount() {
return colCount;
}
}
EDIT2: Both solutions were made using input from txt files in order to make the debugging and testing easier for larger arrays. If you need them to work with user input (the same you have in your code) as well, just make the following changes:
Change the main method so it will listen from user input (again):
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int rowNum=sc.nextInt();
int columnNum=sc.nextInt(); // Note columnNum is not necessary
String[] matrix = new String[rowNum]; // I hope char[][] is not a requirement
for (int a = 0; a < rowNum; a++) // Read array data from user input
matrix[a] = sc.next();
sc.close();
Board2 board = new Board2(matrix); // Call the new constructor
System.out.println("Block count: " + board.getBlockCount());
}
Add a new constructor to Board2, that takes a String[] as input:
public Board2(String[] data) {
for (String line : data) {
this.data.add(line);
colCount = Math.max(colCount, line.length());
}
}
You may remove the previous constructor Board2(String filename) if it is not useful for you but it's not necessary.
Are you searching for this:
import java.util.Scanner;
class Blocks {
public static void removeBlock(char[][] matrix, int posX, int posY) {
if(0 <= posX && posX < matrix.length
&& 0 <= posY && posY < matrix[posX].length) {
if(matrix[posX][posY] == '0') {
return;
}
matrix[posX][posY] = '0';
} else {
return;
}
removeBlock(matrix, posX - 1, posY);
removeBlock(matrix, posX + 1, posY);
removeBlock(matrix, posX, posY - 1);
removeBlock(matrix, posX, posY + 1);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// read in
char[][] matrix = new char[sc.nextInt()][sc.nextInt()];
for(int a = 0; a < matrix.length; a++) {
matrix[a] = sc.next().toCharArray();
}
// calculate number of blocks
int nrBlocks = 0;
for(int i = 0; i < matrix.length; i++) {
for(int j = 0; j < matrix[i].length; j++) {
if(matrix[i][j] == '1') {
// we have found a block, so increment number of blocks
nrBlocks += 1;
// remove any 1's of the block from the array, so that they each block is not counted multiple times
removeBlock(matrix, i, j);
}
}
}
System.out.println(nrBlocks);
}
}
There's a linear time (in number of cells) solution to this. If I get time, I'll add the code to this answer, but if not the Wikipedia article (see EDIT below) gives pseudo code.
The idea is to scan line-by-line, assigning an incrementing unique run numbers to each runs of 1s we see (and changing the cell content to be that unique number) If in any run, the cells immediately above in the previous line were also 1 (that is, they now have a run number), then we know that their unique-run-number and the current unique-run number form part of a single block. So record that the run-above-run-number, and the current-run-number are equivalent (but don't bother to change anything on the board)
At the end, we have a count of the runs we've seen. and a set of equivalence relationships of unique-run-numbers. For each set of equivalent-numbers (say runs 3, 5, 14 form a block), we subtract from the run count the number of runs, minus 1 (in other words, replacing the multiple runs with a single block count).
I think I have some ideas to mitigate the worst case, but they're probably not worth it.
And that's the number of blocks.
The worst case for the equivalence classes is O(size of board) though (1-wide vertical blocks, with one space between them will do this). Fortunately, the entirely-black board will need only O(height of board) - each row will get one number, which will be marked equivalent with the next row.
EDIT: There's a Stackoverflow question about this already: can counting contiguous regions in a bitmap be improved over O(r * c)?
and it turns out I've just re-invented the two-pass "Connected Component Labelling" algorithm discussed on Wikipedia
I am currently looking for a way of scanning a 2D matrix in Java for a number. Precisely, if in my matrix, there are numbers from 0 to 9, how do I "locate" the 0? This is intended for creating a Minesweeper game.
Here is what I have written so far. It is not complete. All I want is a clue on how to complete it.
class DemineurStackOverflow {
public static void minesweeper () {
int champDeMine[][];
boolean résultat[][];
int mine;
char réponse;
champDeMine = new int[longueur][largeur]; //Differenf from the matrix "champDeMines" from the second method
Arrays.asList(champDeMine).contains(0);
mine = (int) Math.floor(Math.random()*nbMines + 1);
System.out.println("Ajustement du nombre de mines en cours...");
if (mine < nbMines) {
for (mine = (int) Math.floor(Math.random()*nbMines + 1); mine < nbMines; mine++);
} else {
for (mine = (int) Math.floor(Math.random()*nbMines + 1); mine > nbMines; mine--);
}
if (mine == nbMines){
System.out.println("Chargement des mines OK.");
}
}
public static int [][] calculeProximité ( boolean [][] champDeMines ){
int row; //row index for prescence of 0, same value as longueur
int col; //column index for presence of 0, same value as largeur
int mine;
champDeMines = new boolean[row][col];
if (champDeMines = 0) {
champDeMines = mine;
}
//Here I am trying to figure a way of finding the 0s in this champDeMines matrix.
return (new int[champDeMines.length][champDeMines[0].length]);
}
}
The first method consists in generating an array from variables "longueur" and "largeur". The number of "mines" is supposed to represent the number 0 (which is why I want to scan for a 0), at random places. The second method consists in finding the "mines" in the array created. That is what I have trouble doing. Do you have any clues for completing the second method? I am simply looking for clues because I am learning to program in Java!
Thank you very much, your help is most certainly appreciated!
This is how minesweeper field population could look from the code provided. I hope you get the clue from the comments and do not hesitate to ask if anything is unclear.
import java.util.Random;
public class Demineur
{
// Here come CONSTANTS
public static final int MAX_MINES = 30;
public static final boolean MINE = true;
// Let's have a field 12x12 size
public static final int LONGEUR = 12;
public static final int LARGEUR = 12;
// each field contains number of mines it has access to
public static int champDeMine[][] = new int[LONGEUR][LARGEUR];
// each field can contain mine or be empty
public static boolean champDeMines[][] = new boolean[LONGEUR][LARGEUR];
public static void minesweeper()
{
Random random = new Random();
int mine ;
System.out.println("Ajustement du nombre de mines en cours...");
int nbMines = random.nextInt(MAX_MINES);
/**
* Let's plant mines. :-E
* Unoptimal but will suffice for demonstration purpose.
*/
int minesLeftToPlant = nbMines;
int skip = 0;
boolean planted = false;
while (minesLeftToPlant > 0)
{
skip = random.nextInt(LONGEUR*LARGEUR);
planted = false;
while (!planted && minesLeftToPlant > 0 && skip > 0)
{
for (int y = 0; !planted && minesLeftToPlant > 0 && y < LONGEUR; y++)
{
for (int x = 0; !planted && minesLeftToPlant > 0 && x < LARGEUR; x++)
{
if ( !MINE == champDeMines[y][x]
&& 0 == skip)
{
champDeMines[y][x] = MINE;
minesLeftToPlant--;
planted = true;
}
else
{
skip--;
}
}
}
}
}
System.out.println("Chargement des "+ nbMines +" mines OK.");
}
public static void calculeProximite()
{
int row ; //row index for prescence of 0, same value as longueur
int col ; //column index for presence of 0, same value as largeur
int mine;
//Check for each field it's neighbors and calculate which of them are mines
for (row = 0; row < LONGEUR; row++)
{
for (col = 0; col < LARGEUR; col++)
{
champDeMine[row][col] = numberOfMines(row,col);
}
}
}
public static void printChampDeMine()
{
for (int row = 0; row < LONGEUR; row++)
{
for (int col = 0; col < LARGEUR; col++)
{
System.out.print("'" + champDeMine[row][col] + "' ");
}
System.out.println();
}
}
public static void printChampDemines()
{
for (int row = 0; row < LONGEUR; row++)
{
for (int col = 0; col < LARGEUR; col++)
{
System.out.print("'" + (champDeMines[row][col] ? "m" : "e") + "' ");
}
System.out.println();
}
}
public static int numberOfMines(int row, int col)
{
return add(hasMine(row , col + 1))
+ add(hasMine(row - 1, col + 1))
+ add(hasMine(row - 1, col ))
+ add(hasMine(row - 1, col - 1))
+ add(hasMine(row , col - 1))
+ add(hasMine(row + 1, col - 1))
+ add(hasMine(row + 1, col ))
+ add(hasMine(row + 1, col + 1));
}
public static boolean hasMine(int row, int col)
{
return row >= 0 && col >= 0 && row < LONGEUR && col < LARGEUR
&& isMine(champDeMines[row][col]);
}
public static boolean isMine(boolean x)
{
return MINE == x;
}
public static int add(boolean c)
{
return c ? 1 : 0;
}
public static void main(String[] args)
{
minesweeper();
System.out.println("Champ de mines");
printChampDemines();
System.out.println("Champ de mine");
calculeProximite();
printChampDeMine();
}
}
Title says it all, I developed this diagonal method that searches the Matrix 'matrix' and goes from the Center to the far right corner. I also have it another set from the center to the left. I now have the question, how would I make it reversed, not starting from the bottom but actually starting "C", go all the way to "G" and keep moving towards the Left.
All it has to do is be reversed but I have tried and tried for about 2 hours and still to no avail. This is actually the final piece to my project I have going on and would awesome if someone could help flip.
Here's the code, I took out a large portion to conserve space.
public class Word {
public static int curCol = 10;
public static int curRow = 10;
public static String[][] matrix = {{"A","B","C"},
{"D","E","F"},
{"G","H","I"}};
private static void searchDiagonalCenterToRight(String word) {//Center to bottom Righ t. Diagnol Works, debug to go along column is needed
int rowOn = 0;
int colOn = 0;
int resetableCol = curCol;
resetableCol--;//Just resets everything then starts again.
int decreaser = curCol;//What to decrease by everytime it runs 10,9,8,7 all the way to 1
int resetableDec = decreaser;
resetableDec--;
char c;
String toFind = word.toUpperCase();
String developingInverse = "";
int integer = 0;
for(int row = 0; row < curRow; row++)//Matrices Row
{
for(int i = 0; i <= resetableDec; i++)
{
String developingWord = "";
integer = i;
for(int j = integer; j <= resetableDec; j++,integer++)
{
c = matrix[j][integer+row].charAt(0);//Sets to whatever letter it is on
char uC = Character.toUpperCase(c);
developingWord = developingWord + "" +uC;
System.out.println("On Row: " + row + " Started From: " + integer + " Now On: " + j);
System.out.println("Processing Letter: " + matrix[j][integer] + " Adding Letter To: " + developingWord);
}
}
resetableDec--;
}
System.out.println("\nNo Matching Word Was Found, Center To Left.");
}
}
Here is the code
public class ReverseDiagonalMatrix {
public static void main(String[] args) {
int [][] a = {{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9,10,11,12},
{13,14,15,16}};
int a1[][]= {{1,2,3},
{4,5,6},
{7,8,9}};
int a2[][]= {{1,2},
{3,4}};
int [][] a3 = {{ 1, 2, 3, 4, 5},
{ 6, 7, 8, 9,10},
{11,12,13,14,15},
{16,17,18,19,20},
{21,22,23,24,25}};
System.out.println("==========5x5==============");
findReverseDiagonalOrder(a3);
System.out.println("==========4x4==============");
findReverseDiagonalOrder(a);
System.out.println("===========3x3=============");
findReverseDiagonalOrder(a1);
System.out.println("===========2x2=============");
findReverseDiagonalOrder(a2);
}
public static void findReverseDiagonalOrder(int[][] a) {
int m = a.length;
int row=0;
int col = m-1;
for(int i=0;i<m*m;i++) {
System.out.println(a[row][col]);
if(col==m-1) {
if(row==0)
col--;
else {
col= (row==col)? 0:col-(row+1);
row= (row==m-1)? 1:0;
}
}
else if(row==m-1) {
if(col-1==0 && col>0)
col--;
else {
row = m-col;
col=0;
}
}
else {
row++;
col++;
}
}
}
}
To access the other diagonal just use the following loop
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==(n-j-1)){
//Do something
}
}
}
By using this logic you will get CEG
Add the same logic to construct other strings too.
EDIT:-
By changing loop like this
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i<=(n-j-1)){
System.out.println("("+i+","+j+")");
}
}
}
You can access elements (0,0) (0,1) (0,2) (1,0) (1,1) (2,0). I hope that is what you want.