Learning to Code — Part 5d: Making a Pyramid

The first sentence of the project within the SoloLearn app says:

Now, let’s create a method that will display a pyramid of any height to the console window using star (*) symbols.

…and I start to get queasy…

I’ve got Visual Studio launched, and a new Console App called StarPyramid made. I’ve erased the sample code within the Main method, and stare…

Here are my thoughts:

  • There will be a loop that repeats based on the number of rows that the user enters.
  • The first row will print 1 star to the screen, and then each subsequent row will take the number of stars from the previous row, and add 1.
  • Once the number of times the loop runs is greater than the original number entered, the program will stop.
  • The Main method will need to call another method to do all the stuff above.

So, let’s first create the basics of the method:

static void printStarRows(int n) {
}

So this creates a method called printStarRows and prepares to take in a variable called n, who has a data type of integer. I’m going to jump down to the Main method, and ask the user for input, like this:

static void Main(string[] args) {
Console.Write(“How many rows?”);
int n = Console.ReadLine();
printStarRows(n);
}

I also added Console.WriteLine(n); to the printStarRows method so I can test whether or not the taking and sending of the number of rows is working.

The Error window is already saying, Cannot implicitly convert type ‘string’ to ‘int’.

I suppose that since the Main method has string within the parentheses, that’s the default intake so, whatever value entered would come in as a string, and therefore needs to be converted to an integer.

…after some research…

…I found, on the Universal Class website, within an article called Implementing User Input in C# Programming. Within the post, the author wrote:

User input is always a string…

Since that’s the case, I’ll change int n = console.ReadLine(); to be int n = Convert.ToInt32(Console.Readline());

OK, so that’s working! Good. Next, let’s create a for loop that will be gone through until however many rows have been printed, based on the user’s input. I’ll do it like this:

for(int i = n; i <= n, i++) {
Console.WriteLine(i);
}

I’ve now already tried this, and it didn’t work. That is to say, I expected it to print 5, 4, 3, 2, 1, to the screen.

I’d like to run through it in detail to see what happens with this code, and where it goes wrong. We’ll assume the user entered the value of 5, so, n equals 5:

  • A variable called i is created with the data type integer, and it’s value is set to be the same as n, so i = 5.
  • Then it checks to see if i is less than or equal to n. In this case, is 5 less than or equal to 5?
  • It is, so the current value of i, which is 5, is printed to the screen.

OK, I see one problem so far, the incrementing will cause the next value of i to be 6, and when it checks to see if 6 is less than or equal to 5, since it’s not, the program will end. Seems like I need to decrement, so I’ll adjust the code to be the following:

for(int i = n; i <= n, i--) {
Console.WriteLine(i);
}

So, while this did print 5 to the screen, and then 4, and then 3, it just kept going and going and never stopped. This is because by decrementing, the test will ALWAYS find the value of i to be less than or equal to the value of n, so it’ll never stop.

I decided to change the check, so my new code shows:

for(int i = n; i != 0; i--) {
Console.WriteLine(i);
}

In other words, if the value of i does not equal 0, print the value of i to the screen. If it does equal 0, break out of the for loop. And that worked! It prints 5, 4, 3, 2, 1 to the screen. I suppose, at this point, however, I should alter it so the lowest number prints first. That will correspond to the lowest number of stars printing first.

Hmm…In that case, I’ll initialize the value of i to be 1, instead of setting it to be equal to what the user entered. I’ll also set the decrementing back to incrementing. Finally, the check that should be done is whether or not the current value of i is less than or equal to n. So, here’s the updated code:

for(int i = 1; int <= n; i++) {
Console.WriteLine(i);
}

OK, that worked, and now it counts up from 1 to 5. My next thought is that I need to have an additional for loop that will print the stars the number of times that is equal to the current value of i. So, within the for loop, I’ve added the following:

for (int i = 1; int <= n; i++) {
for (int x = 0; x <= i; x++) {
Console.Write(i);
}
}

Notice that I also changed Console.WriteLine(i); to Console.Write(i); which will keep each number printed to the screen on the same line. When run, however, this code produced the following:

11222333344444555555

Looks like each number is printing 1 more time than it’s value. Also, every number is on a single line. I added the following outside of the internal for loop, like this:

for (int i = 1; int <= n; i++) {
for (int x = 0; x <= i; x++) {
Console.Write(i);
}
Console.WriteLine();
}

The extra Console.WriteLine(); causes a carriage return after each time it runs through the internal for loop, resulting in this:

11

222

3333

44444

555555

So that’s good, except that the number is still printing a number of times which is one higher than it’s value. I just realized why it’s doing that!

