Printing a triangle with 3 different symbols in C

Thread Starter

LewisMF

Joined Nov 15, 2014
100
Hi,

I've ben sent a exercise where I have to print to the console (using C) a triangle using three different symbols in the following way:

1. The program must ask how many rows the triangle will have.

2. The program will print the triangle in the following way:
Sin título.png

From outside to inside, the first triangle will be formed of *, the one inside it will be -, the one inside again will be $ and then the other way around...

I managed to print it using all the same symbol, but cannot manage to get different symbols inside each triangle...

Can anyone give me a hand?

Thanks in advanced for the help!! :)
 
Last edited:
You didn't include your code or much other information, but it may be that you are forming "strings" of various sizes but made up of the same character.

Think about printing characters one at a time, which will give you the option of the printing different characters - putch(). Thing about making character arrays and changing the values of particular elements, before "printing".
 

Thread Starter

LewisMF

Joined Nov 15, 2014
100
Thank you for your reply Raymond.

Here is my actual code:
Code:
#include <stdio.h>

int num = 0; //Var to store the user input.
int blank;    //Var to store number of blank spaces.

int main() {

  printf("Number of rows? ");
  scanf("%d", &num);
  printf("\n");

    blank = num - 1;
   
    //For loop to print each row of the triangle.
    for(int k = 1; k <= num; k++) {
       
        //For loop to print each blank space.
        for(int j = 1; j <= blank; j++) {
           
            printf(" ");
        }
       
            blank--; //Decrease number of blank spaces.
       
        //For loop to print each symbol of the triangle.
        for(int r = 1; r <= 2 * k - 1; r++) {
           
            if(r % 2 == 0) {
                printf("-");
            }
           
            else if(r % 3 == 0) {
                printf("$");
            }
           
            else {
                printf("*");
            }
           
        }
           
        printf("\n");
           
        }
       
        blank = 1;
       
        return 0;
}
And this is what it's printing:
example.png
 
It's a little confusing. When you say, "I managed to print it using all the same symbol, but cannot manage to get different symbols inside each triangle" you did manage to get different symbols.

When you say,"From outside to inside, the first triangle will be formed of *, the one inside it will be -, the one inside again will be $ and then the other way around.", do you mean the first and subsequent "rows" that, together, form the triangle?

I think you are close, do you want:

*
*-$
$-*-$

What does the correct triangle actually look like?

You could make a single two dimensional character array and send it preformed line by line - or is that cheating? What is the text of the actual assignment, if it is one.
 

WBahn

Joined Mar 31, 2012
30,052
Take a step back and think about the problem, not the code.

How many symbols are printed on line n (where n=1 is the top line with a single '*')?

How many symbols are printed prior to the center symbol?

It might help to replace the symbols with digits using '*' = 0, '-' = 1, and '$' = 2. That will help you see the pattern.
 
Ahh, I think I am starting to follow you. It looks like this is your code segment to form the rows
Code:
        //For loop to print each symbol of the triangle.
        for(int r = 1; r <= 2 * k - 1; r++) {
                if(r % 2 == 0) {
                printf("-");
            }    
            else if(r % 3 == 0) {
                printf("$");
            }    
            else {
                printf("*");
            }     
        }
That is going to give you the correct length but not the correct pattern. It gives only one pattern.

Edit: Hint - maybe add a direction variable
 
Last edited:

MrChips

Joined Oct 2, 2009
30,802
As @WBahn says, take a step back and forget about the code.
Very often you cannot see the forest because of the trees.
Design the algorithm first before writing code.
 

Thread Starter

LewisMF

Joined Nov 15, 2014
100
It's a little confusing. When you say, "I managed to print it using all the same symbol, but cannot manage to get different symbols inside each triangle" you did manage to get different symbols.

When you say,"From outside to inside, the first triangle will be formed of *, the one inside it will be -, the one inside again will be $ and then the other way around.", do you mean the first and subsequent "rows" that, together, form the triangle?

I think you are close, do you want:

*
*-$
$-*-$

What does the correct triangle actually look like?

You could make a single two dimensional character array and send it preformed line by line - or is that cheating? What is the text of the actual assignment, if it is one.
Thank you for your reply.

