Drawing an X shape with using only asteriks and recursion - java

Consider this code.
public static void patternMaker(int start, int max, int direction) {
if (start == 0) {
return;
}
for (int i = 0; i < start; i++) {
System.out.print("*");
}
System.out.println();
if (start == max) {
direction = -1;
}
patternMaker(start +direction, max, direction);
The output looks like this.
Where I need it to look like this
So I basically need the same thing but from the other side,and I need to move one space to the right and every new line.I am not sure how to produce that,I've tried duplicating the direction to get the other part of the X but that did not work out.Also not sure how to move one space to the right every line,I'd assume id need to adjust the direction on every iteration but missing a good idea.Thanks!

When using recursion is required, here is a solution based on your provided code example:
I outsourced the printing-part into a separate method.
public static void patternMaker(int max) {
patternMaker(1, max, 1);
}
public static void patternMaker(int numOfStars, int max, int direction) {
if (numOfStars == 0) {
return;
}
if (numOfStars == max) {
//print the maximum number of stars also before the middle
printPatternLine(numOfStars, max, false);
//print middle part twice
printPatternLine(numOfStars, max, true);
printPatternLine(numOfStars, max, true);
direction = -1;
}
printPatternLine(numOfStars, max, false);
patternMaker(numOfStars + direction, max, direction);
}
private static void printPatternLine(int numOfStars, int max, boolean middle) {
int spacesBefore;
int spacesBetween;
if(middle) {
spacesBefore = numOfStars;
spacesBetween = 0;
} else {
spacesBefore = numOfStars -1;
if(numOfStars == max) {
spacesBetween = 2;
} else {
spacesBetween = (max - numOfStars) * 4 + 2;
}
}
//print the spaces before the stars
for (int i = 0; i < spacesBefore; i++) {
System.out.print(" ");
}
//print first part of stars
for (int i = 0; i < numOfStars; i++) {
System.out.print("*");
}
//print spaces between the stars
for (int i = 0; i < spacesBetween; i++) {
System.out.print(" ");
}
//print second part of stars
for (int i = 0; i < numOfStars; i++) {
System.out.print("*");
}
//linebreak
System.out.println();
}
In the middle section of the X-drawing, the printPatternLine is called multiple times, to print this amount of stars a total of four times for this call of the patternMaker method.
A short explanation of the printPatternLine method:
The spaces before printing the stars and the spaces between the stars are calulated before
The case for the middle section should be self-explaining (no spaces between, spaces before equal to the number of stars)
For the non-middle part
The number of spaces before the stars relates to the position of the first stars for this line (for 1 * no space is printed, for 2 stars 1 space is printed, ...)
The number of spaces between the stars is 2 for the line which is one above the middle (1 space more on each side, 1 star more on each side). For every line that is one line farther away from the middle, the spaces in the middle increases by 4.
If you execute the patternMaker method with only one parameter by calling
patternMaker(3);
it will print this pattern:
* *
** **
*** ***
******
******
*** ***
** **
* *
If you need spaces between the stars, multiply the number of spaces by 2 in front of the for loops and add one space to the star-output like this:
private static void printPatternLine(int numOfStars, int max, boolean middle) {
//...
spacesBefore *= 2;
spacesBetween *= 2;
//...
for (int i = 0; i < numOfStars; i++) {
System.out.print("* ");
}
//...
for (int i = 0; i < numOfStars; i++) {
System.out.print("* ");
}
//...
}
Here is an example-output of patternMaker(3); with spaces:
* *
* * * *
* * * * * *
* * * * * *
* * * * * *
* * * * * *
* * * *
* *
Edit: An adaption, if the middle part should contain more stars than the line before and after it, is easily possible.

Related

how do i change my output from horizontal to vertical in java?

I need to write a function that takes an array and prints '*' for each index by the value of the index
for example for 1,2,3,4 the output will look like this:
enter image description here
but my output is vertical
1
2
3
4
this is my printing code :
public static void printStars(int[] a) {
for (int i = 0; i < a.length; i++) {
for (int j = 1; j <= a[i]; j++)
System.out.print("*");
System.out.println(" " + a[i]);
}
}
[edit] try the following:
public static void printStars(int[] a) {
int maxValue = Collections.max(Arrays.stream(a).boxed().toList());
String[] line = new String[a.length]; //this also works
for (int i = maxValue; i >=0 ; i--) {
//String[] line = new String[a.length]; //this will keep allocating new memory
for (int j = 0; j < a.length; j++) {
if (i == 0) {
line[j] = String.valueOf(j+1); //<change j+1 to a[j] in order to print out the value at each index of the array if you are not looking to print indexes
}else if (a[j] >= i) {
line[j] = "*";
}else {
line[j] = " ";
}
}
System.out.println(String.join(" ", line));
}
}
it takes the maximum value in the array and stores in a variable. This is used to iterate each line. After that, it checks if at this current iteration, does an index of your array contain an asterisk in this location? if yes, assign asterisk to the specific index of the string array corresponding to index of original array, else assign whitespace.
Finally, when it goes to 0, you assign the either the values of your array or the indexes of the array to the string[]. Then you print the array by using String.join() with a delimiter of whitespace. This allows you to focus on white index contains a whitespace or not, and not need to focus on the formatting of whitespaces in between each item.
for the input [1,2,3,4] output is:
*
* *
* * *
* * * *
1 2 3 4
for the input [1,7,3,4]:
*
*
*
* *
* * *
* * *
* * * *
1 2 3 4
The solution from the previous answer works but I provided a slightly more compact version printStars and renamed the old one to printStarsOld. Here is the code:
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class IntTest {
public static void printStarsOld(int[] a) {
int maxValue = Collections.max(Arrays.stream(a).boxed().toList());
String[] line = new String[a.length]; //this also works
for (int i = maxValue; i >= 0; i--) {
for (int j = 0; j < a.length; j++) {
if (i == 0) {
line[j] = String.valueOf(j + 1);
} else if (a[j] >= i) {
line[j] = "*";
} else {
line[j] = " ";
}
}
System.out.println(String.join(" ", line));
}
}
public static void printStars(int[] a) {
List<Integer> list = Arrays.stream(a).boxed().toList();
StringBuffer string = new StringBuffer();
Integer max = list.stream().max(Integer::compare).get();
for (int i = max; i > 0; i--) {
int finalI = i;
list.forEach(integer -> string.append(integer - finalI < 0 ? ' ' : '*').append(' '));
System.out.println(string.toString());
string.setLength(0);
}
for (Integer i=1; i<=list.size();i++) System.out.print(i.toString() + ' ');
}
#Test
public void test() {
System.out.println("Old output: ");
printStarsOld(new int[]{2, 4, 5, 1, 3});
System.out.println("New output: ");
printStars(new int[]{2, 4, 5, 1, 3});
}
}
The output is:
Old output:
*
* *
* * *
* * * *
* * * * *
1 2 3 4 5
New output:
*
* *
* * *
* * * *
* * * * *
1 2 3 4 5

Cannot get JOptionPane to show results of a parallel array

I have this code here that in the end few lines is supposed to return my results through a JOptionPane window,
for(int i = 0; i < 10; i++) {
percent[i] = ((double)counts[i] / amount) * 100;
}
//create results
// results starting out is just the numbers. Remove the code from the for loop above that does that,
// and instead use a for loop and go through both arrays creating the output string results with
// the count and percentage of each of the 10 numbers one per line.
results = String.format("%-10s%-10s%-10s\n*****************************************\n", "Numbers:", "Count:","Percentage:");
for(int i = 0; i < 10; i++) {
int number = i + 1;
results += String.format("%-10s%-10s%-10s\n", number, counts[i], percent[i]);
}
results = results + "\n\nRepeat this? Yes or No";
// show results in a confirm dialog that will also control the loop
choice = JOptionPane.showConfirmDialog(null, results, "Results", 0);
}
but in turn just repeats the initial window requesting the input amount of random numbers. Am I over looking an issue?
Here is the whole code:
/* RandomCounts.java
*
* generates a certain amount of random numbers between 1 and 10
*
* Modify this code as follows:
*
* As is, this code just outputs the random numbers to a dialog box.
*
* Create two arrays where indicated: counts (int) and percents (double). Each of size 10
*
* initialize counts where indicated
*
* update counts where indicated, and remove code that updates results
*
* calculate percentages using a for loop where indicated
*
* output both arrays where indicated
*
* Remember: arrays are zero based. Your arrays of size 10 will have indices 0-9, NOT 1-10
*/
import java.awt.Font;
import javax.swing.*;
public class RandomCountsStart {
public static void main(String[] args) {
UIManager.put("OptionPane.messageFont", new Font(Font.MONOSPACED, Font.BOLD, 24));
int[] counts = new int[10];
double[] percent = new double[10];// Declare the arrays counts and percents here
int num = 0, amount = 0, choice=0;
String results;
while (choice == 0){
for(int i = 0; i < 10; i++){
counts[i] = 0;
}// initialize counts here using a for loop
String input = JOptionPane.showInputDialog(null, "Input the amount of random numbers to generate");
amount = Integer.parseInt(input);
results = "";
// generate the numbers in a for loop
for(int i = 1; i <= amount; i++){
num = (int)(Math.random()*10) + 1;
}
// here is where you should update the array counts based on which num was generated
// for example: if num is 3, update the array element that counts 3's
if(num == 1) {
counts[0]++;
}
else if(num == 2) {
counts[1]++;
}
else if(num == 3) {
counts[2]++;
}
else if(num == 4) {
counts[3]++;
}
else if(num == 5) {
counts[4]++;
}
else if(num == 6) {
counts[5]++;
}
else if(num == 7) {
counts[6]++;
}
else if(num == 8) {
counts[7]++;
}
else if(num == 9) {
counts[8]++;
}
else if(num == 10) {
counts[9]++;
}
}
// calculate percentages
// go through the count array and determine the percentage of each value. Store the
// percentage in the appropriate element in percents (parallel array example)
for(int i = 0; i < 10; i++) {
percent[i] = ((double)counts[i] / amount) * 100;
}
//create results
// results starting out is just the numbers. Remove the code from the for loop above that does that,
// and instead use a for loop and go through both arrays creating the output string results with
// the count and percentage of each of the 10 numbers one per line.
results = String.format("%-10s%-10s%-10s\n*****************************************\n", "Numbers:", "Count:","Percentage:");
for(int i = 0; i < 10; i++) {
int number = i + 1;
results += String.format("%-10s%-10s%-10s\n", number, counts[i], percent[i]);
}
results = results + "\n\nRepeat this? Yes or No";
// show results in a confirm dialog that will also control the loop
choice = JOptionPane.showConfirmDialog(null, results, "Results", 0);
}
}
so i've updated your code to include up until choice = JOptionPane.showConfirmDialog(null, results, "Results", 0); in your while loop.
/* RandomCounts.java
*
* generates a certain amount of random numbers between 1 and 10
*
* Modify this code as follows:
*
* As is, this code just outputs the random numbers to a dialog box.
*
* Create two arrays where indicated: counts (int) and percents (double). Each of size 10
*
* initialize counts where indicated
*
* update counts where indicated, and remove code that updates results
*
* calculate percentages using a for loop where indicated
*
* output both arrays where indicated
*
* Remember: arrays are zero based. Your arrays of size 10 will have indices 0-9, NOT 1-10
*/
import java.awt.Font;
import javax.swing.*;
public class RandomCountsStart {
public static void main(String[] args) {
UIManager.put("OptionPane.messageFont", new Font(Font.MONOSPACED, Font.BOLD, 24));
int[] counts = new int[10];
double[] percent = new double[10];// Declare the arrays counts and percents here
int num = 0;
int amount = 0;
int choice=0;
String results;
while (choice == 0){
for(int i = 0; i < 10; i++){
counts[i] = 0;
}// initialize counts here using a for loop
String input = JOptionPane.showInputDialog(null, "Input the amount of random numbers to generate");
amount = Integer.parseInt(input);
results = "";
// generate the numbers in a for loop
for(int i = 1; i <= amount; i++){
num = (int)(Math.random()*10) + 1;
}
// here is where you should update the array counts based on which num was generated
// for example: if num is 3, update the array element that counts 3's
if(num == 1) {
counts[0]++;
}
else if(num == 2) {
counts[1]++;
}
else if(num == 3) {
counts[2]++;
}
else if(num == 4) {
counts[3]++;
}
else if(num == 5) {
counts[4]++;
}
else if(num == 6) {
counts[5]++;
}
else if(num == 7) {
counts[6]++;
}
else if(num == 8) {
counts[7]++;
}
else if(num == 9) {
counts[8]++;
}
else if(num == 10) {
counts[9]++;
}
// calculate percentages
// go through the count array and determine the percentage of each value. Store the
// percentage in the appropriate element in percents (parallel array example)
for(int i = 0; i < 10; i++) {
percent[i] = ((double)counts[i] / amount) * 100;
}
//create results
// results starting out is just the numbers. Remove the code from the for loop above that does that,
// and instead use a for loop and go through both arrays creating the output string results with
// the count and percentage of each of the 10 numbers one per line.
results = String.format("%-10s%-10s%-10s\n*****************************************\n", "Numbers:", "Count:","Percentage:");
for(int i = 0; i < 10; i++) {
int number = i + 1;
results += String.format("%-10s%-10s%-10s\n", number, counts[i], percent[i]);
}
results = results + "\n\nRepeat this? Yes or No";
// show results in a confirm dialog that will also control the loop
choice = JOptionPane.showConfirmDialog(null, results, "Results", 0);
}
}
}