Since I start the variable x at 0, it has TWO opportunities for the check to come back as true:

  • When x equals 0, the check of is 0 less than or equal to 1, comes back as true, and prints the value of i to the screen (which is 1), and then,
  • When x equals 1, the check of is 1 less than or equal to 1, comes back as true, and prints the value of i to the screen (which is still 1) again!!

I changed the starting value of x from 0 to 1, and when the code runs, the following is the result:

1

22

333

4444

55555

IMAGE

The last step is printing “*” instead of the number, so I modified the innermost for loop, and now the whole printStarRows method looks like this:

static void printStarRows(int n) {
for (int i = 1; i < n; i++) {
for (int x = 1; x <= i: x++) {
Console.Write(“*”);
}
Console.WriteLine();
}
Console.Read();
}

When run, with the value 5, it printed the following result:

*

**

***

****

*****

That’s good, BUT…the challenge is to get the top star to be at the center. The other challenge is that each row should always print an odd number of stars, there’s always one at the center. In other words, the second row, prints 3 stars, not 2!

While up to this point, I was very minimally looking at the SoloLearn app, I’m looking at it now and it shows the check within the for loop that prints the stars, to be x <= 2 * i, and this, I don’t understand.

…after some researching…

I found a video on YouTube, by We The Computer Guys, called C Practical and Assignment Programs-Pattern Printing 8, that talked specifically about that formula. He laid out the pattern first, however, in a table like this:

He then described the number of stars per row, to be related to the number of the row, and that the formula that could be used to get the number of stars, is to take the row’s number, multiply it by 2, and then subtract 1 (or (row*2)-1). This would NOT have naturally occurred to me, but he’s right:

  • (1 * 2) — 1 = 1
  • (2 * 2) — 1 = 3
  • (3 * 2) — 1 = 5
  • (4 * 2) — 1 = 7
  • (5 * 2) — 1 = 9

That definitely helps me to get the number of stars for each row. It will probably also help if I change my variable names to what they actually represent. Updating my existing code with no changes other than variable names, I now have this:

static void printStarRows(int numOfRows) {
for (int row = 1; row <= numOfRows; row++) {
for (int star = 1; star <= row; star++) {
Console.Write(“*”);
}
Console.WriteLine();
}
Console.Read();
}
static void Main(string[] args) {
Console.Write(“How many rows?”);
int numOfRows = Convert.ToInt32(Console.ReadLine());
printStarRows(numOfRows);
}

What we don’t have here (and the reason that when we run this code now, all of the stars are aligned to the left) are spaces. We need to have a for loop to do the spaces, right after the first for loop of the method. Again, I’m not sure that this would come naturally to me, but, the formula for figuring out the number of spaces is to take the number of rows and subtract the row number. The formula is colSpace = numOfRows - row, so for each of our values, here’s the result:

  • 5–1 = 4
  • 5–2 = 3
  • 5–3 = 2
  • 5–4 = 1
  • 5–5 = 0

The code to accomplish this looks like the following:

