'create number pattern into a string vector

new to programming so I apologize if this has been answered before...I have tried searching with almost zero luck. I am trying to create a number pattern like 1,2,2,3,3,3,4,4,4,4 etc; I have gotten to that point but I need to put it into a string vector so that if the user inputs 5, the string vector elements are 1,2,2,3,3,3,4,4,4,4,5,5,5,5,5

void print_vectorStr(vector<string> &vec, string sep = "")
{
    cout << "\nThe vector string elements are: ";
    for (auto elem : vec)
    {
        cout << elem << sep;
    }
    cout << endl;
}

void print_vector(vector<int> &vec, string sep = "")
{
    cout << "\nThe vector integer elements are: ";
    for (auto elem : vec)
    {
        cout << elem << sep;
    }
    cout << endl;
}

int main()
{

    int n;
    cout << "insert n \n";
    cin >> n;

    vector<int> vec(n);
    vector<string> vecString;
    for (int i = 1; i <= vec.size(); i++)
    {
        for (int j = 1; j <= i; j++)
        {
            cout << i << " ";
        }
    }

    print_vector(vec, " ");
    print_vectorStr(vecString, " ");

    return 0;
}
c++


Solution 1:[1]

If you really need a vector of strings, and need to reproduce the output in a comma-separated pattern, you can do something simple like:

#include <iostream>
#include <vector>
#include <string>

int main () {
  
  size_t n = 0;                           /* unsigned variable for n */
  std::vector<std::string> pattern{};     /* vector of strings */
  
  std::cout << "enter n: ";
  if (!(std::cin >> n)) {                 /* validate EVERY user-input */
    std::cerr << "error: invalid input.\n";
    return 1;
  }
  
  for (size_t i = 0; i <= n; i++) {           /* loop n times from 1 */
    for (size_t j = 0; j < i; j++) {          /* loop i times */
      pattern.push_back(std::to_string(i));   /* add i i's to string */
    }
  }
  
  /* loop over each string in pattern with index to control ',' output */
  for (size_t i = 0; i < pattern.size(); i++) {
    if (i) {                    /* if not first string */
      std::cout.put(',');       /* output ',' */
    }
    std::cout << pattern[i];    /* output string */
  }
  std::cout.put('\n');          /* tidy up with newline */
}

Note above you must validate EVERY user-input. Otherwise, what would happen if the user slipped and tapped 't' instead of 5? Also note, to control the ',' separator for output, you can either keep a counter and use a range-based for loop, or, since you need a counter anyway, just use a normal conditioned for loop.

Example Use/Output

$ ./bin/num_pattern
enter n: 2
1,2,2
$ ./bin/num_pattern
enter n: 5
1,2,2,3,3,3,4,4,4,4,5,5,5,5,5

or

$ ./bin/num_pattern
enter n: t
error: invalid input.

Look things over and let me know if you have further questions.

Solution 2:[2]

This is more a less a mathematical problem.

Of course everybody will implement the naive solution with a double nested loop. It is easy and very very fast.

But there is also an analytical solution. We can simply calculate the value of the series using a simple formula. All is based on the arithmetic series.

Let us look at the series and count the number of occurences of the digits:

Series:            1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6
Count of numbers:  1  2    3      4        5          6

If we want to know, how many numbers the series contains, we need to add up 1+2+3+4+5+6. Or more general, 1+2+3+...+k. And this can be easily calculated with a well known formula (see here):

sum = k * (k + 1) / 2

If we want to know, which is the first occurence of a number (k+1), then we know, that before this number, there will be k * (k + 1) / 2other numbers.

Example: How many numbers are in front of the first occurence of 7?

Series:            1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6           7
Count of numbers:  1  2    3      4        5          6         1+2+3+4+5+6 = 21   

So, 21 numbers are in front of that. Ok, now more general. Let's set the sum formular in an equation to equal n and the play a little bit. So, before our number k=7 there are there (one less) k * (k-1) / 2 values. Let us use this and put it into an equation for any number n=k+1 and play a little bit:

k(k-1)/2 = n
k^2-k = 2n
k^2-k-2n = 0

Solve the standard quadratic equation for K (with p=-1 and q=-2n)

k =  1/2 + sqrt( (-1*-1)/4 - (-2n))
k =  1/2 + sqrt( 1/4 +2n)
k =  1/2 + sqrt( 1 + 8n)
k =  (1 + sqrt( 1 + 8n))/2

So, some simple mathematics: if we do this as integer division, we get the count of occurrences for each number. This gives us the final formula for the number at index n:

(int)((1 + std::sqrt(1 + 8 * n)) / 2)

Please note: index starts with 1 here!!!

Cool. We can calculate the number at a given position or for all positions. And we know, how many numbers we need to store.

If we want to store this in a std::vector, then we can define the vector together with the size (k * (k + 1) / 2).

And we can use the above function to fill the vector with std::generate with all the needed numbers.

The result is a completely loopless and very simple piece of code.

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

int main() {

    // Get, check and update user input
    if (int k{}; (std::cin >> k) and (k > 0)) {

        // Create a vector with the needed number of elements
        std::vector<std::string> pattern(k * (k + 1) / 2);

        // Define a generator and create the sequence
        auto generator = [n = 0]() mutable->std::string {return std::to_string((int)((1 + std::sqrt(1 + 8 * n++)) / 2)); };
        std::generate(pattern.begin(), pattern.end(), generator);

        // Simple output
        std::copy(pattern.begin(), pattern.end(), std::ostream_iterator<std::string>(std::cout, " "));
    }
    else std::cerr << "\nInvalid input\n";
}

And the 100'000'000th entry will be 14142, calculated without any loop . . .

Solution 3:[3]

I need to put it into a string vector

You can use std::vector::push_back to add(push_back) more elements into a vector as shown below. Moreover, you can use std::to_string to convert the int to std::string. Also note that there is no need to create a std::vector<int>. You can just directly use push_back to push/add elements into vecString using to_string as shown below:

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

void print_vectorStr(const std::vector<std::string> &vec, std::string sep = "")
{
    std::cout << "\nThe vector string elements are: ";
    for (auto elem : vec)
    {
        std::cout << elem << sep;
    }
    std::cout << std::endl;
}

int main()
{

    int n;
    std::cout << "insert n \n";
    std::cin >> n;

    std::vector<std::string> vecString;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            
            vecString.push_back(std::to_string(i)); //add element into the vecString
        }
    }
    
    print_vectorStr(vecString, " ");//prints the required pattern

}

Demo

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3