Java - Simple formatting regarding power of 2 triangle - java

Overview
I'm sure this is a simple problem for most of you on here, but I have been struggling with a small spacing problem and was hoping I can learn from someone more experienced. I need to produce a triangle similar to the one below. You can see that the numbers are aligned correctly no matter the length.
Enter the number of lines: 8
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
1 2 4 8 16 32 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 64 32 16 8 4 2 1
My Code
Here is what I have so far. It isn't the prettiest, but it seems to give me the correct values at least.
import java.util.Scanner;
public class Pyramid2
{
public static void main(String[] args)
{
int i, j, k, l, a;
//Create a Scanner object
Scanner in = new Scanner (System.in);
//Prompt the user to enter number of rows in pyramid
System.out.print("Enter number of rows: ");
int rows = in.nextInt();
a = rows;
//Variables to determine length
int length = ("" + rows).length();
String str = " %" + length + "s";
//Logic
for (i = 1; i <= rows; i++)
{
for (j = a; j > 0; j--)
{
System.out.printf(str, " ");
}
for (j = 1; j <= (2*rows); j++)
{
if (j == (rows+1))
{
continue;
}
if (j < (rows+1))
{
k = j;
}
else
{
k = ((2*rows)-j+1);
}
if (k >= (rows+1-i))
{
l = (int)Math.pow(2, (i+k-rows-1));
String str1 = "" + l;
System.out.printf(str, str1);
}
}
a--;
System.out.println();
}
}
}
My Results
This is the console output when 6 rows are chosen. Everything looks good until row 5 when a 2 digit number (16) appears. What are some efficient ways to align the results properly?
Enter number of rows: 6
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1

You calculate length as the number of digits in rows, but it needs to be number of digits in largest number in triangle.
E.g. for rows = 6, largest number is 32, so length should be 2.
For rows = 8, largest number is 128, so length should be 3.
Largest number is 2rows, which in Java means 1 << rows, so change length calculation to:
int length = ("" + (1 << rows)).length();
You are also adding one too many blanks on the left.
Change code to this:
a = rows - 1;

First of all i can recommend to determine the largest number in pyramid. Then count digits in this number. For 8 rows this number is 128, it has 3 digits. According this information we can decide that we need 3+1=4 (including spaces) characters to print every value in pyramid.
After it you have to complete every output number by spaces (from the left) to achive string size of 4 characters.
And the global prefix for every pyramid line will contain (rows - i) * 4 spaces.

Related

Printing a squares triangle. How to mirror numbers?