At the beginning, I could only manage to print the complete triangle with the '*' symbol.
After that, I tried inserting some 'if else' statements inside the 'for' loop that prints the symbols and got the result shown in my previous post.

In your post below, you are correct when you say: That is going to give you the correct length but not the correct pattern. It gives only one pattern.
That's the actual part I cannot figure out...the pattern.

This is what the triangle must look like for a user input of, for example, 10 rows:
example_!.png
 

Attachments

Thank you for your reply.

At the beginning, I could only manage to print the complete triangle with the '*' symbol.
After that, I tried inserting some 'if else' statements inside the 'for' loop that prints the symbols and got the result shown in my previous post.

In your post below, you are correct when you say: That is going to give you the correct length but not the correct pattern. It gives only one pattern.
That's the actual part I cannot figure out...the pattern.

This is what the triangle must look like for a user input of, for example, 10 rows:
View attachment 163804
I think a direction variable might help but, I think I will back off and let the two moderators handle helping you. Too many cooks, and all that. They are the real experts :) and they will get you there.
 

Thread Starter

LewisMF

Joined Nov 15, 2014
100
Take a step back and think about the problem, not the code.

How many symbols are printed on line n (where n=1 is the top line with a single '*')?

How many symbols are printed prior to the center symbol?

It might help to replace the symbols with digits using '*' = 0, '-' = 1, and '$' = 2. That will help you see the pattern.
Thank you WBahn.

For n=1 there will only be 1 symbol.

Prior to the center symbol, it will be n - 1 (where n is the total number of rows).
 

Thread Starter

LewisMF

Joined Nov 15, 2014
100
I think a direction variable might help but, I think I will back off and let the two moderators handle helping you. Too many cooks, and all that. They are the real experts :) and they will get you there.
Unfortunately I cannot make use of direction variables or pointers.

Just plain 'for' & 'while' loops and conditionaly statements...

Please note that your help is very much appreciated!! :)
 

Ian Rogers

Joined Dec 12, 2012
1,136
FWIW..

There is a sequence *-$-

Use n and print forwards and backwards printing the central character twice..

1 = * then *
2 = *- then -*
3 = *-$ then $-*
etc..... just keep the sequence..
 

Thread Starter

LewisMF

Joined Nov 15, 2014
100
FWIW..

There is a sequence *-$-

Use n and print forwards and backwards printing the central character twice..

1 = * then *
2 = *- then -*
3 = *-$ then $-*
etc..... just keep the sequence..
Thank you for your reply Ian, but I'm not sure if the sequence you describe is the same one as in the triangle, please see:
example_!.png

I'm not sure what you mean by: Use n and print forwards and backwards printing the central character twice..

Sorry for my misunderstanding.
 

WBahn

Joined Mar 31, 2012
30,052
Thank you WBahn.

For n=1 there will only be 1 symbol.

Prior to the center symbol, it will be n - 1 (where n is the total number of rows).
Think in terms of column numbers starting with the first symbol on a given row being column 0.

So for a row with 13 symbols (which row number would that be) you might have

0 1 2 3 4 5 6 7 8 9 10 11 12

What is the number of the center symbol? Can you use that to change the numbers to

0 1 2 3 4 5 6 5 4 3 2 1 0

Now notice that you have a repeating pattern that consists of four elements, not three. To see this, think of a really long row and then look for the pattern in the front half.

Another way to do it is to think of the center of the triangle as being column 0 and note that the same four-element pattern you have going across a row (in the front half) goes down the center. So determining the type of symbol at the center of a given row becomes much easier. Now it's just a matter of computing the symbol before and after the center column.

If you give it some careful thought before throwing a lot of code at the screen, you can get this down to a very tight loop.
 

Ian Rogers

Joined Dec 12, 2012
1,136
sequence 1
Lets assume someone types 8 rows n = 1 to 8

1 = * and *
2 = *- then -*
3 = *-$ then $-*
4 = *-$- then *-$-*
5 = *-$-* then *-$-*
6 = *-$-*- then *-$-*
7 = *-$-*-$ then $-*-$-*
8 = *-$-*-$- then -$-*-$-*
You just overwrite the center which ever it may be..

