# Printing star greater symbol in Java

Posted on

Problem

I need to print this in Java, but I feel that my code is too big:

``````*
**
***
****
***
**
*
``````
``````public static void main(String[] args) {

for(int i=0; i<=3; i++) {
for(int j=0; j<=i; j++) {
System.out.print("*");
}
System.out.println();
}

for(int j=1; j<=3; j++) {
for(int i=3; i>=j; i--) {
System.out.print("*");
}
System.out.println();
}
}
``````

Solution

Here is a lovely way to do it using only one nested for-loop:

``````for (int i = 0; i < 7; i++) {
for (int numStars = 0; numStars < 4 - Math.abs(3 - i); numStars++) {
System.out.print("*");
}
System.out.println();
}
``````

This uses the Math.abs function to perform the calculation of how many stars to print.

If we take a look at a plot of the classic Math.abs we can see that it looks useful. We need to flip it upside-down though, this is done by taking `4 - abs(x)` which would look like this. Finally, we need to switch it to the right a bit, so we modify the input to the function call and end up with this: 4 – abs(3 – x)

Images courtesy of wolframalpha.com

### 4-abs(3 – x)

Finally, here is a very flexible solution, which also works with even numbers:

``````int rows = 20;
double maximumValue = Math.ceil(rows / 2.0);
double shifted = maximumValue - 1;
for (int i = 0; i < rows; i++) {
int count = (int) (maximumValue - Math.abs(shifted - i));
if (i >= rows / 2 && rows % 2 == 0) // slight fix for even number of rows
count++;

for (int numStars = 0; numStars < count; numStars++) {
System.out.print("*");
}
System.out.println();
}
``````

This will output:

``````*
**
***
****
*****
******
*******
********
*********
**********
**********
*********
********
*******
******
*****
****
***
**
*
``````

You’ve hard-coded `3` in three places. Yet, the output contains a row with four stars. That’s underhanded programming. The culprit is this line:

``````for(int j=0; j<=i; j++)
``````

Idiomatic Java would be either

``````for (int j = 0; j < somelimit; j++)
``````

or

``````for (int j = 1; j <= somelimit; j++)
``````

I also find the way that you interchanged `i` and `j` between the first and second halves of the program disconcerting.

Surely you should define a function that accepts a parameter. What varies? The fill character? The size? Otherwise, the simplest solution would be

``````public static void main(String[] args) {
System.out.println("*n**n***n****n***n**n*");
}
``````

I am in favour of keeping two for-loops, one increasing and one decreasing. Combining those into one loop would likely make it difficult to see the intent at a glance. As for how you generate each line of n stars, though, it’s not particularly interesting how you accomplish it. I’ve chosen a one-line hack for the solution below, but you may wish to pick a more traditional approach.

``````private static String repeat(String s, int n) {
// A bit of a hack, and not very efficient.  Feel free to reimplement.
return String.format("%" + n + "s", "").replaceAll(" ", s);
}

public static void printArrow(String fill, int width, PrintStream out) {
for (int i = 1; i < width; i++) {
out.println(repeat(fill, i));
}
for (int i = width; i >= 1; i--) {
out.println(repeat(fill, i));
}
}

public static void main(String[] args) {
printArrow("*", 4, System.out);
}
``````

You don’t need a loop for this.

``````public static void main(String[] args) {
String ln = System.getProperty("line.separator");
System.out.println("*" + ln
+  "**" + ln
+  "***" + ln
+  "****" + ln
+  "***" + ln
+  "**" + ln
+  "*");
}
``````

Using multiple `print("*")` calls for each star is very inefficient. Print is a slow command, and it also makes what is a relatively simple process (printing a line of stars) become a more complicated loop.

A more efficient way to output the triangle would be to use one `println` per line. An even better way would be for one println for the whole puzzle, but that has a potential issue of the `n` value is large.

A real trick here would be to build up one String value for the longest line, and then just print substrings for the shorter ones.

Note, using `Math.abs(...)` is a clever way to manipulate the substring, but combining it with a loop from `negative width` to `positive width` makes it even easier to understand.

Additionally, putting the code in to its own method, instead of the main method, makes the code more reusable.

``````public static final void triangle(int width) {
String longest = buildLine(width, '*');

for (int i = -width + 1; i < width; i++) {
System.out.println(longest.substring(Math.abs(i)));
}
}

private static String buildLine(int width, char c) {
char[] chars = new char[width];
Arrays.fill(chars, c);
return new String(chars);
}

public static void main(String[] args) {
triangle(5);
}
``````