'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;
}
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
}
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 |
