0

I have to print out a triangle-star formed shape as such where the user specifies the intial number of asterisks--be it 10, 25, or 30.

***** (5) 
 ***  (3)
  *   (1)

OR

********** (10)
 ********
  ******
   ****
    **
     *

I have written the code with three loops--two nested in one--using C++ Someone else claims that it can be done only using two loops but I can't seem to figure it out. In my head, its like asking to draw a triangle out of only 2 lines; it simply cannot work. I would appreciate it if someone could confirm if it can be done with only two loops and if so provide a hint or explanation.

user29568
  • 167
  • 9
  • You may need 3 loops, but only 2 levels of nesting. – Michael Foukarakis Feb 17 '14 at 13:34
  • I could do that in one loop... – crashmstr Feb 17 '14 at 13:34
  • @MichaelFoukarakis I currently have it in a 3 loop form: one for the space one for the star both of which nested in the one for the line. My question is if its possible to do the print with only two loops. – user29568 Feb 17 '14 at 13:35
  • 1 loop would be easier than 2 – Tim Feb 17 '14 at 13:35
  • @user29568 - Yes it is possible. just think of some logic to either print a start or space for a givenx,y – Ed Heal Feb 17 '14 at 13:35
  • Or go recursive and do no loops. – crashmstr Feb 17 '14 at 13:36
  • @crashmstr One loop would definitely be impressive – user29568 Feb 17 '14 at 13:37
  • On a side-note, your second example has a special case on the last line. In the even case all rows should contain even number of asterisks. – Jan Hudec Feb 17 '14 at 13:37
  • @JanHudec Except the last one; it must always end with one star. – user29568 Feb 17 '14 at 13:37
  • 1
    @user29568: That's the special case I am talking about then. – Jan Hudec Feb 17 '14 at 13:38
  • 2
    @user29568 since you did not specify *how* you start, start with `"*******"`, and while it contains `'*'`, replace find first `'*'` and replace with `" "` and same with last `'*'`. – crashmstr Feb 17 '14 at 13:38
  • @crashmstr the user must specify the initial number of stars, be it 10, 20, 35.. – user29568 Feb 17 '14 at 13:40
  • like @crashmstr said, it is possible in one loop. – Swift Feb 17 '14 at 13:40
  • @user29568 so build the asterisk string first (but like I said, you did not give that constraint in your question). – crashmstr Feb 17 '14 at 13:41
  • Provide your code, so we can help you to remove 1 loop. – Jarod42 Feb 17 '14 at 13:42
  • @crashmstr building the asterisk first would mean an additional loop no? – user29568 Feb 17 '14 at 13:46
  • This can definitely be done with 2 loops, 1 to initialize an asterisk initial string and space initial string. The second loop would be outside and completely separate but would print the space string, then the asterisk string, then delete a single space from the space string, and 2 asterisks from the asterisk string. – trumpetlicks Feb 17 '14 at 13:48
  • @trumpetlicks How can you delete? – user29568 Feb 17 '14 at 13:49
  • @user29568 - because you hold each string separately, one will be made up of all spaces and the other with all asterisks. That means that you simply need to take the '\0' char at the end of the string and move it backward by 1 from strlen for the space string, and by 2 from strlen for the asterisk string. I do apologize, perhaps I shouldn't have used the term "delete". – trumpetlicks Feb 17 '14 at 13:51
  • @user29568 nope, not if you use a `char` array and `memset` to set it up. – crashmstr Feb 17 '14 at 13:53
  • 1
    @crashmstr - that's cheating, and actually a memset is nothing more than a loop, thus needs to be counted in the amount of loops. Whether the memset is HW accelerated or not, the action of memset is a loop based portion of the ALGORITHM. – trumpetlicks Feb 17 '14 at 13:55
  • @trumpetlicks Could you please explain further? strlen is string length correct? – user29568 Feb 17 '14 at 13:59
  • @user29568 - yes, strlen is the C routine for getting the string length of a string. I am actually not necessarily stating that you should use this. The initial string length can be calculated by you, and updated BY YOU when necessary as well as the position of the null terminator of the string. – trumpetlicks Feb 17 '14 at 14:00
  • @trumpetlicks How does knowing the string length create the triangle. Its formed by having 10 stars first, then 8 stars with 1 space on the left, then 6 stars with 2 spaces from the left. The stars are decreasing the spaces are increasing and this clearly calls for two loops? – user29568 Feb 17 '14 at 14:03
  • @user29568 - the point is that you are GIVEN The string length. you need to initialize a string with N (your input) amount of asterisks. Then you need to initialize another string with (essentially) 1 space (the initial spacer to your triangle) but the ability to grow to N/2 spaces (+1 for the ending null character), Print that, then dwindle the asterisk string down and upgrade the space string by 1 space, print, then dwindle and grow, etc.... I believe this is homework which is why I am not simply giving the code. – trumpetlicks Feb 17 '14 at 14:11
  • @trumpetlicks Its an assignment; while its justified not giving the code, it makes it difficult for me to understand what you are saying. I have a working code with two nested loops; if all else fails I will submit what I have. As of now, I can't see how one can avoid three loops. – user29568 Feb 17 '14 at 14:15
  • @trumpetlicks How can I dwindle the asterisks? Isn't it with a loop? (1) Increasing the spaces needs another loop (2) and finally a loop for each line (3) Of course, if we could create a string with a limited and constant length, then we could add two space from the left and one from the right. And with every addition of a space from the left one asterisk is deleted, in light of the limited space. – user29568 Feb 17 '14 at 14:32
  • @user29568 - no, these can be done with static operations, move the ending NULL char back by a static 2 positions for the asterisk string, and move the ending null forward 1 with the space string making the last null position into a space. The space string needs to be pre-allocated with the correct amount of chars (which should be N/2 + 1). – trumpetlicks Feb 17 '14 at 14:36
  • @trumpetlicks What is a null character(empty character?? if yes, what does an empty character do) and how can you move positions? – user29568 Feb 17 '14 at 14:37
  • @EdHeal Could you expand perhaps with a few pieces of code on how to use x,y to print the triangle of user-specified range using only 2 loops. – user29568 Feb 17 '14 at 14:45
  • @user29568 - You can convert a one dimensional array into a two dimensional plane. You can then work out if it needs a space, * or nothing. I have no motivation to sit down and write your homework – Ed Heal Feb 17 '14 at 15:41
  • @EdHeal Very sad of you to think of it that way, I feel very saddened. You are helping me out by letting me learn. And If you think I came here to do my homework you are gravely mistaken, I am here to get better and learn new things. If your here to merely mock me then I suggest going elsewhere. – user29568 Feb 17 '14 at 15:46
  • @user29568 - You can take a horse to water but you cannot make it drink. I have given the outline perhaps you need to do the leg work – Ed Heal Feb 17 '14 at 15:49
  • @EdHeal I haven't learned two dimensional arrays yet, so I wouldn't know the neccesary code/tools to do what you say. If you had the motivation to answer questions then you could have provided an answer with sufficient information on the functions and how they are relevant. Regardless, I am sure you are busy so I am grateful for the outline you have presented. But, I have to admit if the reason you didn't expand on it is because you think I am here to do my "homework" then you seem to have a one-sided view to things because it just doesn't add up. – user29568 Feb 17 '14 at 15:53
  • 1
    @user29568 - Just off the top of my head http://codepad.org/rVuYpNzz – Ed Heal Feb 17 '14 at 16:06
  • @EdHeal Thank You, this is impressive considering that you were able to do it with only one loop. But, it might need a few edits to accommodate for odd depths,i.e. even widths. – user29568 Feb 17 '14 at 16:13
  • @user29568 - It is off the top of my head - I am not going to refine it. I sure a person of your talent can do that – Ed Heal Feb 17 '14 at 16:16
  • @user29568 - Ypu welcome. I have not formed any opinion about you as I do not know you – Ed Heal Feb 17 '14 at 16:23

