Printing a box of numbers with perimeters that are the same value - java

I need series of for loops to return a box like below depending on the values of m & n.
Should output:
1 1 1 1 1 1 1
1 2 2 2 2 2 1
1 2 3 3 3 2 1
1 2 2 2 2 2 1
1 1 1 1 1 1 1
Below is my code so far which uses a series of loops to split the box in half and either ascends or descends the value for both the column and row. Where I am stuck is trying to find a way to make these perimeters for the values. Another note that this should be able to work without using any if statements.
int m = 5; //column value
int n = 7; //row value
int column;
for (int row = 0; row <= (m / 2); row++) {
//Ascending
for (column = 1; column < (n / 2); column++) {
int outputNumber = row + 1;
System.out.print(outputNumber + " ");
}
//Fixed
do {
int outputNumber = row + 1;
System.out.print(outputNumber + " ");
}
while (column < 0);
//Descending
for (column = n / 2; column >= 0; column--) {
int outputNumber = row + 1;
System.out.print(outputNumber + " ");
}
System.out.println();
}
for (int row = m / 2; row > 0; row--) {
for (column = 1; column <= n; column++) {
System.out.print(row + " ");
}
System.out.println();
}
Current output for the code above:
1 1 1 1 1 1 1
2 2 2 2 2 2 2
3 3 3 3 3 3 3
2 2 2 2 2 2 2
1 1 1 1 1 1 1

Here is my result. I know that it is a bit complicated and quick written, however it solves your problem. I also tested it with other numbers:
int m = 5; //column value
int n = 7; //row value
for (int i = 0; i < m / 2 + 1; i++) {
for (int j = 0; j < i + 1; j++) {
System.out.print(j + 1 + " ");
}
for (int j = 0; j < n - ((i + 1) * 2); j++) {
System.out.print(i + 1 + " ");
}
for (int j = 0; j < i + 1; j++) {
System.out.print(i + 1 - j + " ");
}
System.out.println("");
}
for (int i = m / 2 + 1; i < m; i++) {
for (int j = 0; j < m - i; j++) {
System.out.print(j + 1 + " ");
}
for(int j = 0; j < n - (m - i) * 2; j++) {
System.out.print(m-i + " ");
}
for(int j = 0; j < m - i; j++) {
System.out.print(m - i - j + " ");
}
System.out.println("");
}

Assuming my understanding is correct that the perimeter tiles should be 1, and subsequently each tile should display the minimum number of 'steps' it would take to get there from outside the matrix.
I personally have a hard time picturing/following your solution, so I'm not sure if my suggestion will mesh with your understanding.
First, lets separate the construction of this matrix from the printing of this matrix. I think this keeps things tidy, but that's my style.
Lets say you have c columns and r rows in your matrix. So we'll iterate over every cell with a nested for loop.
for (int r = 0; r < rows; r++) {
for (int c = 0; c < columns; c++) {
int distanceToEdgeOfRow = Math.abs(rows - (r - rows)); //this finds the number of steps to the nearest row end
int distanceToEdgeOfColumn = Math.abs(columns - (c - columns)); //this find the number of steps to the nearest column end
int shortestPath = Math.min(distanceToEdgeOfColumn, distanceToEdgeOfRow); //is it shorter to take the closest row exit or column exit?
//the shortestPath is still off by one, so we need to add 1 to shortestPath to see what should be printed on this tile
matrix[r][c] = shortestPath + 1;
}
}

Related

How to print a 2D array in java

