Finding 5 values in a row diagonally in Java - java

I have this 10x10 array:
private static int[][] intersections = new int[10][10];
I'm using this code to find if there are 5 values in a row horizontally:
public static int horizontalCheck() {
String horizontal = "";
for (int i = 0; i < intersections.length; i++) {
for (int j = 0; j < intersections[i].length; j++) {
horizontal += Integer.toString(intersections[i][j]);
}
if (horizontal.indexOf("11111") != -1) {
// White wins.
return 1;
} else if (horizontal.indexOf("22222") != -1) {
// Black wins.
return 2;
}
horizontal = "";
}
return 0;
}
And a similar code to do it vertically. But my question is, how could I find if there are 5 values in a row diagonally? The board is sized 10x10 and the diagonals can be both ways anywhere on the board. If you have any questions or need some more information on the code, make sure to ask.

I suggest you write a helper function for this. The function should take these parameters:
r0 - The starting row from which the check needs to start
c0 - The starting column from which the check needs to start
dr - The vertical step from {-1, 0, 1}
dc - The horizontal step from {-1, 0, 1}
len - The number of items to be found
num - The number to find.
Here is how this function may look:
private static boolean checkRow(int r0, int c0, int dr, int dc, int len, int num) {
for (int k = 0 ; k != len ; k++) {
int r = r0 + k*dr;
int c = c0 + k*dc;
if (r < 0 || c < 0 || r >= intersections.length || c > intersections[r].length || intersections[r][c] != num) {
return false;
}
}
return true;
}
With this function in hand, you can check for len items in a row in any direction that you wish:
// See if we've got five eights in any direction:
for (int r = 0 ; r != intersections.length ; r++) {
for (int c = 0 ; c != intersections[r].length ; c++) {
if (checkRow(r, c, 0, 1, 5, 8)) {
System.out.println("Horizontal, starting at "+r+" " +c);
}
if (checkRow(r, c, 1, 0, 5, 8)) {
System.out.println("Vertical, starting at "+r+" " +c);
}
if (checkRow(r, c, 1, 1, 5, 8)) {
System.out.println("Diagonal descending right, starting at "+r+" " +c);
}
if (checkRow(r, c, 1, -1, 5, 8)) {
System.out.println("Diagonal descending left, starting at "+r+" " +c);
}
}
}

Related

how to replace a 2D array for a new 2D array in a console in Java?