4 Answers4

1

To use 2 for loops, you will have one loop for the lines and another nested loop for the characters.

An "if" statement can be used to determine whether to print a '*' or space.

Another alternative is to use functions that create strings of repetitive characters.

Edit 1:
This may come in handy, centering formula for text:

starting_position = center_position - (character_count / 2);
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • I don't understand; what does the centering formula do? If we are printing spaces, that per se should imply centering, right? Further, the if statement needs some complicated construction. But, I can see it vaguely, really vaguely. – user29568 Feb 17 '14 at 14:53
  • Thank you I finally got it, but I didn't use the centering formula.:) – user29568 Feb 17 '14 at 16:04
1

One loop is sufficient, to enumerate all lines. To print N spaces on line N, use the std::string(N, ' ') constructor.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Wow does that really work? So it can also print n-stars like this string(N, '*')?? – user29568 Feb 17 '14 at 15:07
  • @user29568: Of course. You'd probably want something like `2 * (Initial-N)` stars, though. Printing N spaces followed by N stars also gets you a triangle, but a rather slanted one. – MSalters Feb 17 '14 at 15:11
  • @MSalters - Can I ask you what you think std::string(N, ' ') is doing??? Is that not internally a loop? Thus NOT 1 loop is sufficient, in your case it would be 3! One external loop for the line count, one for the spaces, and one for the asterisks. Be careful to recognize what your calls are actually doing. – trumpetlicks Feb 17 '14 at 15:18
  • @trumpetlicks: Computers are full of loops. Even `std::cout << "Hello, world";` will have a loop. I can't possibly count all loops (how does font rendering work anyway?), and counting only the loops that are obvious to me is rather subjective. – MSalters Feb 17 '14 at 15:27
  • @MSalters - I hear what you're saying. I think we need to better understand the OP question. I think this is his / her homework, and Im sure the instructor has given fairly strict instructions. – trumpetlicks Feb 17 '14 at 15:30
  • @trumpetlicks I believe that Thomas Mathews suggested method with the if statement is worth looking into, but I can't seem to figure out which if argument would work for the space. Can you help me out? – user29568 Feb 17 '14 at 15:36
  • @user29568 - He is suggesting something very similar to what I was. I think at this point we need to better understand the REQUIREMENTS of the question. What makes up (in your definition) a loop? – trumpetlicks Feb 17 '14 at 15:40
  • @trumpetlicks Thanks for your ongoing help i finally figured out doing it with two loops only :)))). MSalters thanks for your additions as well, I will test them out. – user29568 Feb 17 '14 at 16:27