Hello so am trying to create a 2D array of int with random number of rows and columns and a random starting and ending points using java to apply the A* algorithm on it.
When i add {S} and {E} to define the tow points and print it there are numbers outside of the 2D array printed.
`Random rand = new Random();
int min = 2, max = 10;
// a random number of rows and columns
int a = (int)(Math.random() * (max - min + 1)) + min;
// the location of the starting point.
int row_start = rand.nextInt(a);
int col_start = rand.nextInt(a);
// the location of the ending point.
int row_end = rand.nextInt(a);
int col_end = rand.nextInt(a);
int [][] M = new int [a][a];
public void create() {
//empty: 0; grass: 1; sand: 2; water: 3; wall: 4.
for (int i = 0; i < a; i++) {
for (int j = 0; j < a; j++) {
M[i][j] = rand.nextInt(5);
}
}
for (int i = 0; i < a; i++) {
for (int j = 0; j < a; j++) {
System.out.print(" " +M[i][j] + "\t");
if(row_start == i && col_start == j) {
System.out.print("{S}" + "\t");
}
if(row_end == i && col_end == j) {
System.out.print("{E}" + "\t");
}
}
System.out.print("\n");
}
}`
the output looks like this:
1 0 4 0
2 {S} 1 2 2
4 4 {E} 0 3
2 0 3 3
the 2 and 3 shouldn't appear there.
The problem is that you always print m[i][j].
What you need is to only print m[i][j] when i and j are not S and E positions. When i and j are S and E positions, print S or E. Otherwise, print m[i][j].
if(row_start == i && col_start == j) {
System.out.print("{S}" + "\t");
} else if(row_end == i && col_end == j) {
System.out.print("{E}" + "\t");
} else {
System.out.print(" " +M[i][j] + "\t");
}

Invert incrementing triangle pattern

I am writing some code that creates a incrementing number right angle triangle that looks something like this:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
I am unsure on how to make my code output a triangle to that shape as my code outputs the same thing except inverted.
This is the code I have:
public class Main {
public static void main(String[] args) {
int rows = 6;
for (int i = 1; i <= rows; ++i) {
for (int j = 1; j <= i; ++j) {
System.out.print(j + " ");
}
System.out.println();
}
}
}
My speculation is that instead of incrementing some of the values I would decrement them however the code would run infinite garbage values and not what I wanted.
It is needed to print some spaces before printing the numbers in each row, and the number of spaces should be decreasing depending on the row:
int rows = 6;
for (int i = 1; i <= rows; ++i) {
for (int j = rows - i; j >= 1; j--) {
System.out.print(" ");
}
for (int j = 1; j <= i; ++j) {
System.out.print(j + " ");
}
System.out.println();
}
This prefix may be build using String::join + Collections::nCopies:
System.out.print(String.join("", Collections.nCopies(rows - i, " ")));
Or since Java 11, this prefix may be replaced using String::repeat:
System.out.print(" ".repeat(rows - i));
Instead of two nested for loops, you can use a single while loop with two incrementing variables. The number of iterations stays the same.
int n = 7, i = 0, j = 0;
while (i < n) {
// element
if (i + j >= n - 1) {
// print an element
System.out.print(i + j + 2 - n);
} else {
// print a whitespace
System.out.print(" ");
}
// suffix
if (j < n - 1) {
// print a delimiter
System.out.print(" ");
j++;
} else {
// print a new line
System.out.println();
j = 0;
i++;
}
}
Output:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
See also: Optimized Bubble Sort
Your approach is almost correct - use two nested for loops, all that remains is to add one if else statement and calculate the sum of coordinates i and j.
Try it online!
public static void main(String[] args) {
int n = 6;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
System.out.print(" ");
int sum = i + j;
if (sum > n)
System.out.print(sum - n);
else
System.out.print(" ");
}
System.out.println();
}
}
Output:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
See also: Printing a squares triangle. How to mirror numbers?
You can print an inverted triangle using two nested for-loops as follows:
// the number of rows and the
// number of elements in each row
int n = 6;
// iterating over rows with elements
for (int i = 0; i < n; i++) {
// iterating over elements in a row
for (int j = 0; j < n; j++) {
// element
if (i + j >= n - 1) {
// print an element
System.out.print(i + j + 2 - n);
} else {
// print a whitespace
System.out.print(" ");
}
// suffix
if (j < n - 1) {
// print a delimiter
System.out.print(" ");
} else {
// print a new line
System.out.println();
}
}
}
Output:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
See also: How to draw a staircase with Java?
You have to print spaces before printing the numbers to make the triangle look inverted, the number of spaces depends on the amount of numbers you skip which are rows-i, so you can loop from i to rows and print space in each iteration.
int rows = 6;
for (int i = 1; i <= rows; ++i) {
for (int j = i; j < rows; j++) {
System.out.print(" ");
}
for (int j = 1; j <= i; ++j) {
System.out.print(j + " ");
}
System.out.println();
}
Output:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
You can use the property that for the row containing i as the greatest number of the row the number of the spaces can be calculated as 2*(rows-i). You can rewrite your program like below:
public class Main {
public static void main(String[] args) {
int rows = 6;
for (int i = 1; i <= rows; ++i) {
for (int nspaces = 0; nspaces < 2 * (rows - i); ++nspaces) {
System.out.print(" ");
}
for (int j = i; j > 0; --j) {
System.out.print(j + " ");
}
System.out.println();
}
}
}
Output:
1
2 1
3 2 1
4 3 2 1
5 4 3 2 1
6 5 4 3 2 1

