Java Integer Pyramid

2k views Asked by At

I'm working on an assignment that asks a user to input an integer between 1-15 and then displays an integer pyramid for the number of rows they selected.

I have everything working, but if the number enters an integer greater than 10, I'm getting tripped up by the extra space needed for a double digit number. I've attached my code below. If anyone could provide a little help it would be greatly appreciated.

int lines = input.nextInt();
for (int row = 1; row <= lines; row++)
{
    for (int column = 1; column <= lines - row; column++) 
    {
        System.out.print("  ");
    }
    for (int num = row; num >= 1; num--)
    {
        System.out.print((num>=10)?+num:" "+num);
    }
    for (int num = 2; num <= row; num++)
    {
        System.out.print((num>=10)?+num:" "+num);
    }
    System.out.println();
}

With my current code, if the user entered 13, it would produce the following output:

                         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
             7 6 5 4 3 2 1 2 3 4 5 6 7
           8 7 6 5 4 3 2 1 2 3 4 5 6 7 8
         9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9
       10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 910
     11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11
   12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12
 13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13

I just need to figure out how to get the extra space for the double digit integers. The desired output would be:

                         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
             7 6 5 4 3 2 1 2 3 4 5 6 7
           8 7 6 5 4 3 2 1 2 3 4 5 6 7 8
         9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9
      10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10
   11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11
12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12
5

There are 5 answers

3
Scott Sosna On

You've got the conditional backwards, believe it should be

System.out.print((num >= 10) ? " " + num : num)

Easier to understand

System.out.print((num < 10) ? num : num : " " + num)
9
Greg Hewgill On

It looks like you have chosen to do this the (slightly) harder way.

The easy way would be to reserve three spaces for each number (so that single digit numbers would have two spaces between them).

What you have chosen to do is variable spacing depending on the actual length of the numbers in each column. The first step is to change your output statements to the following:

    System.out.print(" "+num);

So you will always print one space between numbers on each row. If you run that, you'll notice that it almost works except the top part of the triangle is misaligned. To fix that, you'll have to adjust your

    System.out.print("  ");

statement so that the number of spaces it prints in each column depends on the value of the number that will appear in each column later on. To do this, you'll have to work out some arithmetic involving column and lines, to choose between " " (two spaces) and " " (three spaces). It's straightforward but I'll let you work out the details.

It is possible to further extend this idea to support 100 lines or more, but it's not clear that you need that capability.

1
user3707125 On

I was interested in solving this, so wrote a simple solution for your task. Seems to work for any lines value.

public static void main(String[] args) {
    int lines = 100;
    for (int row = 1; row <= lines; row++) {
        for (int i = 0; i < calculateOffset(row, lines); i++) {
            System.out.print(" ");
        }
        System.out.print(row);
        for (int num = row-1; num >= 1; num--) {
            System.out.print(" " + num);
        }
        for (int num = 2; num <= row; num++) {
            System.out.print(" " + num);
        }
        System.out.println();
    }
}

private static int calculateOffset(int row, int totalRows) {
    return calculateSpace(totalRows) - calculateSpace(row);
}

private static int calculateSpace(int columnsCount) {
    int categoryLowest = 1;
    int categoryHighest = 9;

    int categoryDigits = 1;

    int charactersUsed = 0;

    while (categoryLowest <= columnsCount) {
        int categoryItems = Math.min(categoryHighest, columnsCount) - categoryLowest + 1;

        int numbersCharacters = categoryDigits * categoryItems;
        int spacesCharacters = (categoryItems - 1);
        boolean previousCategoryIncluded = categoryLowest > 1;
        int spaceBetweenCategoriesPresent = previousCategoryIncluded ? 1 : 0;

        charactersUsed += numbersCharacters + spacesCharacters + spaceBetweenCategoriesPresent;

        categoryHighest = categoryHighest * 10 + 9;
        categoryLowest *= 10;
        categoryDigits++;
    }
    return charactersUsed;
}
3
Adrian Shum On

No idea why you chose the logic like that. However, intuitively, this is what I am going to do:

1 find mid point location (you can simply contruct the last line and find the mid-point)

2 a function to construct a line, by simply do (psuedo-code):

String getLine(int num) {
  String result = "";
  for (int i = num; i > 0; i--) {
    result = result + i + " "; 
  }
  for (int i = 2; i <= num; i++) {
    result = result + i + (i == num? "" : " ");
  }
  return result;
}

3 do a loop to print each line:

int midPoint = .....; //
for (i=0; i < num; i++) {
    String line = getLine(i+1);
    print (midPoint - mid point of line) spaces;
    print line
}

Update:

Have briefly tested, looks good to me:

public static String getLine(int num) {
    String result = "";
    for (int i = num; i > 0; --i) {
        result = result + i + " ";
    }
    for (int i = 2; i <= num; ++i) {
        result = result + i + (i == num ? "" : " ");
    }
    return result;
}
public static void main(String[] args) {
    int num = 15;
    int midPoint = getLine(num).length()/2 + 1;

    for (int i = 0; i < num; ++i) {
        String line = getLine(i+1);
        int noPrefix = midPoint - (line.length()+1)/2 ;
        for (int j = 0; j < noPrefix; ++j) {
            System.out.print(" ");
        }
        System.out.println(line);
    }
}

result :

                                  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
                      7 6 5 4 3 2 1 2 3 4 5 6 7
                    8 7 6 5 4 3 2 1 2 3 4 5 6 7 8
                  9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9
               10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10
            11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11
         12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12
      13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13
   14 13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0
almightyGOSU On

Late to the party, but here's a solution using StringBuilder and printing it out only at the end.

The idea is to calculate the amount of padding required based on the String equivalent of the current value.
Note: The solution is not efficient (with all the conversion to String), but it can be used for any input value.

Working Example:

import java.util.Scanner;

public class IntegerPyramid {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        System.out.print("Enter # of lines: ");
        int numLines = sc.nextInt();

        StringBuilder sb = new StringBuilder();
        System.out.println();

        for(int row = 1; row <= numLines; row++) {

            for(int num = -numLines; num <= numLines; num++) {
                if(num == -1 || num == 0)
                    continue;

                int value = Math.abs(num);
                int padding = String.valueOf(value).length() + 1;

                if(value <= row) {
                    // Print numbers
                    sb.append(String.format(("%" + padding + "d"), value));
                }
                else {
                    // Print spaces
                    sb.append(String.format(("%" + padding + "s"), ""));
                }
            }
            sb.append("\n");
        }

        System.out.println(sb.toString());
        sc.close();
    }
}

Output:

Enter # of lines: 6

           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

Enter # of lines: 15

                                   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                        
                       7 6 5 4 3 2 1 2 3 4 5 6 7                      
                     8 7 6 5 4 3 2 1 2 3 4 5 6 7 8                    
                   9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9                  
                10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10               
             11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11            
          12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12         
       13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13      
    14 13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14   
 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15