So I've been working on this lab for a while now for my programming class and so far I think I'm on the right track.
However, I'm not quite sure how to mirror the numbers. So pretty much, my code is only printing the top half of the triangle. Anyway here is the actual assignment that was given to us:
Write a program using a Scanner that asks the user for a number n between 1 and 9 (inclusive). The program prints a triangle with n rows. The first row contains only the square of 1, and it is right-justified. The second row contains the square of 2 followed by the square of 1, and is right justified. Subsequent rows include the squares of 3, 2, and 1, and then 4, 3, 2 and 1, and so forth until n rows are printed.
Assuming the user enters 4, the program prints the following triangle to the console:
1
4 1
9 4 1
16 9 4 1
9 4 1
4 1
1
For full credit, each column should be 3 characters wide and the values should be right justified.
Now here is what I have written for my code so far:
import java.util.Scanner;
public class lab6 {
public static void main(String[] args) {
Scanner kybd = new Scanner(System.in);
System.out.println(
"Enter a number that is between 1 and 9 (inclusive): ");
// this is the value that the user will enter for # of rows
int rows = kybd.nextInt();
for (int i = rows; i > 0; i--) {
for (int j = rows; j > 0; j--)
System.out.print((rows - j + 1) < i ?
" " : String.format("%3d", j * j));
System.out.println();
}
}
}
And this is what that code PRINTS when I enter 4:
Enter a number that is between 1 and 9 (inclusive):
4
1
4 1
9 4 1
16 9 4 1
As you can see, I can only get the TOP half of the triangle to print out. I've been playing around trying to figure out how to mirror it but I can't seem to figure it out. I've looked on this website for help, and all over the Internet but I can't seem to do it.
Answer is:
public static void main(String... args) {
Scanner kybd = new Scanner(System.in);
System.out.println("Enter a number that is between 1 and 9 (inclusive): ");
int rows = kybd.nextInt(); // this is the value that the user will enter for # of rows
for (int i = -rows + 1; i < rows; i++) {
for (int j = -rows; j < 0; j++)
System.out.print(abs(i) > j + rows ? " " : String.format("%3d", j * j));
System.out.println();
}
}
Try think of this as how to find points(carthesians) that are betwean three linear functions(area of triangle that lied betwean):
y = 0 // in loops i is y and j is x
y = x + 4
y = -x -4
And here is example result for 4:
And 9:
In the outer loop or stream you have to iterate from 1-n to n-1 (inclusive) and take absolute values for negative numbers. The rest is the same.
If n=6, then the triangle looks like this:
1
4 1
9 4 1
16 9 4 1
25 16 9 4 1
36 25 16 9 4 1
25 16 9 4 1
16 9 4 1
9 4 1
4 1
1
Try it online!
int n = 6;
IntStream.rangeClosed(1 - n, n - 1)
.map(Math::abs)
.peek(i -> IntStream.iterate(n, j -> j > 0, j -> j - 1)
// prepare an element
.mapToObj(j -> i > n - j ? " " : String.format("%3d", j * j))
// print out an element
.forEach(System.out::print))
// start new line
.forEach(i -> System.out.println());
See also: Output an ASCII diamond shape using loops
Another alternative :
public static void main(String args[]) {
Scanner kybd = new Scanner(System.in);
System.out.println("Enter a number that is between 1 and 9 (inclusive): ");
int rows = kybd.nextInt(); // this is the value that the user will enter for # of rows
int row = rows, increment = -1;
while (row <= rows){
for (int j = rows; j > 0; j--) {
System.out.print(rows - j + 1 < row ? " " : String.format("%3d", j * j));
}
System.out.println();
if(row == 1) {
increment = - increment;
}
row += increment;
}
}
The outer loop from 1-n to n-1 inclusive, and the inner decrementing loop from n to 0. The if condition is the absolute value of i should not be greater than n - j.
Try it online!
int n = 6;
for (int i = 1 - n; i <= n - 1; i++) {
for (int j = n; j > 0; j--)
if (Math.abs(i) > n - j)
System.out.print(" ");
else
System.out.printf("%3d", j * j);
System.out.println();
}
Output:
1
4 1
9 4 1
16 9 4 1
25 16 9 4 1
36 25 16 9 4 1
25 16 9 4 1
16 9 4 1
9 4 1
4 1
1
See also: Invert incrementing triangle pattern

How can i determine the formula for determining the first number in Java's loop array for floyd's triangle?