My code has some logic issues with the problem mentioned above.
What I'm trying to do is to print a 2D array in the console, and then, after asking for the user's input, the array will change and will replace the old one for this new one in the console.
Here is an example of what I'm trying to do.
Don't pay attention to the numbers on the array, what I am asking only has to do with the elements that are printed in the console.
The console will look like this
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---1---
After the user gives the column, the console will look like this.
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---1---
A
3 3 2 1 1 3
2 2 3 1 1 3
2 3 3 1 3 3
2 2 3 3 1 3
1 3 1 2 2 3
2 2 1 1 3 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---2---
The code that I attached at the end does all of this, but the problem starts after the user gives the second input. After the user gives his second input (his second column) the console will look like this:
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---1---
A
3 3 2 1 1 3
2 2 3 1 1 3
2 3 3 1 3 3
2 2 3 3 1 3
1 3 1 2 2 3
2 2 1 1 3 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---2---
B
2 2 2 3 3 1
3 3 2 1 1 3
2 2 3 1 1 3
2 3 3 1 3 3
2 2 3 3 1 3
1 3 1 2 2 3
0 0 1 1 3 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---3---
What it's doing is that it keeps printing and printing new boards instead of "updating" the same board.
What I am trying to achieve is the following: (What I am showing is what I want the console to look like)
(User gives the first input)
Console:
The number that is going to be shoot is ---2---
A
3 3 2 1 1 3
2 2 3 1 1 3
2 3 3 1 3 3
2 2 3 3 1 3
1 3 1 2 2 3
2 2 1 1 3 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
(User gives second input)
Console:
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---3---
A
2 2 2 3 3 1
3 3 2 1 1 3
2 2 3 1 1 3
2 3 3 1 3 3
2 2 3 3 1 3
1 3 1 2 2 3
0 0 1 1 3 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
(The only 2 changes here are the number that is going to be shoot and the numbers in the array)
In a few words all I want to do is to "update" the board with the result instead of printing and printing new boards over and over again.
The code below is the code I have so far. I included a pseudo code so that you can see what each method does (The whole game structure is on the game() method). I would prefer to not change the code for any of the methods rather than the gameOver method since it is the one that is in "charge" of clearing the consoles and all that stuff. (If you find an answer and involves changing another method that's ok)
Again, the only thing that i'm confused about is on how to replace the existing board instead of printing new boards, not with the content of the arrays.
Here's the code
import java.util.Scanner;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Collections;
public class Project {
public static final int[][] NEIGHBOURS = // adjacent cells
{{0, 1}, // horizontal -
{1, 0}, // vertical |
{1, 1}, // diagonal \
{1, -1}}; // diagonal /
private List<Island> islands = new ArrayList<>(); // collection of Islands
private int[][] grid; // matrix
public Project(int[][] grid) {
this.grid = grid;
}
public static int[][]board = { {0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0} };
public static int[][]numberBoard = createBoard(6, /*Number of colums*/ 5, /*Number of rows*/ 3 /*Bubble types in the board (1, 2 or 3)*/);
//creates random board
public static void main( String[] args) {
game();
}
public static void game() {
String input; //the Input
int randomNumber;
int[] location;
board = combine(board, numberBoard); //Empty Board to Randomized Board
while(gameOver(board).equals("GAME CONTINUES")) {
gameOver(board); //Scans the array to see if the game is still going or not
//The code below up to "shiftRow" shouldn't really matter with the question because all it's doing is to make changes to the array
//but does not print anything to the console so I seperated them.
randomNumber = createRandomNumber(3); //creates a randomNumber
input = shoot(randomNumber); //Input
board = putNumber(board, input, randomNumber); //Places Input
location = numberLocation(board, input, randomNumber); //Gets location of the placed number
board = destroyAdjacentNumbers(board, location[0], location[1], randomNumber); //Deletes any number that is both, a neighbor and
//has the same value as the number placed
Project destroyIslands = new Project(board); //destroys the islands (Chunks of numbers that are completely surrounded by zeros)
destroyIslands.deleteIslandBoard2();
shiftRow(board); //Shifts the row down
destroyIslands.printGrid(); //prints the grid
}
if(gameOver(board).equals("CONGRATULATIONS, YOU WON THE GAME!")) {
clearConsole();
System.out.println("CONGRATULATIONS, YOU WON THE GAME!");
} else if(gameOver(board).equals("YOU LOST THE GAME!")) {
clearConsole();
System.out.println("YOU LOST THE GAME!");
}
}
public static int[][] createBoard(int cols, int rows, int numBubbleTypes) {
int[][] board = new int[rows][cols];
for( int row = 0; row < rows; row++ ) {
for( int col = 0; col < cols; col++ ) {
board[row][col] = (int)(Math.random() * (double)numBubbleTypes) + 1;
}
}
return board;
}
public static int createRandomNumber(int type) {
double randomNumber = Math.random();
randomNumber = randomNumber * type;
int roundedNumber = (int) Math.floor(randomNumber);
int result = roundedNumber + 1;
return result;
}
public static void printGrid(int[][] grid) {
for( int row = 0; row < grid.length; row++ ) {
for( int col = 0; col < grid[row].length; col++ ) {
System.out.print( grid[row][col] + " " );
}
System.out.println("");
}
}
public static int[][] shiftRow( int[][] grid ) {
/*
* Pseudocode:
* Shift down first row to second row, then third row goes up two rows
*
* Shift each row down one (except the last row), then shift bottom row to the top
*
* Store the row after the current row in a temporary box, then overwrite the next row
* with the first, then repeat (excluding the last row).
*/
int[] tempList = new int[ grid[0].length ]; //0, 0, 0
for( int col = 0; col < grid[0].length; col++ ) {
tempList[col] = grid[0][col];
}
for( int row = 0; row < grid.length - 1; row++ ) {
int[] currentList = new int[ grid[row].length ];
for( int col = 0; col < grid[row].length; col++ ) {
currentList[col] = tempList[col];
tempList[col] = grid[row+1][col];
grid[row+1][col] = currentList[col];
}
}
int[][]newRow = createBoard(6, 1, 3);
for( int col = 0; col < grid[0].length; col++ ) {
grid[0][col] = newRow[0][col];
}
return grid;
}
public static void fillBoard(int[]array) {
}
public static String shoot(int number) {
System.out.println("What column do you want to shoot (A, B, C, D, E, F)");
System.out.println("The number that is going to be shoot is ---" + number + "--- ");
Scanner scanShoot = new Scanner(System.in);
String input = scanShoot.nextLine();
return input;
}
private static void clearConsole() {
System.out.print('\u000C'); //Clear terminal
}
public static int[][] combine(int[][]board, int[][] numberBoard) {
for(int i = 0; i < numberBoard.length; i++) {
for(int j = 0; j < numberBoard[i].length; j++) {
board[i][j] = numberBoard[i][j];
}
}
return board;
}
public static int[][] putNumber(int[][] board, String columnInput, int randomNumber) {
if(columnInput.equals("A") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][0] == 0) {
board[row][0] = randomNumber;
break;
}
}
}
if(columnInput.equals("B") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][1] == 0) {
board[row][1] = randomNumber;
break;
}
}
}
if(columnInput.equals("C") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][2] == 0) {
board[row][2] = randomNumber;
break;
}
}
}
if(columnInput.equals("D") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][3] == 0) {
board[row][3] = randomNumber;
break;
}
}
}
if(columnInput.equals("E") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][4] == 0) {
board[row][4] = randomNumber;
break;
}
}
}
if(columnInput.equals("F") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][5] == 0) {
board[row][5] = randomNumber;
break;
}
}
}
return board;
}
public static int [] numberLocation(int [][] board, String column, int randomNumber) {
int columnIndex = column.charAt (0) - 'A';
int saveRow = -1;
for (int row = 0; row < board.length; row++) {
if (columnIndex >= 0 && columnIndex < board[row].length && board [row][columnIndex] == 0) {
board [row][columnIndex] = randomNumber;
saveRow = row;
break;
}
}
return new int [] { saveRow, columnIndex };
}
public static void destroyNumbers(int num, int[][] grid) {
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
if (grid[i][j] == num) {
grid[i][j] = 0;
}
}
}
}
public static int[][] destroyAdjacentNumbers(int[][] array, int row, int col, int num) {
if (row < 0 || row >= array.length || col < 0 || col >= array[row].length) {
return array;
}
if (array[row][col] == num) {
array[row][col] = 0;
}
if (row > 0 && array[row - 1][col] == num) {
array[row - 1][col] = 0;
destroyAdjacentNumbers(array, row - 1, col, num);
}
if (row < array.length - 1 && array[row + 1][col] == num) {
array[row + 1][col] = 0;
destroyAdjacentNumbers(array, row + 1, col, num);
}
if (col > 0 && array[row][col - 1] == num) {
array[row][col - 1] = 0;
destroyAdjacentNumbers(array, row, col - 1, num);
}
if (col < array[row].length - 1 && array[row][col + 1] == num) {
array[row][col + 1] = 0;
destroyAdjacentNumbers(array, row, col + 1, num);
}
return array;
}
public static void numberShot(int number) {
System.out.println("The number that is going to be shot is " + " --- " + number + " --- " );
}
public static String gameOver(int[][] array) {
boolean hasEmpty = false;
boolean hasNonEmpty = false;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] == 0) {
hasEmpty = true;
} else {
hasNonEmpty = true;
}
}
}
if (hasEmpty && hasNonEmpty) {
return "GAME CONTINUES";
} else if (hasEmpty) {
clearConsole();
return "CONGRATULATIONS, YOU WON THE GAME!";
} else {
clearConsole();
return "YOU LOST THE GAME!";
}
}
public static int[][] deleteIslandBoard(int[][] array) {
// Create a boolean array to track which cells have been visited
boolean[][] visited = new boolean[array.length][array[0].length];
// Iterate
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[0].length; j++) {
// If the cell is not visited and is part of an island
if (!visited[i][j] && array[i][j] != 0) {
// Delete the island by setting all cells to 0
deleteIsland(array, i, j, visited);
}
}
}
// Return the modified array
return array;
}
public static void deleteIsland(int[][] array, int i, int j, boolean[][] visited) {
// Check if the current cell is out of board or if it has already been visited
if (i < 0 || i >= array.length || j < 0 || j >= array[0].length || visited[i][j]) {
return;
}
// Mark the current cell as visited
visited[i][j] = true; // If the current cell is part of the island, set it to 0
if (array[i][j] != 0) {
array[i][j] = 0;
// Recursively delete the neighboring cells that are part of the island
deleteIsland(array, i - 1, j, visited);
deleteIsland(array, i + 1, j, visited);
deleteIsland(array, i, j - 1, visited);
deleteIsland(array, i, j + 1, visited);
}
}
public class Island implements Comparable<Island> {
private List<int[]> cells = new ArrayList<>();
public void addCell(int[] cell) {
cells.add(cell);
}
public void destroy() {
cells.forEach(cell -> grid[cell[0]][cell[1]] = 0);
}
#Override
public int compareTo(Island other) {
return Integer.compare(cells.size(), other.cells.size());
}
}
public void deleteIslandBoard2() {
exploreIslands();
deleteSmallerIslands();
}
public void exploreIslands() {
boolean[][] visited = new boolean[grid.length][grid[0].length];
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (!visited[i][j] && grid[i][j] != 0) { // if a New Island was found
exploreIsland(new int[]{i, j}, visited); // explore the Island, i.e. index all its cell and mark them as visited
}
}
}
}
/**
* Depth first search implementation
*/
public void exploreIsland(int[] cell, boolean[][] visited) {
Island island = new Island();
islands.add(island); // updating the list of Islands
Deque<int[]> stack = new ArrayDeque<>();
stack.push(cell);
while (!stack.isEmpty()) {
int[] next = stack.poll();
island.addCell(next);
for (int[] shift : NEIGHBOURS) {
int row = next[0] + shift[0];
int col = next[1] + shift[1];
if (isValid(row, col) && !visited[row][col]) { // if cell exist, non-zero and not visited yet
stack.push(new int[]{row, col});
visited[row][col] = true;
}
}
}
}
public boolean isValid(int row, int col) {
return row >= 0 && row < grid.length
&& col >= 0 && col < grid[0].length
&& grid[row][col] != 0;
}
public void deleteSmallerIslands() {
if (islands.isEmpty()) return; // otherwise Collections.max() would throw NoSuchElementException
Island largest = Collections.max(islands);
for (Island next : islands) {
if (next != largest) next.destroy();
}
}
public void printGrid() {
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
System.out.print(grid[i][j] + " ");
}
System.out.println();
}
}
}
Most of this code shouldn't matter, just the methods that print stuff!!!!!!!!!!!!!!!