1

Theoretical computer science says that every problem can be solved in one loop.

This doesn't mean that it's always easy, but in your case, it fortunately is!

How about this program, http://ideone.com/nTnTC8:

#include <iostream>
using namespace std;

int main(int argc, char* argv[]) {

    int startNum = 0;
    cin >> startNum;

    if (startNum <= 0) return 1;

    cout << startNum << endl;
    int numCols = startNum;
    int numRows = (startNum + 1) / 2;

    if (numCols % 2 == 0) {
        ++numRows;
    }

    int numFields = numCols * numRows;

    for (int currentField = 0; currentField < numFields; ++currentField) {
        int currentRow = currentField / numCols;
        int currentCol = currentField % numCols;

        if (currentCol < currentRow) cout << "-";
        else if (currentCol > (numCols - currentRow - 1)) 
            if (currentRow == numRows - 1 && currentCol == numCols / 2) 
                cout << "^";
            else cout << "_";
        else cout << "*";

        if (currentCol == numCols - 1) cout << endl;
    }

    return 0;
}
Felix Dombek
  • 13,664
  • 17
  • 79
  • 131
  • it must end with one star. – user29568 Feb 17 '14 at 15:18
  • @FelixDombek - I think your first claim is completely false. If what you are saying is true, then there would be no such thing as complexity theory and indeed every problem would be solvable in O(n) time. As it is, this is NOT the case. – trumpetlicks Feb 17 '14 at 15:34
  • @trumpetlicks One loop is enough to program a turing machine which keeps looping until an end state is reached. Of course, this loop can be extremely long, and potentially infinite. I'm looking around for a good source, but until I find one you may be interested in this article http://www.zib.de/zuse/Inhalt/Kommentare/Html/0684/universal2.html. The author is a computer science professor at a Berlin university. – Felix Dombek Feb 17 '14 at 15:46
  • @trumpetlicks The loop for a N*N problem would simply run until N*N is reached. I said nothing about the upper bound for the loop. Fact is, you can simply "extract" inner loops into the outer loop, keeping state information (such as, in which inner loop you actually are) as additional variables, and therefore simulate any inner loop inside your one and only outer loop. – Felix Dombek Feb 17 '14 at 15:50
  • @trumpetlicks Actually, it gets even better: you don't technically need *any* classical loop structure, because the same program flow can be achieved with a single recursive function :) – Felix Dombek Feb 17 '14 at 16:01
  • @FelixDombek - I have read the entirety of the link you sent, and I have to admit, I think there is a flaw in the logic. In the section where he speaks about "simulating branches" he specifically states "At the beginning of each section tex2html_wrap_inline123 a comparison is made and if z=j the auxiliary variable t is set to zero, otherwise it is set to one. So he NEEDS an internal branch to simulate branches. That seems inherently flawed to me. I hear the overall logic, but in problem solving, decisions are necessary, i.e. branches. – trumpetlicks Feb 17 '14 at 16:39
  • @trumpetlicks This doesn't have anything to do with looping, but for a short discussion please see http://stackoverflow.com/a/4062912/481061. But I didn't argue that conditional branches aren't necessary! I only meant to state that each and every algorithm can, in theory, be written in one single loop. – Felix Dombek Feb 17 '14 at 17:48
  • @user29568 Updated version; I didn't use `*` but `^` and `-`/`_` instead of blanks to visualize what each `if` statement prints exactly. Now you have a single item on the last line. :) – Felix Dombek Feb 17 '14 at 18:17
1

Strictly speaking, this code does the trick using 2 loops :

int n, s, z;

cout << "Enter the width \n";
cin >> n;

// for each row
for (int i = 0; i < n/2+1; i++) {   

    z = i; // set number of spaces to print
    s = (n-i*2) + (i == n/2 ? (1-n%2) : 0); // set number of stars to print

    // still something to print
    while (z+s > 0) {
        if ( z ) {
            cout << " ";
            z--;
        } else if ( s ) {
            cout << "*";
            s--;
        }
    }

    cout << endl;
}
cid
  • 696
  • 1
  • 8
  • 19
  • I am not mistaken how does it distinguish odd and even widths. – user29568 Feb 17 '14 at 15:26
  • @user29568 - most likely he is using the natural nature of integer divides, etc... Integer ONLY math can be a BIT different than what we learned strictly speaking in arithmetics in school. – trumpetlicks Feb 17 '14 at 15:37