Hi so i have java loop problem.
So i'm trying to figure out how to determine the first number(in the top of the pattern) in the loop for floyd's triangle by entering the height on the triangle.
Note: only the height is to be inputted to determine the first number and the last number should be fixed to 1.
for example:
Enter the height: 5
The first number is: 15
15
14 13
12 11 10
9 8 7 6
5 4 3 2 1
Another one is
Enter the height: 6
The first number is: 21
21
20 19
18 17 16
15 14 13 12
11 10 9 8 7
6 5 4 3 2 1
I've figured out how to do the pattern and the decrementing of the value but i cant seem to figure out the first number. I've been trying to figure out the sequence but it's still confusing to me because i'm still new at java.
Here is my code:
import java.util.Scanner;
public class Main
{
public static void main(String[] args) {
int n;
int startingnumber = ;
Scanner input = new Scanner(System.in);
System.out.print("Enter the height of the triangle: ");
n = input.nextInt();
System.out.print("The first number is "+startingnumber);
for(int i =1; i<=n; i++){
for(int j =1; j<=i; j++){
System.out.print(startingnumber);
startingnumber--;
}
System.out.println();
}
}
}
The code is still not finished because i cant figure out the formula :(
I would appreciate any help that i can find. Thanks!
This mathematical problem is Triangular number and here is a visual demonstration
S1 = 1
S2 = 1 + 2
S3 = 1 + 2 + 3
...
Sn = 1 + 2 + 3 + ... + n
=> 1 + 2 + 3 + ... + n = n * (n + 1) / 2
An also have a look at System.out.printf
public static void main(String[] args) {
int n;
int startingnumber;
Scanner input = new Scanner(System.in);
System.out.print("Enter the height of the triangle: ");
n = input.nextInt();
startingnumber = n * (n + 1) / 2;
System.out.println("The first number is " + startingnumber);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
System.out.printf("%3d ", startingnumber);
startingnumber--;
}
System.out.println();
}
}
Output
Enter the height of the triangle: 6
The first number is 21
21
20 19
18 17 16
15 14 13 12
11 10 9 8 7
6 5 4 3 2 1
The way you solve that type of question is by finding a mathematical relationship. In this case, you know (when input's 6) that the height's 6. You also know that at each row, you have one less number than at the one that goes after it. The bottom one has 6, as its the same as the height.
Therefore, you need to do 6+5+4+3+2+1 to obtain the starting number.
Now that formulated as a generic solution: n+(n-1)+((n-1)-1)..+1.
A possible implementation for that is:
System.out.print("Enter the height of the triangle: ");
n = input.nextInt();
int startingNumber = 0;
for (int i=n;i>0;i--) startingNumber+=i;

I need help making this shape with nested for loops [Update]

I need to print out this shape using nested for loops for homework (full disclosure.)
I cant figure out how to center the whole thing though.
The periods represent a continuation of the pattern. So it's supposed to be the whole pyramid.
Here's what I have so now
public static void question4(){
int ix = 30;
for(int i = 1; i<=128; i=i*2){
// x is the number printed
//it gets the value from i,
for (int g = ix; g>=0; g--){
System.out.print(" ");
}
for (int x2 =1; x2<=i-1; x2=x2*2){
System.out.print(" ");
System.out.print(x2);
}
for (int x = i; x>=1; x=x/2){
System.out.print(" ");
System.out.print(x);
}
ix=ix-4;
System.out.println();
}
Thanks for the help with the decrementing spaces, now the numbers themselves push the bottom rows over however. I tried using the string.length command suggested by another user but it kept returning an error.
Try something like this:
public static void main(String[] args) {
String spacer = " ";
for (int i = 1; i <= 128; i = i * 2) {
// x is the number printed
// it gets the value from i,
System.out.print(spacer);
for (int x2 = 1; x2 <= i - 1; x2 = x2 * 2) {
System.out.print(" ");
System.out.print(x2);
}
for (int x = i; x >= 1; x = x / 2) {
System.out.print(" ");
System.out.print(x);
}
if ((i * 2) < 10)
spacer = spacer.substring(0, spacer.length() - 2);
else if ((i * 2) < 100)
spacer = spacer.substring(0, spacer.length() - 3);
else
spacer = spacer.substring(0, spacer.length() - 4);
System.out.println();
}
}
This will create space for each row decreasing the space as you go down the triangle.
Gives this for output:
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
1 2 4 8 16 32 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 64 32 16 8 4 2 1
I know it is very easy to answer it. First check this code
int spaces = 7;
for(int i = 1; i<=128; i=i*2){
for(int k=1;k<=spaces;k++)
System.out.print(" ");
spaces--;
// x is the number printed
//it gets the value from i,
for (int x2 =1; x2<=i-1; x2=x2*2){
System.out.print(" ");
System.out.print(x2);
}
for (int x = i; x>=1; x=x/2){
System.out.print(" ");
System.out.print(x);
}
System.out.println();
}
As you can see whenever the first loop starts iterating, nested for loop for space start giving space before the another nested loop print the numbers. As the loop move further spaces will get decremented and your pyramid will grow eventually.
Although answered & accepted, here's a solution that prints a perfect pyramid with one for loop
public static void perfectPyramid() {
int upLimit = 1024;
int blankFieldWidth = String.valueOf(upLimit).length() + 1; // if upLimit is 3-digit, the blank field will be 4-blanks
String blank = new String(new char[blankFieldWidth]).replace("\0", " "); //one-liner for creating a String by repeating another String a given number of times
String numPart = "1" + new String(new char[blankFieldWidth - String.valueOf(blankFieldWidth - 1).length()]).replace("\0", " ");
String previous = "-"; // dummy initial value
for (int i = 1; i <= upLimit; i = i * 2) {
int countOfBlankFields = (int) (Math.log(upLimit / i) / Math.log(2)); // the count of blank columns per row (one side only)
String dynSpacer = new String(new char[blankFieldWidth - String.valueOf(i).length()]).replace("\0", " ");
numPart = numPart.replace(previous, previous + i + dynSpacer + previous);
String blanks = new String(new char[countOfBlankFields]).replace("\0", blank);
String row = blanks + numPart + blanks;
previous = i + dynSpacer;
System.out.println(row);
}
}
it prints a pyramid taking into account the spaces
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
1 2 4 8 16 32 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 256 128 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 256 512 256 128 64 32 16 8 4 2 1
1 2 4 8 16 32 64 128 256 512 1024 512 256 128 64 32 16 8 4 2 1
For what concerns the nested-loops, you can move from creating a row by replacing string into using a nested-for

I need help producing a pyramid with a certain algorithm to combine numbers (nested loops)

I have the layout for the pyramid set I just can't find out how I would combine or mathematically get the next few numbers. What I need is:
1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
My code right now is:
int x = 7;
for (int i =1; i<=x; i++) {
for (int j =1; j<=x-i; j++) {
System.out.print(" ");
}
for (int k=1; k<=i;k++) {
System.out.printf("%2d",k);
}
for(int k=i-1; k>=1;k--) {
System.out.printf("%2d",k);
}
System.out.println(" ");
}
But my output comes out as:
1
1 2 1
1 2 3 2 1
1 2 3 4 3 2 1
1 2 3 4 5 4 3 2 1
1 2 3 4 5 6 5 4 3 2 1
1 2 3 4 5 6 7 6 5 4 3 2 1
Sorry if this came out weird; this is my first question ever on this site. How can I modify my code to get the other pyramid?
Firstly, I presume you are trying to compute a Pascal triangle and that when you wrote that the desired output was:
1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
you actually mean:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
because otherwise it doesn't make much sense.
Assuming you have made a slight error and the second triangle is the one you want then that is a Pascal's triangle. The rules for computing a Pascal triangle is to add the number above and to the left with the number above and to the right to find the new value.
Image credit Hersfold
You can quite easily write a recursive function that will do this. With a recursive function a good approach is to write your guards and base case, then recurse. This would look like:
private static int calculatePascalNumber(int row, int column)
{
if (row < 1 || column < 1 || column > row) {
return 0;
} else if (column == 1 || row == column) {
return 1;
} else {
return calculatePascalNumber(row - 1, column - 1) +
calculatePascalNumber(row - 1, column);
}
}
These are the rules for this function
if the row or column is less than 1 or the column is wider than the
row these are points outside of the triangle and should return 0
if the column is in one of the end columns (either column equals 1 or the row and column are equal) return 1
otherwise add the two numbers above to the left and the right
You could then call this function within your code that would look like
int x = 7;
for (int row = 1; row <= x; row++) {
for (int j =1; j<=x-row; j++) {
if (j % 2 == 0) {
System.out.print(" ");
} else {
System.out.print(" ");
}
}
for (int column=1; column<=row;column++) {
System.out.printf(" %2d", calculatePascalNumber(row, column));
}
System.out.println(" ");
}
I have revised it a little for formatting, if you wanted to put in further work the ouput formatting would be a good thing to look at.
Finally, it is worth noting performance. If you wanted to run this to compute values on large triangles the number of recursive calls would start making this function go very slowly. A possible way to resolve this would be to cache the results of calls to calculatePascalNumber so that when it is called with parameters it has already computed it returns the value from a hashmap/ array rather than running through all the computations multiple times.
Another option to speed this up for larger triangles is to use this function for calculating a row by itself which could lead to the following code for calculatePascalNumber
private static int calculatePascalNumber(int row, int column)
{
if (row < 0 || column < 0 || column > row) {
return 0;
} else if (column == 1) {
return 1;
} else {
return (calculatePascalNumber(row, column - 1)
* (row + 1 - column)) / (column - 1);
}
}
but what you gain with efficiency you lose with clarity.

How to find element number from either a single, or a range of values in an array

This is the code for an upcoming university practical I have:
import java.util.Random;
public class Practical4_Assessed
{
public static void main(String[] args)
{
Random numberGenerator = new Random ();
int[] arrayOfGenerator = new int[100];
int[] countOfArray = new int[10];
int count;
for (int countOfGenerator = 0; countOfGenerator < 100; countOfGenerator++)
{
count = numberGenerator.nextInt(10);
countOfArray[count]++;
arrayOfGenerator[countOfGenerator] = count + 1;
}
int countOfNumbersOnLine = 0;
for (int countOfOutput = 0; countOfOutput < 100; countOfOutput++)
{
if (countOfNumbersOnLine == 10)
{
System.out.println("");
countOfNumbersOnLine = 0;
countOfOutput--;
}
else
{
if (arrayOfGenerator[countOfOutput] == 10)
{
System.out.print(arrayOfGenerator[countOfOutput] + " ");
countOfNumbersOnLine++;
}
else
{
System.out.print(arrayOfGenerator[countOfOutput] + " ");
countOfNumbersOnLine++;
}
}
}
System.out.println("");
System.out.println("");
String occurrencesReport = "";
String graph = "";
for (int countOfNumbers = 0; countOfNumbers < countOfArray.length; countOfNumbers++)
{
occurrencesReport += "The number " + (countOfNumbers + 1) +
" occurs " + countOfArray[countOfNumbers] + " times.";
if (countOfNumbers != 9)
graph += (countOfNumbers + 1) + " ";
else
graph += (countOfNumbers + 1) + " ";
for (int a = 0; a < countOfArray[countOfNumbers]; a++)
{
graph += "*";
}
occurrencesReport += "\n";
graph += "\n";
}
System.out.println(occurrencesReport);
System.out.println(graph);
int max = 0;
int test = 0;
for (int counter = 0; counter < countOfArray.length; counter++)
{
if (countOfArray[counter] >= max)
{
max = countOfArray[counter];
test = counter + 1;
}
}
System.out.println("The number that appears the most is " + test + ".");
}
}
The program creates an array that will store 100 integers (all of which are between 1 and 10), which are generated by a random number generator, and then print out ten numbers of this array per line. It then scans these integers, counts up how often each number appears and store the results in a second array.
Following this, it outputs a horizontal bar chart of asterisks showing how often each number appears before finally outputting the number that appears the most often.
I thought I had the code totally and completely done, but I've just realised that if multiple numbers occur the same amount of times, the last part of my code can't handle this, e.g. if the numbers 3 and 5 both appears 12 times, the code can only produce one of them.
Does anyone have a way around this?
Thanks,
Andrew
There are a couple of ways to address this, which range from quick to complex. The easiest way is to brute force it like such:
int max = 0;
//int test = 0;
for (int counter = 0; counter < countOfArray.length; counter++)
{
if (countOfArray[counter] >= max)
{
max = countOfArray[counter];
//test = counter + 1;
}
}
System.out.print("The number that appears the most is");
boolean first = true;
for(int i = 0; i < countOfArray.length; i++)
{
if(countOfArray[i] == max)
{
if(first)
first = false;
else
System.out.print(",");
System.out.print(" " + (i+1) );
}
}
System.out.println(".");
Here's the output:
6 2 6 5 6 8 9 3 5 8
9 8 10 10 4 5 8 9 8 5
1 7 8 5 6 7 10 4 5 4
2 7 9 2 3 3 1 2 10 3
5 2 10 1 1 6 3 3 8 10
2 6 10 2 5 1 4 10 8 7
7 8 7 3 7 8 3 4 5 5
7 8 9 8 6 6 8 1 10 3
2 5 4 6 9 9 10 10 1 10
9 4 10 9 7 3 4 3 2 4
The number 1 occurs 7 times.
The number 2 occurs 9 times.
The number 3 occurs 11 times.
The number 4 occurs 9 times.
The number 5 occurs 11 times.
The number 6 occurs 9 times.
The number 7 occurs 9 times.
The number 8 occurs 13 times.
The number 9 occurs 9 times.
The number 10 occurs 13 times.
1 *******
2 *********
3 ***********
4 *********
5 ***********
6 *********
7 *********
8 *************
9 *********
10 *************
The number that appears the most is 8, 10.
There are much cleaner ways to go about it, but hopefully that gives you a decent start!
I am assuming this is not some kinda homework, so i am providing you another approach than this.
- Use Collection like ArrayList instead of Array.
- Use method like Collections.frequency(Object o) to know the number of time the value got occurred in that Collection.
Instead of just doing
System.out.println("The number that appears the most is " + test + ".");
Again loop through countOfArray, do the print for each element that has the same value as max.

Categories

Resources