static void printStarRows(int numOfRows) {
for (int row = 1; row <= numOfRows; row++) {
for (int colSpace = numOfRows — row; colSpace >= 1; colSpace — )
{
Console.Write(“ “);
}

More specifically, here’s what happens each time through this loop:

  • First time through the loop, we’re dealing with row number 1, and we’ll always have the number that the user entered initially, which was 5. So, again, for the first time through the loop, the variable colSpace is initialized as numOfRows - row, which translates into colSpace = 5 - 1, or colSpace = 4.
  • A space is now printed to the screen and the cursor remains on the same line. Additionally, the value of colSpace is decremented from 4 to 3.
  • Second time through the loop, there’s a check to see if colSpace is greater than or equal to 1, or colSpace >= 1, which translates into, is 3 greater than or equal to 1?
  • Since it is, a space is now printed to the screen and the cursor remains on the same line. Keep in mind that this printed space is right next to the printed space that came about as a result of the last time through the loop. Additionally, the value of colSpace is decremented from 3 to 2.
  • Third time through the loop, there’s a check to see if colSpace is greater than or equal to 1, or colSpace >= 1, which translates into, is 2 greater than or equal to 1?
  • Since it is, a space is now printed to the screen and the cursor remains on the same row. Now, there are 3 spaces right next to each other. Additionally, the value of colSpace is decremented from 2 to 1.
  • Fourth time through the loop, there’s a check to see if colSpace is greater than or equal to 1, or colSpace >= 1, which translates into, is 1 greater than or equal to 1?
  • Since it is, a space is now printed to the screen and the cursor remains on the same row. Now, there are 4 spaces right next to each other. Additionally, the value of colSpace is decremented from 1 to 0.
  • Fifth time through the loop, there’s a check to see if colSpace is greater than or equal to 1, or colSpace >=1, which translates into, is 0 greater than or equal to 1?
  • Since it isn’t, we’ll break out of the loop.

Next, we hit the for loop that creates the stars. For the stars to print only the odd numbers (i.e. 1, 3, 5, etc.), we need to use that formula that we saw first which takes the row that we’re on, multiplies it by 2, and then subtracts 1. Then, we’ll want to increment the number of stars by 1 each time through the loop. So, the “star creation” for loop now looks like this:

for (star = 1; star <= (row * 2) — 1; star++) {
Console.Write(“*”);
}

More specifically, here’s what happens each time through this loop:

  • First time through, star is initialized to be equal to 1.
  • Then there’s a check for whether star is less than (row * 2) - 1, which translates into (1 * 2) - 1, which translates into (2) - 1, which equals 1. In other words, is 1 less than or equal to 1?
  • Since it is, after the 4 spaces generated by the previous loop, star is printed to the screen.
  • Star, which is currently 1 is incremented by 1, and is now 2.
  • Second time through, star is now equal to 2, so there’s a check for whether star is less than (row * 2) - 1, which translates into (2 * 2) - 1, which translates into (4) - 1, which equals 3. In other words, is 3 less than or equal to 2?
  • Since it isn’t, we’re broken out of the loop, thus the printing of no more stars.
  • We then go back up to the beginning of the first loop in the method, just before which the value of row is incremented from 1 to 2.
  • Then we go back to the colSpace loop, where the colSpace variable is initialized as numOfRows - row, which translates into colSpace = 5 - 2, or colSpace = 3
  • Then there’s a check to see if our colSpace value is greater than or equal to 1. In other words, is 3 greater than or equal to 1?
  • Since it is, a space will be printed, and the cursor will remain on the same row. Then colSpace will be decremented from 3 to 2.
  • Second time through this loop, there’s a check to see if colSpace is greater than or equal to 1. In other words, is 2 greater than or equal to 1?
  • Since it is, a space in now printed to the screen and the cursor remains on the same row. There are now 2 spaces next to each other. Then, colSpace is decremented from 2 to 1.
  • Third time through this loop, there’s a check to see if colSpace is greater than or equal to 1. In other words, is 1 greater than or equal to 1?
  • Since it is, a space is printed to the screen and the cursor remains on the same row. There are now 3 spaces next to each other. Then, colSpace is decremented from 1 to 0.
  • Fourth time through this loop, there’s a check to see if colSpace is greater than or equal to 1. In other words, is 0 greater than or equal to 1?
  • Since it’s not, we’re broken out of the loop, thus the printing of no more spaces.
  • The star loop will then be executed, resulting in 3 stars being printed to the screen.
  • The row value is incremented from 2 to 3, and then the spaces loop is executed, resulting in 2 spaces being printed to the screen.
  • The star loop is then executed, resulting in 5 stars being printed to the screen.
  • The row value is incremented from 3 to 4, and then the spaces loop is executed, resulting in 1 space being printed to the screen.
  • The star loop is then executed, resulting 7 stars being printed to the screen.
  • The row value is incremented from 4 to 5, and there is a check to see if the row number is less than or equal to the numOfRows value. In other words, is 5 less than or equal to 5?
  • Since it is, the spaces loop is executed. However, at this point, colSpace is equal to numOfRows - row, which translates into colSpace = 5 - 5, which translates into colSpace = 0.
  • There is a check to see if colSpace is greater than or equal to 1, which translates into is colSpace >= 1, or is 0 >= 1?
  • Since it isn’t, we break out of the loop, and no spaces are printed to the screen.
  • The star loop is then executed, resulting in 9 stars being printed to the screen.
  • The row value is now incremented from 5 to 6, and there is a check to see if the row number is less than or equal to the numOfRows value. In other words, is 6 less than or equal to 5?
  • Since it isn’t, we’re broken out of the loop, and the program ends.

One of the comments made within the SoloApp was very specific to say that the first part of the code (colSpace = numOfRows - row) initializes the value of colSpace JUST ONE TIME. This was very important for me to remember. Additionally, I had to keep reminding myself that the star loop was NOT inside of the spaces loop. It occurs after the spaces loop.

This was a VERY tough one. It took me all day to truly understand what was taking place and, as I said, those two formulas would NOT have occurred to me naturally. That said, I understand what took place during the execution of the program, so that’s good. Also, I’m now exhausted.

Anyway, please correct or add to anything I’ve written, and feel free to provide any other feedback.

Here’s a link to the previous article, Learning to Code — Part 5c: Method Overloading and Recursion.