Displaying a pyramid of number ladder

I did this below but I didn't get it right,
int i = 1;
while(i <= 6){
for(int j = 1;j <= 6-i;j++){
System.out.print(" ");
}
for(int m = 1; m <= i; m++){
System.out.print(m + " ");
}
i++;
System.out.println();
}
I got this instead :
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
But I need guide on how to get this below,
1
2 1 2
3 2 1 2 3
4 3 2 1 2 3 4
5 4 3 2 1 2 3 4 5
while(i <= 6){
for(int j = 1; j <= 6 - i; j++){
System.out.print(" ");
}
for(int m = i-1; m > 1; m--){
System.out.print(m + " ");
}
for(int m = 1; m < i; m++){
System.out.print(m + " ");
}
i++;
System.out.println();
}
This should work for you, i just added / edited this part:
for(int m = i-1; m > 1; m--){
System.out.print(m + " ");
}
for(int m = 1; m < i; m++){
System.out.print(m + " ");
}
To let it count down again, and let it count up afterwards
This should do the trick, but it's important to understand what is going on:
public class Main {
public static void main(String[] args) {
for (int i = 0; i <= 6; i++) {
printRow(6, i);
}
}
public static void printRow(int highestValue, int rowValue) {
for (int i = 0; i < (highestValue - rowValue); i++) {
System.out.print(" ");
}
for (int i = rowValue; i >= 1; i--) {
System.out.print(i + " ");
}
for (int i = 2; i <= rowValue; i++) {
System.out.print(i + " ");
}
System.out.println();
}
}
The first loop pads the left side of the pyramid, as you have already done. The second loop counts down from the value of the row to 1, which is the center of the pyramid. The third loop counts back up from 2 to the value of the row. Note that for the first row, 2 will not be printed, because i = 2 is greater than rowValue, which is 1, so the loop is skipped.
Running this results in the following:
1
2 1 2
3 2 1 2 3
4 3 2 1 2 3 4
5 4 3 2 1 2 3 4 5
6 5 4 3 2 1 2 3 4 5 6
Note that a row starting with 6 is printed since I used the bounds you provided. If this is not what should be done (from your example output), I will leave that up to you on how to fix this. Pay attention to the name of the arguments in the printRow method to see why there is an extra row printed.
There you have my solution, little smarty solution with using absolute value, with notes why is what where
public static void printPyramid(int rows) {
// row counter
for (int i = 1; i <= rows; i++) {
// padding- size = rows - i
for (int j = 1; j <= rows - i; j++) {
// 2 spaces - char + space
System.out.print(" ");
}
// print numbers
for (int j = -i; j <= i; j++) {
// we want only once 1, and skip print zero
if (j == 0 || j == 1) {
continue;
}
// print absolute value
System.out.print(Math.abs(j) + " ");
}
// new row- println same as print("\n");
System.out.println();
}
}
With 6 rows, output is
1
2 1 2
3 2 1 2 3
4 3 2 1 2 3 4
5 4 3 2 1 2 3 4 5
6 5 4 3 2 1 2 3 4 5 6
Let's break this down into parts. First we need to figure out how to output a single level of the pyramid. Let's start without padding. For the first level it's just "1", for every other level it's the level above it surrounded by the "number" of that level (and the spaces).
private static String buildLevel(int num) {
if (num == 1) return "1";
return Integer.toString(num) + " " + buildLevel(num -1) + " " + Integer.toString(num);
}
We then need to be able to add the padding, so let's create a method that pads to a certain length.
private static String pad(String stringToPad, int padTo) {
return String.join("", Collections.nCopies(padTo - stringToPad.length(), " ")) + stringToPad;
}
Putting this together we can create a method to build a pyramid by looping over the needed levels and concatenating the levels together.
private static String buildPyramid(int height) {
int expectedLength = height * 2 + 1;
String out = "";
for (int i = 1; i <= height; i++) {
out += pad(buildLevel(i), expectedLength) + "\n";
expectedLength += 2;
}
return out;
}
The length of the first line is the height * 2 + 1, derived by counting. (This includes two spaces at the beginning of each line, which is in your examples). Each subsequent line should be 2 longer than the one above it.
Call it like this to produce your example
public static void main(String[] args) {
System.out.println(buildPyramid(5));
}
Outputs:
1
2 1 2
3 2 1 2 3
4 3 2 1 2 3 4
5 4 3 2 1 2 3 4 5
For completeness, here is all the code in one block.
private static String buildLevel(int num) {
if (num == 1) return "1";
return Integer.toString(num) + " " + buildLevel(num -1) + " " + Integer.toString(num);
}
private static String pad(String stringToPad, int padTo) {
return String.join("", Collections.nCopies(padTo - stringToPad.length(), " ")) + stringToPad;
}
private static String buildPyramid(int height) {
int expectedLength = height * 2 + 1;
String out = "";
for (int i = 1; i <= height; i++) {
out += pad(buildLevel(i), expectedLength) + "\n";
expectedLength += 2;
}
return out;
}
public static void main(String[] args) {
System.out.println(buildPyramid(6));
}

