Home > Net >  printing the below pattern using just one loop
printing the below pattern using just one loop

Time:11-05

ive got the below code to print a pattern (attached below). However i'd like to just use one loop

#include<iostream>
using namespace std;
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i  ){
        for(int j=1;j<=i;j  ){
            cout<<"*";
        }
        for(int j=1;j<=n-i;j  ){
            if(j%2!=0){
                cout<<"_";
            }else{
                cout<<".";
            }
        }
        cout<<endl;
    }
    for(int i=1;i<n;i  ){
        for(int j=1;j<=n-i;j  ){
            cout<<"*";
        }
        for(int j=1;j<=i;j  ){
            if(j%2==0){
                cout<<".";
            }else{
                cout<<"_";
            }
        }
        cout<<endl;
    }
}
    

when n = 5, heres the output.

*_._.
**_._
***_.
****_
*****
****_
***_.
**_._
*_._.

how do i just make this into one single loop

CodePudding user response:

Try this and see how it does what you want to understand the step you did not find on your own:

#include<iostream>
using namespace std;
int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n*2-1; i  ) {
        if (i <= n)
        {
            for (int j = 1; j <= i; j  ) {
                cout << "*";
            }
            for (int j = 1; j <= n - i; j  ) {
                if (j % 2 != 0) {
                    cout << "_";
                }
                else {
                    cout << ".";
                }
            }
            cout << endl;
        }
        else
        {
            for (int j = 1; j <= n*2 - i; j  ) {
                cout << "*";
            }
            for (int j = 1; j <= i-n; j  ) {
                if (j % 2 == 0) {
                    cout << ".";
                }
                else {
                    cout << "_";
                }
            }
            cout << endl;
        }
    }
}

CodePudding user response:

I'd like to just use one loop.

I'll take it literally and show a starting point for a possible solution.

// Let's start by figuring out some dimensions.
int n;
std::cin >> n;                  
int height = 2 * n - 1;
int area = n * height;

// Now we'll print the "rectangle", one piece at a time.
for (int i = 0; i < area;   i)
{ //            ^^^^^^^^
  // Extract the coordinates of the char to be printed.
  int x = i % n;
  int y = i / n;
  
  // Assign a symbol, based on such coordinates.
  if ( x <= y  and  x <= height - y - 1 )
  { // ^^^^^^       ^^^^^^^^^^^^^^^^^^^    Those are the diagonals.  
    std::cout << '*'; // This prints correctly the triangle on the left...
  }
  else
  {
    std::cout << '_'; // <---  But of course, something else should done here. 
  }
  
  // End of row.
  if ( x == n - 1 )
    std::cout << '\n';
}

CodePudding user response:

If you look at the pattern, then you can see a sort of "triangles". And this already gives a hint for the solution. Use a triangle function.

Please read about it here.

Then you will notice that always the "aboslute"-function, in C std::abs, is involved.

But first of all, it is easily visible that the number rows to print is always the width of a triangle * 2.

And the number of charcters in the pattern, can be calculated by applying the triangle function. Example for width 5:

     Number of stars        number of dashdot
Row  width-abs(row-width)   abs(row-width)

 1             1                  4 
 2             2                  3
 3             3                  2
 4             4                  1
 5             5                  0
 6             4                  1
 7             3                  2 
 8             2                  3
 9             1                  4  

And this can be implemented easily now.

#include <iostream>
#include <cmath>
#include <algorithm>

using namespace std::string_literals;

int main() {
    // Get the max width of the pattern and perform a short input validation
    int maxWidth{};
    if ((std::cin >> maxWidth) and (maxWidth > 0)) {

        // The number of rows for the pattern is dependent on the width. It is a simple relation
        const int numberOfRows = 2 * maxWidth;

        // Show all rows
        for (int row = 1; row < numberOfRows;   row) {

            // Use triangle formular to create star pattern
            std::string starPattern(maxWidth - std::abs(row - maxWidth), '*');

            // Create dashDot pattern
            std::string ddp(std::abs(row - maxWidth), '\0');
            std::generate(ddp.begin(), ddp.end(), [i = 0]() mutable { return i   % 2 ? '.' : '_'; });

            // Show output
            std::cout << (starPattern ddp) << '\n';
        }
    }
    else std::cout << "\n*** Error: Invalid input\n\n";
}

Of course you can also create the whole pattern wit std::generate.

Maybe it is too complex for now.

And less understandable.

See:

#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>

int main() {
    // Get the max width of the pattern and perform a short input validation
    if (int width{}; (std::cin >> width) and (width > 0)) {

        std::vector<std::string> row(2 * width - 1);

        std::for_each(row.begin(), row.end(), [&, r = 1](std::string& s) mutable {
        s = std::string(width - std::abs(r - width), '*');
        std::string ddp(std::abs(r   - width),'\0');
        std::generate(ddp.begin(), ddp.end(), [&, i = 0]()  mutable{ return i   % 2 ? '.' : '_'; });
        s  = ddp; std::cout << s << '\n'; });
    }
    else std::cout << "\n*** Error: Invalid input\n\n";
}
  • Related