8 will have 15 characters *-$-*-$-$-*-$-* as the - is placed it the same position ..
 
Last edited:
Well, it has been ~ 6 weeks since the original post and more than a month since @LewisMF has logged on, so I am hoping that the "assignment" has expired.. Since I did this program at the time, and now xmas is almost over I want to post it :)

After I got it to work (it did take a little while to figure out I will admit, but after post #8 I understood what the task was - I think) I didn't try to make it more streamlined or tighter or cleaner or shorter or anything really. I will put it in as a spoiler in case someone else also did it or wants to try (or wants to criticize my code ;) It is actually a kind of neat little assignment.

This was done in an old Visual Studio - the 'meat' is delineated
C:
// xmastree.cpp : MS Visual Studio

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
   char ch;
   int nRows, i,j;

   printf("\nEnter number of rows:");
   scanf_s("%d",&nRows);
   printf("\n\n");
   // Here is the meat ---------------------------
   for(i = 0; i < nRows; i++)    //row loop
   {
   for(j = i + 1; j < nRows; j++)    //space loop
     {
     printf(" ");
     }
  for(j = 0; j <= 2*i; j++){ // symbol loop
     if((j==0) || (j==2*i)){ // first or last col
       putchar(ch='*');
     }
     else{
       if   ( j % 2 != 0 ) {
         putchar('-');    
       }
       else{
         if ( ( i % 2 !=0 ) && (j==(2*i/2)+1)) {
           putchar(ch);
           }
         else {
           (ch == '$') ? (ch='*') : (ch='$'); //alternate symbols
           putchar(ch);
         }
       }
     }
   }
   if(i < nRows - 1) printf("\n"); // CRs
   }
   // End of the meat ---------------------------
   printf("\n\n\nEnter a key to end:");
   scanf_s("%d",&nRows);
   return 0;
}
 

ebeowulf17

Joined Aug 12, 2014
3,307
Well, it has been ~ 6 weeks since the original post and more than a month since @LewisMF has logged on, so I am hoping that the "assignment" has expired.. Since I did this program at the time, and now xmas is almost over I want to post it :)