how to print " * " n number of times using while loop?

public class Hello {
public static void pattern() {
int s1 = 3;
while(s1 >= 1) {
System.out.println("*");
s1--;
}
}
public static void main(String [] args){
pattern();
}
}
Actual output:
*
*
*
Expected output:
* * *
* *
*
I would like to print " * " (like the above-expected output) using while loop. I made a while loop controlling the number of columns. I'm not able to make a while loop to control the rows to output "*" in the same line 3 times (next line 2 times and so on).
With just you one loop and some String.repeat() you can draw your pattern
Repeat the leading space, starting and 0, and one more each round
Repeat the pattern depending ong s1, 3 times, then 2 then 1
public static void pattern() {
int s1 = 3;
int s2 = 0; // space counter
while(s1 >= 1) {
System.out.print(" ".repeat(s2));
System.out.println("* ".repeat(s1).trim()); // trim to remove last space
s1--;
s2++;
}
}
int lines = 0, asterisks = 3;
String whiteSpace = "";
while (lines++ < 3) {
System.out.print(whiteSpace);
for (int i = 0; i < 3; i++) {
if (i <= (asterisks - lines)) {
System.out.print("* ");
}
}
whiteSpace += " ";
System.out.println();
}

Building a base for my christmas tree

I'm trying to build a Christmas tree with a user inputted triangular top and a rectangular base, but I'm currently stuck while building the base. The specifications are as follows: The triangle starts with a single * and increases the amount of * on each row by a total of 2 per line, such that the final row is 2(n)-1 with n being the inputted height of the triangle. The height of the rectangle (stump) underneath the tree is equal to 1 plus (1/5)n and the width of the stump is 1/3n however if the result of 1/3n is an even integer, add 1 to the total stump width. (i.e the stump width is always an odd number.)
Here's what i have so far, the triangular part of the tree is fine, but the rectangle is a mess.
public class xmasTree {
public static final int TREE_MAXIMUM = 20;
public static final int TREE_MINIMUM = 3;
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
//User introduction
System.out.println("This program prints a \"Christmas\" tree. You "
+ "choose how big the tree will be (within reason);
// prompt for and get user input
System.out.println("How tall should the top of the tree be?");
int treeHeight = keyboard.nextInt();
while (treeHeight < TREE_MINIMUM || TREE_MAXIMUM < treeHeight) {
System.out.println("That's not a valid size. I can only do trees "
+ "from 3 to 20.");
System.out.println("Qutting now.");
System.exit(0);
}
//Print the top triangle section of the christmas tree
for (int i = 0; i < treeHeight; i++) {
for (int j = 0; j < treeHeight - i; j++) {
System.out.print(" ");
}
for (int k = 0; k < (2 * i + 1); k++) {
System.out.print("*");
}
System.out.println();
}
//Print the bottom rectangle section of the tree
for (int c = 0; c <= (1 + (treeHeight / 5)); c++) {
for (int d = 0; d <= (treeHeight / 3); d++) {
System.out.print("");
}
System.out.printf("*");
}
}
}
If anyone could help me figure out how to get the proper input shape for the rectangle that would be awesome, I know I can center it with a simple printf once it is built properly.
First, you need to visualize what your result should be.
Example, n = 8, so base should be 1 + n/5 = 2 tall and n / 3 = 2 adjusted to 3 wide.
*
***
*****
*******
*********
***********
*************
***************
***
***
Your code has the following problems:
print("") is a meaningless statement. It does nothing.
You don't print any leading spaces for indentation.
You don't print * for a count equal to base width.
You don't call println() so base height will definitely not work.
You got the tree part good, so you really shouldn't have problems with this. I won't give you the answer, but hopefully this visual example will help you do it yourself.
And if you make your for loop start at 0, then don't use a equal sign, as it will work 1 more time to what you expect
You almost made it, just a couple comments about your code:
In the last for you should have used < instead of <= like you did on the beggining
You had clear the rules so you just needed to write them in your code, like I did in my code try to make it more clear, find the height and the width of the stump before writing it out
In the inner for you should have printed out the * and in the outer for you just needed to print a new line
Scanner keyboard = new Scanner(System.in);
//User introduction
System.out.println("This program prints a \"Christmas\" tree. You "
+ "choose how big the tree will be (within reason)");
// prompt for and get user input
System.out.println("How tall should the top of the tree be?");
int treeHeight = keyboard.nextInt();
while (treeHeight < TREE_MINIMUM || TREE_MAXIMUM < treeHeight) {
System.out.println("That's not a valid size. I can only do trees "
+ "from 3 to 20.");
System.out.println("Qutting now.");
System.exit(0);
}
//Print the top triangle section of the christmas tree
for (int i = 0; i < treeHeight; i++) {
for (int j = 0; j < treeHeight - i; j++) {
System.out.print(" ");
}
for (int k = 0; k < (2 * i + 1); k++) {
System.out.print("*");
}
System.out.println();
}
//Print the bottom rectangle section of the tree
int stumpHeight = (1 + (treeHeight / 5));
int stumpWidth;
if ((treeHeight / 3) % 2 == 0) {
//it is even add 1
stumpWidth = (treeHeight / 3) + 1;
} else {
//it is odd keep it like that
stumpWidth = (treeHeight / 3);
}
for (int c = 0; c < stumpHeight; c++) {
//sorry for adding the spaces but I don't like the incomplete answers
//centering
for (int d = 0; d < treeHeight - stumpWidth/2; d++) {
System.out.print(" ");
}
//adding stump
for (int d = 0; d < stumpWidth; d++) {
System.out.print("*");
}
//going to the next line
System.out.println();
}