Search in circular sorted martix and run complexity

The method is given NxN matrix always powers of 2 and a number,it will return true if the num is found example for 4x4 size:
this is what i wrote:
public class Search {
public static boolean Search (int [][] matrix, int num)
{
int value = matrix.length / 2;
int first_quarter_pivot = matrix[value-1][0]; // represents highest number in first quarter
int second_quarter_pivot = matrix[value-1][value]; // represents highest number in second quarter
int third_quarter_pivot = matrix[matrix.length-1][value]; // represents highest number in third quarter
int fourth_quarter_pivot = matrix[matrix.length-1][0]; // represents highest number in fourth quarter
boolean isBoolean = false;
int i=0;
int j;
// if the num is not in the range of biggest smallest number it means he can`t be there.
if(!(num >= first_quarter_pivot) && (num <= fourth_quarter_pivot)) {
return false;
}
// if num is one of the pivots return true;
if((num == first_quarter_pivot || (num ==second_quarter_pivot))
|| (num == third_quarter_pivot) || (num == fourth_quarter_pivot ))
return true;
// if num is smaller than first pivot it means num is the first quarter,we limit the search to first quarter.
// if not smaller move to the next quarter pivot
if(num < first_quarter_pivot){{
j =0;
do
if(matrix[i][j] == num) {
isBoolean = true;
break;
}
else if((j == value)) {
j = 0;
i++;
}
else if(matrix[i][j] != num){
j++;
}
while(isBoolean != true) ;
}
return isBoolean;
}
// if num is smaller than second pivot it means num is the second quarter,we limit the search to second quarter.
// if not smaller move to the next quarter pivot
if(num < second_quarter_pivot){{
j = value;// start (0,value) j++ till j=value
do
if(matrix[i][j] == num) {
isBoolean = true;
break;
}
else if((j == matrix.length-1)) {
j = value;
i++;
}
else if(matrix[i][j] != num){
j++;
}
while(isBoolean != true) ;
}
return isBoolean;
}
// if num is smaller than third pivot it means num is the third quarter,we limit the search to third quarter.
// if not smaller move to the next quarter pivot
if(num < third_quarter_pivot){{
i = value;
j = value;// start (0,value) j++ till j=value
do
if(matrix[i][j] == num) {
isBoolean = true;
break;
}
else if((j == matrix.length-1)) {
j = value;
i++;
}
else if(matrix[i][j] != num){
j++;
}
while(isBoolean != true) ;
}
return isBoolean;
}
// if num is smaller than fourth pivot it means num is the fourth quarter,we limit the search to fourth quarter.
// number must be here because we verfied his existence in the start.
if(num < fourth_quarter_pivot){
i = value;
j = 0;// start (0,value) j++ till j=value
do
if(matrix[i][j] == num) {
isBoolean = true;
break;
}
else if((j == value)) {
j = 0;
i++;
}
else if(matrix[i][j] != num){
j++;
}
while(isBoolean != true) ;
}
return isBoolean;
}
}
What i tried to do:
find in which quarter the wanted number is in,after that check
the same quarter by moving j++ until it hits the limit,than i++
until found
with the limits changing for each quarter,i cant understand if run time complexity is O(n^2) or lower? and will it be better do create one dimensional array and and move on the quarter this way: move right until limit,one down,move left until limit and il have a sorted array and just binear search
If you can map an array to a matrix, you can use a normal binary search.
You can define the translation table to achieve that like this:
X = [0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3, ...]
Y = [0, 1, 1, 0, 2, 3, 3, 2, 2, 3, 3, 2, 0, 1, 1, 0, ...]
The final program looks like this.
static final int MAX_N = 64;
static final int MAX_NN = MAX_N * MAX_N;
static final int[] DX = {0, 0, 1, 1};
static final int[] DY = {0, 1, 1, 0};
static final int[] X = new int[MAX_NN];
static final int[] Y = new int[MAX_NN];
static { // initialize X and Y
for (int i = 0; i < MAX_NN; ++i) {
int x = 0, y = 0;
for (int t = i, f = 0; t > 0; ++f) {
int mod = t & 3;
x += DX[mod] << f; y += DY[mod] << f;
t >>= 2;
}
X[i] = x; Y[i] = y;
}
}
public static boolean Search(int [][] matrix, int num) {
int n = matrix.length, nn = n * n;
int lower = 0;
int upper = nn - 1;
while (lower <= upper) {
int mid = (lower + upper) / 2;
int value = matrix[X[mid]][Y[mid]];
if (value == num)
return true;
else if (value < num)
lower = mid + 1;
else
upper = mid - 1;
}
return false;
}
and
public static void main(String[] args) {
int[][] matrix = {
{1, 3, 7, 9},
{6, 4, 15, 11},
{36, 50, 21, 22},
{60, 55, 30, 26},
};
// case: exists
System.out.println(Search(matrix, 1));
System.out.println(Search(matrix, 60));
System.out.println(Search(matrix, 11));
// case: not exists
System.out.println(Search(matrix, 0));
System.out.println(Search(matrix, 70));
System.out.println(Search(matrix, 20));
}
output:
true
true
true
false
false
false

