0

Input: base=2, row = 3
Output:

   **
  ****
********

Input: base=3, row = 3
Output:

            ***
         *********
***************************

I have tried this way, but I spaces aren't printing properly.

import java.util.Scanner;

public class loops {
    public static void main(String[] args) {
        Scanner s=new Scanner(System.in);
        System.out.println("enter base:");
        int base = s.nextInt();

        System.out.println("enter height:");
        int h = s.nextInt(); 


        for (int i = 1; i <= h; i++) {

            int num = (int)Math.pow(base, i);
                for(int n=h-1; n>i-1; n--) {
                        System.out.print(" ");

                  }

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

            System.out.println("");
        }
    }
}
Justin
  • 24,288
  • 12
  • 92
  • 142
Nayeem Sarwar
  • 134
  • 11

3 Answers3

1
import java.util.Scanner;

public class loops {
    public static void main(String[] args) {
        Scanner s=new Scanner(System.in);
        System.out.println("enter base:");
        int base = s.nextInt();

        System.out.println("enter height:");
        int h = s.nextInt();

        int spacesNum;
        int asterisksNum;

        for (int i = 1; i <= h; i++) {

            spacesNum = (int) ((Math.pow(base, h) - Math.pow(base, i)) / 2);
            asterisksNum = (int) (Math.pow(base, i));

            for (int j = 0; j < spacesNum; j++) {
                System.out.print(" ");
            }

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

            System.out.println();

        }

        s.close();
    }
}
zbr
  • 6,860
  • 4
  • 31
  • 43
0

The width of space grows geometrically, just like the width of the rings, but in the opposite direction -- it's decaying. Probably the easiest way to code it is to think about the total width, and what you're taking away from it with each ring.

Your code with that taken into account:

public class loops {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        System.out.println("enter base:");
        int base = s.nextInt();

        System.out.println("enter height:");
        int h = s.nextInt();
        int width = (int) Math.pow(base, h); // Note the total width.

        for (int i = 1; i <= h; i++) {
            int num = (int) Math.pow(base, i);

            // The space is half of what's left after removing the ring.
            for(int j = 0; j < (width - num)/2; j++) {
                 System.out.print(" ");
            }

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

            System.out.println("");
        }
    }
}
dahc
  • 534
  • 5
  • 6
0

Your code calls System.out.print method exponential times, one call per character.

Also, System.out.println is invoked in every iteration which causes the underlying stream to flush. (refer links from michaelt in the comments).

This SO answer is a good reference.

This is NOT good approach because:

  1. h number of I/O operations are performed, which is expensive.
  2. So many method invocations of print and println reduces the readability of the code.

Compose the strings in a separate method and use System.out.print only for printing.

Please refer the code below:

    public static void main(String[] args) {
        //your code here

    int totalWidth  = (int) Math.pow(base, h);
    String output = "";

    for (int i = 1; i <= h; i++) {
        int numOfStars = (int) Math.pow(base, i);
        int numOfSpace = (int) ((totalWidth - numOfStars) / 2);
        output += composeString(' ', numOfSpace).concat(composeString('*', numOfStars ).concat("\n"));
    }
    System.out.println(output);
    }


    //Method to create String with same character repeated X number of times
    public static String composeString(char character, int x) {
        StringBuilder buf = new StringBuilder(x);
        while (buf.length() < x) {
            buf.append(character);
        }
        return buf.toString();
    }
Community
  • 1
  • 1
Infinite Recursion
  • 6,511
  • 28
  • 39
  • 51
  • 1
    If you are concerned about performance... Builder rather than Buffer. Use the StringBuilder(int) constructor rather than "". Append rather than insert. –  Dec 11 '13 at 06:10
  • 1
    In particular - the difference between [append](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/AbstractStringBuilder.java#AbstractStringBuilder.append%28char%29) and [insert](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/AbstractStringBuilder.java#AbstractStringBuilder.insert%28int%2Cchar%29) is a System.arrayCopy in the `insert` call, which is *very* expensive. –  Dec 11 '13 at 06:16
  • 1
    Its an improvement. You might want to read about the [BufferedStream](http://docs.oracle.com/javase/tutorial/essential/io/buffers.html) and the [PrintStream](http://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html) - the stream isn't flushed with a call to `System.out.print` unless that contains a '\n'. Until then, the data passed into it is buffered, much the same as a StringBuffer. Not as optimal as building the string beforehand and then sending it in one go, but it is not doing IO with each System.out.print invocation. –  Dec 11 '13 at 17:38
  • @MichaelT As all the posts in this thread including OP's code calls `println` at in every iteration causing the stream to flush, I should have been more explicit about it, edited answer. Thanks again :-) – Infinite Recursion Dec 12 '13 at 03:37