Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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();
    }
}
share|improve this question
up vote 27 down vote accepted

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(x)

enter image description here

4-abs(3 - x)

enter image description here

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:

*
**
***
****
*****
******
*******
********
*********
**********
**********
*********
********
*******
******
*****
****
***
**
*
share|improve this answer
    
Thanks for the code. – user3272408 Feb 4 '14 at 21:06
18  
This is an excellent answer. I am disappointed that @user3272408 was apparently only interested in the code. – MirroredFate Feb 5 '14 at 1:58
9  
+5 for charts and graphs! Letterman would be proud. – David Harkness Feb 5 '14 at 4:09

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);
}
share|improve this answer

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
                        +  "*");
}
share|improve this answer
3  
That is overkill: System.out.println("*\n**\n***\n****\n***\n**\n*"); Seriously, what were you thinking? ;-) ! – rolfl Feb 5 '14 at 0:54
3  
@rolfl: But it looks like the output itself! ;-) – Jamal Feb 5 '14 at 0:57

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);
}
share|improve this answer

protected by Jamal Aug 27 '15 at 3:31

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.