Printing string in rows and column pattern Java

i'm just created a java project to print string that is given in rows and column just like matrix. Here's the output that i just made:
h e l l o
_ w o r l
d _ i t s
_ b e a u
t i f u l
Is it possible to show the output like a spiral pattern like this?
h e l l o
_ b e a _
s u l u w
t f i t o
i _ d l r
For the clarification how this spiral matrix created:
Here's my current code:
String str = "hello world its beautiful";
double length = Math.sqrt(str.length());
int x = (int) length;
for (int i = 0, len = str.length(); i < len; i++) {
System.out.print(str.charAt(i) + " ");
if (i % x == x - 1) {
System.out.println();
}
}
I'm trying to make the same pattern like that, but it's never be. Let me know that you can help me with this. I appreciate for every answer that you gave, thank you.
Basically, you move through the string from start to end, but treat the stringbuffer as an array.
You#ll also need to to keep track of your direction (dx,dy) and where your bounds are.
The following code will produce:
hello
beau
l.tw
sufio
i dlr
given the input "hello world is beautiful"
public class Main {
public static void main(String[] args) {
String text ="hello world is beautiful";
int len = text.length();
double sideLength = Math.sqrt( len );
int width = 0;
int height = 0;
// check if it's a square
if ( sideLength > (int) sideLength) {
// nope... it#s a rectangle
width = (int) sideLength +1;
height = (int) Math.ceil((double)len / (double)width);
} else {
// square
width = (int) sideLength;
height = (int) sideLength;
}
// create a buffer for the spiral
StringBuffer buf = new StringBuffer( width * height );
buf.setLength( width * height );
// clear it.
for (int a=0; a < buf.length(); a++ ) {
buf.setCharAt(a, '.');
}
int dstX = 0;
int dstY = 0;
int curWidth = width;
int curHeight = height;
int startX = 0;
int startY = 0;
int dx = 1;
int dy = 0;
// go through the string, char by char
for (int srcPos =0; srcPos < len; srcPos++) {
buf.setCharAt( dstX + dstY * width, text.charAt( srcPos ));
// move cursor
dstX += dx;
dstY += dy;
// check for bounds
if ( dstX == curWidth-1 && dx > 0) {
// end of line while going right, need to go down
dx = 0;
dy = 1;
// also, reduce width
curWidth--;
startY++;
} else if (dstY == curHeight-1 && dy > 0) {
// end of column while going down, need to go left
dx = -1;
dy = 0;
// also, reduce height
curHeight--;
} else if (dstX == startX && dx < 0) {
// hit left border while going left, need to go up
dx = 0;
dy = -1;
// also, increase startX
startX++;
} else if (dstY == startY && dy < 0) {
// hit top border, while going up, need to go right
dx = 1;
dy = 0;
// also, increase startY
startY++;
}
}
// display string
for (int line = 0; line < height; line++) {
System.out.println( buf.substring( line* width, line*width +width) );
}
}
}
spiralMatrix(int s) returns s x s spiral matrix.
static int[][] spiralMatrix(int s) {
int[][] a = new int[s][s];
int n = 0;
for (int b = s - 1, c = 0, x = 0, y = 0, dx = 0, dy = 1; b > 0; b -= 2, x = y = ++c)
for (int j = 0, t = 0; j < 4; ++j, t = dx, dx = dy, dy = -t)
for (int i = 0; i < b; ++i, x += dx, y += dy, ++n)
a[x][y] = n;
if (s % 2 == 1)
a[s / 2][s / 2] = n;
return a;
}
test
for (int s = 0; s < 6; ++s) {
int[][] a = spiralMatrix(s);
System.out.println("s=" + s);
for (int[] row : a)
System.out.println(Arrays.toString(row));
System.out.println();
}
result
s=0
s=1
[0]
s=2
[0, 1]
[3, 2]
s=3
[0, 1, 2]
[7, 8, 3]
[6, 5, 4]
s=4
[0, 1, 2, 3]
[11, 12, 13, 4]
[10, 15, 14, 5]
[9, 8, 7, 6]
s=5
[0, 1, 2, 3, 4]
[15, 16, 17, 18, 5]
[14, 23, 24, 19, 6]
[13, 22, 21, 20, 7]
[12, 11, 10, 9, 8]
And you can do it with this method.
String str = "hello world its beautiful";
int[][] spiral = spiralMatrix(5);
int length = str.length();
for (int x = 0, h = spiral.length, w = spiral[0].length; x < h; ++x) {
for (int y = 0; y < w; ++y) {
int p = spiral[x][y];
System.out.print((p < length ? str.charAt(p) : " ") + " " );
}
System.out.println();
}
result
h e l l o
b e a
s u l u w
t f i t o
i d l r
you could try to make the spiral algorithm first and try to find the value of its each index in the matrix so that later you could map every index of your string into the specific index in the spiral array matrix.
for example:
Input: n = 5
Output: 1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
Aligned Output: 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9
the algorithm can be found here or here.
now you know all the index of each position to make the letters aligned in a spiral way, what you have to do is map each letter of your string to be print according to the number of the spiral matrix sequentially.
print string 1.
print string 2.
print string 3.
print string 4.
print string 5.
print string 16.
print string 17.
print string 18.
print string 19.
print string 6.
print string 15.
cont...
Probably I'll add my answer too, idea is to flatten a two dimensional array to 1d and use the 1D array and transform it to a 2D spiral array. Hope it helps.
Code:
class Test {
static String[][] spiralPrint(int m, int n, String[] a) {
String[][] output = new String[m][n];
int count = 0;
int i, k = 0, l = 0;
while (k < m && l < n) {
for (i = l; i < n; ++i) {
output[k][i] = a[count++];
}
k++;
for (i = k; i < m; ++i) {
output[i][n - 1] = a[count++];
}
n--;
if (k < m) {
for (i = n - 1; i >= l; --i) {
output[m - 1][i] = a[count++];
}
m--;
}
if (l < n) {
for (i = m - 1; i >= k; --i) {
output[i][l] = a[count++];
}
l++;
}
}
return output;
}
private static String[] flattenArray(String[][] input, int m, int n) {
String[] output = new String[m * n];
int k = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
output[k++] = input[i][j];
}
}
return output;
}
public static void main(String[] args) {
String[][] input = {
{"h", "e", "l", "l", "o"},
{"_", "w", "o", "r", "l"},
{"d", "_", "i", "t", "s"},
{"_", "b", "e", "a", "u"},
{"t", "i", "f", "u", "l"}};
int m = 5;
int n = 5;
String[] flattenArray = flattenArray(input, m, n);
String[][] spiralArray = spiralPrint(m, n, flattenArray);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
System.out.print(spiralArray[i][j] + " ");
}
System.out.println();
}
}
}
Output:
h e l l o
_ b e a _
s u l u w
t f i t o
i _ d l r
Note: Indeed that I followed this Spiral transform to 1D, but it is not straight forward, I have re-modified to fit to the problem.
I think that the best way to implement this is the following:
create an instruction object (Dictionary.java) which controls the fill-in process of the matrix
fill in the matrix with data (Spiral.java)
then show the matrix
With this approach, you can change the pattern easily, without changing the rest of the code because the pattern generator works detached from the rest of the code.
This is how the basic Dictionary class may look like:
public abstract class Dictionary {
protected int matrixSize;
protected String[] dictionary;
public Dictionary(int matrixSize) {
this.matrixSize = matrixSize;
dictionary = new String[matrixSize * matrixSize];
}
public abstract String[] createPattern();
public void showPattern() {
Arrays.stream(dictionary).forEach(System.out::println);
}
}
For each pattern, you need to implement the createPattern() method differently.
For example, a frame pattern implementation can be something like this:
public class FrameDictionary extends Dictionary {
protected int dictionaryIndex = 0;
protected int startX, endX;
protected int startY, endY;
public FrameDictionary(int matrixSize) {
super(matrixSize);
startX = -1;
endX = matrixSize - 1;
startY = 0;
endY = matrixSize - 1;
}
#Override
public String[] createPattern() {
while (dictionaryIndex < matrixSize) {
pattern1();
pattern2();
}
return dictionary;
}
/**
* pattern 1
* direction: left -> right then top -> bottom
*/
protected void pattern1() {
startX++;
for (int i = startX; i <= endX; i++) {
dictionary[dictionaryIndex] = i + ":" + startY;
dictionaryIndex++;
}
startY++;
for (int i = startY; i <= endY; i++) {
dictionary[dictionaryIndex] = endX + ":" + i;
dictionaryIndex++;
}
}
/**
* pattern 2
* direction: right -> left then bottom -> top
*/
protected void pattern2() {
endX--;
for (int i = endX; i >= startX; i--) {
dictionary[dictionaryIndex] = i + ":" + endY;
dictionaryIndex++;
}
endY--;
for (int i = endY; i >= startY; i--) {
dictionary[dictionaryIndex] = startX + ":" + i;
dictionaryIndex++;
}
}
}
Output:
a b c d e f
t g
s h
r i
q j
p o n m l k
You can draw the pattern what you need with the following implementation of the createPattern() method:
public class ClockWiseDictionary extends FrameDictionary {
public ClockWiseDictionary(int matrixSize) {
super(matrixSize);
}
#Override
public String[] createPattern() {
int pixelsInMatrix = matrixSize * matrixSize;
while (dictionaryIndex < pixelsInMatrix) {
pattern1();
pattern2();
}
return dictionary;
}
}
Output:
a b c d e f
t u v w x g
s 6 7 8 y h
r 5 0 9 z i
q 4 3 2 1 j
p o n m l k
Or just for fun, a "snake" pattern implementation:
public class SnakeDictionary extends Dictionary {
private int dictionaryIndex = 0;
private int startY = 0;
public SnakeDictionary(int matrixSize) {
super(matrixSize);
}
#Override
public String[] createPattern() {
int pixelsInMatrix = matrixSize * matrixSize;
while (dictionaryIndex < pixelsInMatrix) {
pattern1();
if (dictionaryIndex < pixelsInMatrix) {
pattern2();
}
}
return dictionary;
}
public void pattern1() {
for (int i = 0; i < matrixSize; i++) {
dictionary[dictionaryIndex] = i + ":" + startY;
dictionaryIndex++;
}
startY++;
}
public void pattern2() {
for (int i = matrixSize - 1; i >= 0; i--) {
dictionary[dictionaryIndex] = i + ":" + startY;
dictionaryIndex++;
}
startY++;
}
}
Output:
a b c d e f
l k j i h g
m n o p q r
x w v u t s
y z 1 2 3 4
0 9 8 7 6 5
This is how the main method looks like:
public static void main(String[] args) {
String sentence = "abcdefghijklmnopqrstuvwxyz1234567890";
String[][] spiral = new String[MATRIX_SIZE][MATRIX_SIZE];
// Dictionary dictionary = new FrameDictionary(MATRIX_SIZE);
Dictionary dictionary = new ClockWiseDictionary(MATRIX_SIZE);
// Dictionary dictionary = new SnakeDictionary(MATRIX_SIZE);
String[] pattern = dictionary.createPattern();
//dictionary.showPattern();
Spiral.fill(sentence, pattern, spiral);
Spiral.show(spiral);
}
You can check/download the complete source code from GitHub.
Hope that it helps you.
Here's a one with a recursive approach,
I am traversing the matrix in right -> down -> left -> up fashion on the boundaries
Then change the size and do the same for inner boundaries,
Matrix M would be a spiral matrix then of character indices
Create spiral matrix C for characters by traversing matrix M.
int m = 5;
int n = 5;
int limit = m * n;
int[][] M = new int[m][n];
public void spiral(int[][] M, int row, int col, int c, int start, int m, int n) {
if (c > limit | row >= m | col >= n)
return;
if (M[row][col] == 0)
M[row][col] = c;
if (row == start) // go right
spiral(M, row, col + 1, c + 1, start, m, n);
if (col == n - 1) // go down
spiral(M, row + 1, col, c + 1, start, m, n);
if (row == m - 1 && col > start) // go left
spiral(M, row, col - 1, c + 1, start, m, n);
if (col == start && row >= start) // go up
spiral(M, row - 1, col, c + 1, start, m, n);
};
spiral(M, 0, 0, 1, 0, m, n);
for (int i = m - 1, x = 1, j = n - 1; i >= m - 2 && j >= n - 2; i--, j--, x++)
spiral(M, x, x, M[x][x - 1] + 1, x, i, j);
This would give you spiral Matrix M
Output:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
Then create a spiral matrix for characters using matrix M
String string = "hello_world_its_beautiful";
char[][] C = new char[size][size];
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++)
C[i][j] = string.charAt(M[i][j] - 1);
}
Output:
h e l l o
_ b e a _
s u l u w
t f i t o
i _ d l r
When can't go straight turn left to walk, this is the theory used in this solution
int dr[] = {0, 1, 0, -1};
int dc[] = {1, 0, -1, 0};
this is used for always move pattern. And curr & curc represent current position and curm represent current move pattern.
public int[][] solve(int r, int c, String s) {
int m[][] = new int[5][5];
int curr = 0, curc = 0;
for (int pos = 0, curm = 0; pos < r*c; pos++) {
m[curr][curc] = (int) s.charAt(pos);
if (curr + dr[curm] < 0 || curr + dr[curm] >= r || curc + dc[curm] < 0 || curc + dc[curm] >= c
|| m[curr + dr[curm]][curc + dc[curm]] != 0)
curm = (curm + 1) % 4;
curr = curr + dr[curm];
curc = curc + dc[curm];
}
return m;
}
Then you can print this way
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
System.out.printf("%c ", m[i][j]);
}
System.out.println("");
}