After I got it to work (it did take a little while to figure out I will admit, but after post #8 I understood what the task was - I think) I didn't try to make it more streamlined or tighter or cleaner or shorter or anything really. I will put it in as a spoiler in case someone else also did it or wants to try (or wants to criticize my code ;) It is actually a kind of neat little assignment.

This was done in an old Visual Studio - the 'meat' is delineated
C:
// xmastree.cpp : MS Visual Studio

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
   char ch;
   int nRows, i,j;

   printf("\nEnter number of rows:");
   scanf_s("%d",&nRows);
   printf("\n\n");
   // Here is the meat ---------------------------
   for(i = 0; i < nRows; i++)    //row loop
   {
   for(j = i + 1; j < nRows; j++)    //space loop
     {
     printf(" ");
     }
  for(j = 0; j <= 2*i; j++){ // symbol loop
     if((j==0) || (j==2*i)){ // first or last col
       putchar(ch='*');
     }
     else{
       if   ( j % 2 != 0 ) {
         putchar('-');
       }
       else{
         if ( ( i % 2 !=0 ) && (j==(2*i/2)+1)) {
           putchar(ch);
           }
         else {
           (ch == '$') ? (ch='*') : (ch='$'); //alternate symbols
           putchar(ch);
         }
       }
     }
   }
   if(i < nRows - 1) printf("\n"); // CRs
   }
   // End of the meat ---------------------------
   printf("\n\n\nEnter a key to end:");
   scanf_s("%d",&nRows);
   return 0;
}
I didn't see this thread until your new reply, but it piqued my interest. I've just started taking an online class in C and did simpler, but vaguely similar assignments there, so I couldn't resist the challenge of trying this one. Getting the pattern right is an interesting trick. Here's my take (I'd welcome any comments or criticism.)

*** EDIT: I realized I didn't do a good job of commenting code initially - I've added a few more notes now to hopefully make it more intelligible.
C:
#include <stdio.h>

char printChar(int row, int columnDistance);            // function prototype

int main(void) {
    int rowCount=0;                                     // number of rows to print
    int i, j;                                           // used for loop iteration
    int distFromCenter=0;                               // distance of cursor from center column of pattern

    printf("How many rows would you like? ");
    scanf("%d",&rowCount);
    printf("\n");

    for(i=0; i<rowCount; i++){                          // loop through rows
        for(j=1; j<rowCount*2; j++){                    // loop through columns
            if(j<rowCount){
                //  j<rowCount means we're in column left of mid-point
                distFromCenter=rowCount-j;              // calculate distance from center (abs value)
            } else {
                //  j>=rowCount means we're in column right of mid-point or dead-center
                distFromCenter=j-rowCount;              // calculate distance from center (abs value)
            }
            printf("%c",printChar(i,distFromCenter));   // this relies on "printChar" function defined below
        }
        printf("\n");
    }
}

char printChar(int row, int columnDistance){
    int shapePicker=0;
    if(columnDistance>row) {
        //  print empty space for area outside of triangle
        return ' ';
    } else {
        shapePicker=(columnDistance-row)%4;             // modulo function establishes pattern of 4 characters
        if(shapePicker==0){
            return '*';
        }
        else if(shapePicker==-2){
            return '$';
        }
        else {
            return '-';
        }
    }

}
 
Last edited:

WBahn

Joined Mar 31, 2012
30,052
I'll go the opposite way.

If anyone wants to walk through the development, we can certainly do that. But my posts earlier in the thread give the needed hints.

C:
#include <stdio.h>
void tree(int n)
{
   char s[] = {'*', '-', '$', '-'};
  
   for (int r = 0; r < n; r++)
      for (int c = 1; c <= n + r + 1; c++)
         putchar(c<n-r?' ':(c<=n+r?s[(r+(c<n?c-n:n-c))%sizeof(s)]:'\n'));
}

int main(void)
{
   tree(20);
   return 0;
}
 
It's interesting to see the different approaches.

For better or worse, I can tell you that when I first started (well, after understanding what the program was supposed to do which took a few posts), I was approaching it as printing a multi-character pattern. I did read your (@WBahn) 'hints', but disregarded them completely, because, after looking at it for a bit, I decided it was simply printing an alternating symbol ("$" or "*") with a separator ("-") on odd numbered columns and starting and ending with "*". But, with a rule that on even odd rows there was no alternation in the symbol on the column after the midpoint. That is, quite honestly, how I saw the task.

That change in alternate or don't alternate was what I think I was getting at with the "direction" idea, but I had not thought it through.

In retrospect, I certainly could have incorporated the spaces and first and last symbols into the loops rather than as separates- a little lazy there, but that happens a lot when playing around, I suppose. I had forgotten about the shorthand if-then-else until the end of writing - I almost never use that shorthand.

Both of you (@ebeowulf17 @WBahn) used a function apart from main(), I also never considered doing that.

It's a cool little assignment. I wonder what the OP, or the assignor came up with...we may never know unless @LewisMF comes back and tells us :)
 
Last edited:

ebeowulf17

Joined Aug 12, 2014
3,307
I had forgotten about the shorthand if-then-else until the end of writing - I almost never use that shorthand.
I'm curious about that method. As a novice, I prefer the more verbose if-then-else statements, but I'm interested in knowing the pros and cons.

I imagine with experience, the conditional operator will become easier for me to read quickly, but it's hard to imagine it would ever be as intuitive as if-then-else. The whitespace and indentations that typically go with ifs are easy on the eyes!

On the other hand, if there are performance benefits to the more compact conditional operator, it would be good to know that too.

I must confess, when I first saw @WBahn's code, it looked like it must be a magic trick - how could it possibly work while being so small? Once I recognized that there are three separate conditionals embedded in 1 line of code, it was a little easier to understand, but it's still impressively compact and efficient.

I really like the use of a character array instead of more conditionals to decode the results of the modulo function into individual characters. Wish I had thought of that myself.

As usual, this is a great forum, exposing me to new ideas and different approaches all the time!
 
Top