What logic needs to be changed to get the star pattern

class Starr {
public static void main(String[] args) {
int res;
for(int i=1;i<=5;i++) {
for(int j=1;j<=5;j++) {
res=i+j;
if(res>=6) {
System.out.print("*");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}
Output:
*
**
***
****
*****
Expected:
*
* *
* * *
* * * *
* * * * *
To get the above expected result i made the following changes,
{
System.out.print(" *"); /* Added a space before '*' */
}
else
{
System.out.print(" "); /* Added 2 spaces */
}
I would like to know if this expected result can be achieved in another logic where i don't have to change the print statement. Whatever changes i have done is a right approach?
You cannot achieve a way of printing whitespaces between the stars without printing anything, although you can achieve the desired output without using whitespaces. This could be done with System.out.format() or System.out.printf(). format and printf are actually the same thing in practice. For you particularly:
System.out.printf("%2s", "*");
This means that this output should print two characters, out of which the first one should be '*'. The rest will be whitespaces.
public class StarPattern {
public static void main(String[] args) {
// This loop print the number of * rows
for (int i = 5; i >= 1; i--) {
// This prints the empty space instead of *
for (int j = 1; j < i; j++) {
System.out.print(" ");
}
// Print the * in the desired position
for (int k = 5; k >= i; k--) {
System.out.print("*");
}
// Move the caret to the next line
System.out.println();
}
}
}
Output:
*
**
***
****
*****
Check this code, It works!
int res;
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 5; j++) {
res = i + j;
String sp = (j != 1) ? " " : "";
if (res >= 6) {
System.out.print(sp + "*");
} else {
System.out.print(sp + " ");
}
}
System.out.println();
}
Output:
*
* *
* * *
* * * *
* * * * *

Categories