Maximum number of pairs

I need to find out the maximum number of pairs of 1's and 0's that can be found by just altering a single number in a given array.
For example:
If my input is {1,0,0,1,0,0}, here at index position 3 if I replace 1 with 0 then I will get 4 pairs i.e the arrays becomes {1,0,0,0,0,0}, and the pairs are (1,2), (2,3), (3,4), (4,5).
But if I replace index position 0 from 1 to 0 then the array is {0,0,0,1,0,0} here I will get only 3 pairs i.e (0,1), (1,2), (4,5)
I need a program that returns maximum number of pairs possible for a given input array. In this case the program should give 4 as result.
Here the array contains only 1's and 0's.
Here is my program:
public class Program {
public static void main(String[] args) {
Program program = new Program();
int[] a = { 1, 0, 0, 1, 0, 1 };
int response = program.calculate(a);
System.out.println(response);
}
int calculate(int[] input) {
if(input == null || input.length == 0) {
return -1;
}
int length = input.length;
int result = 0;
for (int i = 0; i < length - 1; i++) {
if (input[i] == input[i + 1]) {
result = result + 1;
}
}
int temp = 0;
for (int i = 0; i < length - 1; i++) {
int count = 0;
if (i > 0) {
if (input[i - 1] != input[i]) {
count = count + 1;
} else {
count = count - 1;
}
}
if (i < length - 1) {
if (input[i + 1] != input[i]) {
count = count + 1;
} else {
count = count - 1;
}
}
temp = Math.max(temp, count);
}
return result + temp;
}
}
I was told the program is having some bugs but I was not able to find out where the issue is. I tried passing various values to this program but it is still working without issues. Can you please help me with some combination of inputs for which this program fails.
Well, it seems to be failing for
{ 0, 0, 0, 0, 0, 0, 1}; -> 5 but not {0, 1}; -> 1
{ 1, 0, 1}; -> 2
{ 1, 1, 1}; -> 2
{ 1,0,0,0,0,1,1,0,0,0}; -> 7