Rotating sequential numbers to right

Its easy enough to rotate numbers to the left. I would do the following:
int numberCount = 4;
int rotationCount = 2 * numberCount;
for(int i = 0; i < rotationCount; i++)
{
for(int j = 0; j < numberCount; j++)
{
System.out.print((i+j) % numberCount + " ");
}
System.out.println();
}
In this example the following would be printed:
0 1 2 3
1 2 3 0
2 3 0 1
3 0 1 2
0 1 2 3
1 2 3 0
2 3 0 1
3 0 1 2
How would you do the same thing, but rotating the numbers to the right?
The answer was obvious once I thought about it-- to move a number left, you add to it, so to move right, you subtract from it. I thought the formula would be significantly changed, so I was thinking of formulas that were much more complicated than the solution turned out to be.
// ensures mod is positive
int mod(int a, int b)
{ return (a%b+b)%b; }
int numberCount = 4;
int rotationCount = 2 * numberCount;
for(int i = 0; i < rotationCount; i++)
{
for(int j = 0; j < numberCount; j++)
{
System.out.print(mod((j-i), numberCount) + " ");
}
System.out.println();
}

Is there a way to combine incrementing and decrementing for loops?

int j = 0;
for (int i = 1; i < 4; i++)
{
if ((columnIndex + i) > 6 || this.isWinningCondition(columnIndex, i, j, colSlot, isRed))
{
break;
}
else
{
pieces++;
}
}
for (int i = -1; i > -4; i--)
{
if ((columnIndex + i) < 0 || this.isWinningCondition(columnIndex, i, j, colSlot, isRed))
{
break;
}
else
{
pieces++;
}
}
Basically, it is apart of a Connect4 program that searches for three in a row on the left and right side of a specific column (in this case, it is searching for horizontal wins), hence the incrementing (for the right side) and the decrementing (for the left side) for loops. Is there a way I can combine these for loops into one, so I don't have to repeat myself?
If your MaxValue ( 4 )is always the same for both for loop, you can always do :
for( int i = 1; i < 4; ++i)
{
//verify i version 1
int i2 = i * -1;
// verify i2 version 2
}
Try the mixed for loop.
for(int i = 0, j = 4; i <= 4 && j >=0; i ++, j --)
{
System.out.println(i + " " + j);
}
Output:
0 4
1 3
2 2
3 1
4 0

Categories