Java: How to implement 3 sum?

I'm studying the 3 Sum to implement it on my own, and came across the following implementation with the rules:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note: Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4},
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
And implementation (sorts the array, iterates through the list, and uses another two pointers to approach the target):
import java.util.*;
public class ThreeSum {
List<List<Integer>> threeSum(int[] num) {
Arrays.sort(num);
List<List<Integer>> res = new LinkedList<>();
for (int i=0; i<num.length-2; i++) {
if (i==0 || (i>0 && num[i] != num[i-1])) { //HERE
int lo = i+1;
int hi = num.length-1;
int sum = 0 - num[i];
while (lo < hi) {
if (num[lo] + num[hi] == sum) {
res.add(Arrays.asList(num[i], num[lo], num[hi]));
while (lo < hi && num[lo] == num[lo+1]) lo++; //HERE
while (lo < hi && num[hi] == num[hi-1]) hi--; //HERE
lo++; hi--;
} else if (num[lo] + num[hi] < sum) lo++;
else hi--;
}
}
}
return res;
}
//Driver
public static void main(String args[]) {
ThreeSum ts = new ThreeSum();
int[] sum = {-1, 0, 1, 2, -1, -4};
System.out.println(ts.threeSum(sum));
}
}
And my question is (located where commented: //HERE), what's the reason for checking num[i] != num[i-1], num[lo] == num[lo+1], and num[hi] == num[hi-1]? Supposedly they are supposed to skip the same result, but what does that mean? Examples would really help.
Thank you in advance and will accept answer/up vote.
Imagine you have {-1,-1,0,1,2,4} and considering triplet num[0], num[2], num[3] (-1,0,1).
lo=0 here. To exclude triplet num[1], num[2], num[3] with the same values, we should increment lo and pass over duplicate
This will prevent the list to have duplicate triplet.
For example, with you test :
int[] sum = {-1, 0, 1, 2, -1, -4};
will be sorted like :
sum = {-4, -1, -1, 0, 1, 2};
You see that you have -1 twice. Without these test, you would test twice if -1 = 0 + 1. This is not usefull so the algo simply search the next different value.
You could remove duplicate in the sorted List to prevent these test.
Thanks to MBo, we can't remove duplicate since we can have triplet with same value (but with different index)
All the three sentences is used to avoid the duplicate output.
Consider a sorted list {-2, -2 , 1, 1}
If there is no checking for num[i] != num[i-1], the output of the program would be(-2, 1, 1)and(-2, 1, 1), which are two duplicate triplets.
The checking for num[lo] != num[lo + 1]and num[hi] != num[hi - 1] are for the same reason.
Consider a sorted list
{-2,-1,-1,0,3}
If there is no checking for num[lo], you will get (-2,-1,3) and (-2,-1,3) as the output.
Still, I want to recommend a better solution for this problem. You can numerate the sum of two numbers in the list and find the 3rd number by hash or binary search. It will helps you to gain a O(n^2logn) time complexity rather than O(n^3). (I was wrong, the time complexity of this algorithm is O(n^2), sorry for that.)
Following program finds pairs of three integer with O(N*2)
Sort the input Array
and iterate each element in for loop and check for sum in program which is developed for Two sum.
Two sum in linear time after sorting ->
https://stackoverflow.com/a/49650614/4723446
public class ThreeSum {
private static int countThreeSum(int[] numbers) {
int count = 0;
for (int i = 0; i < numbers.length; i++) {
int front = 0, rear = numbers.length - 1;
while (front < rear) {
if (numbers[front] + numbers[rear] + numbers[i] == 0) {
System.out.printf(String.format("Front : {%d} Rear : {%d} I : {%d} \n", numbers[front],
numbers[rear], numbers[i]));
front++;
rear--;
count++;
} else {
if (Math.abs(numbers[front]) > Math.abs(numbers[rear])) {
front++;
} else {
rear--;
}
}
}
}
return count;
}
public static void main(String[] args) {
int[] numbers = { 1, 3, 5, 7, 12, 16, 19, 15, 11, 8, -1, -3, -7, -8, -11, -17, -15 };
Arrays.sort(numbers);
System.out.println(countThreeSum(numbers));
}
}
It's worked with any NSum (3Sum, 4Sum, 5Sum, ...) and quite fast.
public class ThreeSum {
private static final int RANDOM_RANGE = 20;
private Integer array[];
private Integer arrayIndex[];
private int result[];
private int bagLength;
private int resultIndex = 0;
private void generateData(int size) {
array = new Integer[size];
Random random = new Random();
for (int i = 0; i < size; i++) {
array[i] = random.nextInt(RANDOM_RANGE) - (RANDOM_RANGE/2);
}
}
private void markArrayIndex(int size) {
arrayIndex = new Integer[size];
for (int i = 0; i < size; i++) {
arrayIndex[i] = i;
}
}
private void prepareBeforeCalculate(int size, int sumExpected, int bagLength) {
this.bagLength = bagLength;
result = new int[bagLength];
generateData(size);
markArrayIndex(size);
}
void calculate(int size, int sumExpected, int bagLength) {
prepareBeforeCalculate(size, sumExpected, bagLength);
Arrays.sort(arrayIndex, (l, r) -> array[l].compareTo(array[r]));
System.out.println(Arrays.toString(array));
long startAt = System.currentTimeMillis();
if (sumExpected > 0) findLeft(sumExpected, 0, 0, array.length);
else findRight(sumExpected, 0, 0 - 1, array.length - 1);
System.out.println("Calculating in " + ((System.currentTimeMillis() - startAt) / 1000));
}
private void findLeft(int total, int indexBag, int left, int right) {
while (left < array.length && array[arrayIndex[left]] < 0 && indexBag < bagLength) {
navigating(total, arrayIndex[left], indexBag, left, right);
left++;
}
}
private void findRight(int total, int indexBag, int left, int right) {
while (right >= 0 && array[arrayIndex[right]] >= 0 && indexBag < bagLength) {
navigating(total, arrayIndex[right], indexBag, left, right);
right--;
}
}
private void navigating(int total, int index, int indexBag, int left, int right) {
result[indexBag] = index;
total += array[index];
if (total == 0 && indexBag == bagLength - 1) {
System.out.println(String.format("R[%d] %s", resultIndex++, toResultString()));
return;
}
if (total > 0) findLeft(total, indexBag + 1, left + 1, right);
else findRight(total, indexBag + 1, left, right - 1);
}
private String toResultString() {
int [] copyResult = Arrays.copyOf(result, result.length);
Arrays.sort(copyResult);
int iMax = copyResult.length - 1;
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(array[copyResult[i]]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
}
public class ThreeSumTest {
#Test
public void test() {
ThreeSum test = new ThreeSum();
test.calculate(100, 0, 3);
Assert.assertTrue(true);
}
}

Categories