Inserting multiple elements into a 2D block - c++

I am attempting to calculate the energy of a series of elements inside a vector of vectors. As soon as the particular element has the right energy, it is then pushed into another vector of vectors. Here is an example because it is hard to explain:
bool energy(const std::vector<double> &vals)
{
float sum = 0.0;
for(unsigned i=0; (i < vals.size()); i++)
{
sum += (vals[i]*vals[i]);
}
//cout << sum << endl;
return (sum >= 5);
}
int main(int argc, char *argv[]) {
std::vector<vector<double> > vals {
{0, 0, 0, 0, 0}, // This has an energy of "0" -> does not count
{1, 1, 1, 1, 1}, // This has an energy of "5" -> push_back to vector[0]
{1, 1, 1, 1, 1}, // This has an energy of "5" -> push_back to vector[0]
{1, 1, 1, 1, 1}, // This has an energy of "5" -> push_back to vector[0]
{1, 2, 1, 1, 1}, //This has an energy of "5" -> push_back to vector[0]
{0, 0, 0, 0, 0}, // This has an energy of "0" -> does not count && start a new
// vector
{1, 2, 3, 4, 5}, // This has an energy of "55" -> push_back to vector[1]
{1, 2, 3, 4, 5}, // This has an energy of "55" -> push_back to vector[1]
{1, 2, 3, 4, 5}, // This has an energy of "55" -> push_back to vector[1]
{1, 2, 3, 4, 5} // This has an energy of "55" -> push_back to vector[1]
};
std::vector<vector<double> > clusters;
std::vector<vector<double> > tmp;
//std::for_each(vals.begin(), vals.end(), energy);
int j = 0;
for(unsigned i=0; (i < vals.size()); i++)
{
if(energy(vals[i]))
{
clusters.resize(j + 1);
clusters[j] = vals[i];
}else if(!energy(vals[i]) && energy(vals[i+1]))
{
j++;
}
}
for(unsigned i=0; (i < clusters.size()); i++)
{
for(unsigned j=0; (j < clusters[i].size()); j++)
{
cout << clusters[i][j] << ' ';
}
cout << endl;
}
}
What should happen
There should be 2 elements of the vector of vectors named clusters each containing the values of:
clusters[0] = {
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 2, 1, 1, 1
};
`clusters[1] = 1, 2, 3, 4, 5,
1, 2, 3, 4, 5,
1, 2, 3, 4, 5,
1, 2, 3, 4, 5}`
What is happening?
The vector of vectors seem to be over-riding the blocks that get inserted into them. So instead of the above, I just get the last element that it found so:
`cluster[0] = {1 2 1 1 1}
cluster[1] = {1 2 3 4 5}`
What I was thinking and attempting was to store each of the "blocks" inside a vector of vectors that contain the sufficient energy and then push all these values inside a vector<double> and then insert this vector inside the block of clusters..
Is there an alternative way, a much simpler solution to this problem?

Corrected code:
#include<vector>
#include<iostream>
using namespace std;
bool energy(const std::vector<double> &vals)
{
float sum = 0.0;
for(unsigned i=0; (i < vals.size()); i++)
{
sum += (vals[i]*vals[i]);
}
//cout << sum << endl;
return (sum >= 5);
}
int main(int argc, char *argv[]) {
std::vector<vector<double> > vals {
{0, 0, 0, 0, 0}, // This has an energy of "0" -> does not count
{1, 1, 1, 1, 1}, // This has an energy of "5" -> push_back to vector[0]
{1, 1, 1, 1, 1}, // This has an energy of "5" -> push_back to vector[0]
{1, 1, 1, 1, 1}, // This has an energy of "5" -> push_back to vector[0]
{1, 2, 1, 1, 1}, //This has an energy of "5" -> push_back to vector[0]
{0, 0, 0, 0, 0}, // This has an energy of "0" -> does not count && start a new
// vector
{1, 2, 3, 4, 5}, // This has an energy of "55" -> push_back to vector[1]
{1, 2, 3, 4, 5}, // This has an energy of "55" -> push_back to vector[1]
{1, 2, 3, 4, 5}, // This has an energy of "55" -> push_back to vector[1]
{1, 2, 3, 4, 5} // This has an energy of "55" -> push_back to vector[1]
};
std::vector<vector<double> > tmp(vals.size());
std::vector<vector<double> > clusters(vals.size());
int j = 0;
for(unsigned i=0; (i < vals.size()); i++)
{
if(energy(vals[i]))
{
clusters[j].insert(clusters[j].end(), vals[i].begin(), vals[i].end());
}else if(!energy(vals[i]) && energy(vals[i+1]))
{
j++;
}
}
for(unsigned i=0; (i < clusters.size()); i++)
{
for(unsigned j=0; (j < clusters[i].size()); j++)
{
cout << clusters[i][j] << ' ';
}
cout << endl;
}
}
The output is:
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5

Your problem is here:
for(unsigned i=0; (i < vals.size()); i++)
{
if(energy(vals[i]))
{
clusters.resize(j + 1);
clusters[j] = vals[i];
}
else if(!energy(vals[i]) && energy(vals[i+1]))
{
j++;
}
}
First of all, your energy function returns an int, so when the return value is non-zero, it will evaluate the condition to true, and when it is 0, it will be false.
Second, you are effectively doing a push_back in the if branch, but you are only pushing the current vector (you aren't appending it to an existing vector).
To fix this, I would recommend using a map<int, vector<int>> so you can quickly reference each cluster (e.g. the ones with energy of 5 would have a key of 5, so you would either create a new vector and insert those values, or append to the one that already exists there). If you need it in a vector of vectors, you can always iterate through the map after you have them sorted and swap them into the vector of vectors.

you could simplify a lot your code, so it would be much more easy to read and understand, for example take you energy function, you could write it in a single line using algorithms:
return std::inner_product(vals.begin(), vals.end(), vals.begin(), 0.) >= 5;

I changed a piece of code make it works
int j = 0;
for(unsigned i=0; (i < vals.size()); i++)
{
if(energy(vals[i])) {
clusters[j].insert(clusters[j].end, vals[i].begin(), vals[i].end());
}
if(!energy(vals[i]) && energy(vals[i+1])) {
clusters.push_back( tmp );
++j;
}
}
Don't use resize. You can just push_back an empty vector into your clusters.
And for each operation to append a vector, just using insert by range
void insert (iterator position, InputIterator first, InputIterator last);
Ref: http://en.cppreference.com/w/cpp/container/vector/insert

Related

How can I add an item to the structure with vector elements?

I would like to add the peak position of a vector and the peak number but I can't find a way to add the elements and then return it, or write it on console.
#include <iostream>
#include <vector>
using namespace std;
struct PeakData {
vector<int> pos, peaks;
};
PeakData pick_peaks(vector<int> v) {
PeakData result;
for (int i = 1; i < v.size() - 1; i++) {
if ((v[i] > v[i - 1]) && (v[i] > v[i + 1])) {
result.peaks.push_back(v[i]);
result.pos.push_back(i);
}
}
return result;
}
Example: pickPeaks([3, 2, 3, 6, 4, 1, 2, 3, 2, 1, 2, 3]) should return {pos: [3, 7], peaks: [6, 3]}
Add this to your main function:
int main()
{
vector<int> a = {3, 2, 3, 6, 4, 1, 2, 3, 2, 1, 2, 3};
PeakData stPickPeaks = pick_peaks(a);
vector<int> :: iterator itr;
for(itr = stPickPeaks.pos.begin(); itr<stPickPeaks.pos.end(); itr++)
{
cout <<*itr<<endl;
}
for(itr = stPickPeaks.peaks.begin(); itr<stPickPeaks.peaks.end(); itr++)
{
cout <<*itr<<endl;
}
return 0;
}
Also try to pass the parameters either by reference or pointer.

Runtime library error connected with vector

This is my code which task is to check how many times does the number appear in my array.
Error message tells me that vector subscript is out of range.
int main() {
vector<int> numbers(1,-1);
int x;
int z;
bool exit;
int digits[] = { 2, 4, 5, 3, 2, 5, 6, 3, 5, 7, 9, 2, 1, 2, 3, 4, 5, 6, 4, 3, 2, 6, 3, 4, 4, 1, 3, 7, 9, 5, 9, 2, 3, 1, 2, 3, 4, 5, 6, 2, 1, 2, 3, 4, 5, 3, 2, 7, 7, 7 };
for (int i = 0; i < (sizeof(digits) / sizeof(int)); i++) {
z = 0;
bool exit = 1;
for (int j = 0; j < (sizeof(digits) / sizeof(int)); j++) {
x = digits[i];
for (int y = 0; y < (sizeof(numbers) / sizeof(int)); y++) {
if (x == numbers[y]) {
bool exit = 0;
}
}
if (digits[j] == x && exit) {
z++;
}
}
if (exit) {
cout << "Liczba: " << x << " wystepuje: " << z << " razy" << endl;
numbers.push_back(x);
}
}
}
Visual studio tells me that my code is valid but then during compilation , cmd shows me the error message which tells me that Vector subscript out of range . I just can't figure it out how to fix it exactly , bcs i have not found that i would initialize the vector which would not exist .
At least this statement
for (int y = 0; y < (sizeof(numbers) / sizeof(int)); y++) {
does not make sense because the expression sizeof(numbers) / sizeof(int) does not yield the number of elements in the vector. Instead use
for (int y = 0; y < numbers.size(); y++) {
If I have correctly understood your task then instead of the container std::vector it is better to use either std::map or std::unordered_map.
For example
#include <iostream>
#include <map>
int main()
{
int digits[] =
{
2, 4, 5, 3, 2, 5, 6, 3, 5, 7,
9, 2, 1, 2, 3, 4, 5, 6, 4, 3,
2, 6, 3, 4, 4, 1, 3, 7, 9, 5,
9, 2, 3, 1, 2, 3, 4, 5, 6, 2,
1, 2, 3, 4, 5, 3, 2, 7, 7, 7
};
std::map<int, size_t> frequency;
for ( const auto &item : digits )
{
++frequency[item];
}
for ( const auto &p : frequency )
{
std::cout << p.first << ": " << p.second << '\n';
}
return 0;
}
The program output is
1: 4
2: 10
3: 10
4: 7
5: 7
6: 4
7: 5
9: 3

printing all increasing subsequence using recursion

I'm trying to print all increasing subsequence with following.
But it is not working accordingly.
Please explain what actually my code doing.
I'm stuck since last 1 week.
But unable to figure out.
#include <bits/stdc++.h>
using namespace std;
int temp[1000];
int ans = 1;
int cnt = 0;
void solve(int *arr, int n, int k)
{
if(k == n){
cnt++;
for(int j = 0; j < n; j++){
cout<<temp[j]<<" ";
}
cout<<endl;
return;
}
for(int i = k; i < n; ++i){
if(arr[k] <= arr[i]){
temp[k] = -2;
solve(arr, n, i+1);
temp[k] = 2;
}
}
}
int main()
{
int arr[] = {4, 1, 13, 7, 0, 2, 8, 11, 3};
//int arr[] = {-1, 1 ,2, 3, 4};
//int arr[] = {-1,1,2,3,4,11, 5,6, 2, 9};
memset(temp, -1, sizeof(temp));
solve(arr, 9, 0);
cout<<cnt<<endl;
return 0;
}
Output should be total number of enumerating increasing subsequence.
This prints all increasing subsequences:
void print(const vector<int> v) {
for (size_t i = 0; i < v.size() - 1; ++i)
cout << v[i] << ", ";
cout << v.back() << endl;
}
int solve(const vector<int>& v, size_t start, vector<int>& sequence) {
print(sequence);
int count = 1;
for (size_t i = start; i < v.size(); ++i) {
if (v[i] >= sequence.back()) {
sequence.push_back(v[i]);
count += solve(v, i + 1, sequence);
sequence.pop_back();
}
}
return count;
}
size_t solve(const vector<int>& v) {
int count = 0;
for (size_t i = 0; i < v.size(); ++i) {
vector<int> sequence{v[i]};
count += solve(v, i + 1, sequence);
}
return count;
}
Usage:
vector<int> v{4, 1, 13, 7, 0, 2, 8, 11, 3};
auto count = solve(v);
cout << "Count: " << count << endl;
Output:
4
4, 13
4, 7
4, 7, 8
4, 7, 8, 11
4, 7, 11
4, 8
4, 8, 11
4, 11
1
1, 13
1, 7
1, 7, 8
1, 7, 8, 11
1, 7, 11
1, 2
1, 2, 8
1, 2, 8, 11
1, 2, 11
1, 2, 3
1, 8
1, 8, 11
1, 11
1, 3
13
7
7, 8
7, 8, 11
7, 11
0
0, 2
0, 2, 8
0, 2, 8, 11
0, 2, 11
0, 2, 3
0, 8
0, 8, 11
0, 11
0, 3
2
2, 8
2, 8, 11
2, 11
2, 3
8
8, 11
11
3
Count: 48

How do i remove duplicates from this recursion code? Many 6-sided dice will be rolled and print only unique combinations that add up to a desired sum

in the following code, I'm able to print all the dice combinations that add up to a desired sum. I'd like some help in tweaking the code to remove the duplicate entries.
void rep(int n, string ans, int currentSum, int targetSum)
{
if(n==0)
{
if(currentSum==targetSum)
cout << "{" << ans << "}"<<endl;
}
else
{
for(int i=1 ; i<=6 ; i++)
{
if(n>1)
{
rep(n-1, ans + to_string(i) + ", ", currentSum+i, targetSum);
}
else
{
rep(n-1, ans + to_string(i), currentSum+i, targetSum);
}
}
}
}
void ManyDiceSum(int howManyDice, int targetSum)
{
if(howManyDice>0)
rep(howManyDice,"",0,targetSum);
}
int main()
{
int howManyDice, targetSum;
howManyDice=3;
targetSum=7;
ManyDiceSum(howManyDice, targetSum);
return 0;
}
Output for 3 dice and target sum of 7 should be:
{1, 1, 5}
{1, 2, 4}
{1, 3, 3}
{2, 2, 3}
But, my code is displaying all combinations:
{1, 1, 5}
{1, 2, 4}
{1, 3, 3}
{1, 4, 2}
{1, 5, 1}
{2, 1, 4}
{2, 2, 3}
{2, 3, 2}
{2, 4, 1}
{3, 1, 3}
{3, 2, 2}
{3, 3, 1}
{4, 1, 2}
{4, 2, 1}
{5, 1, 1}
Constraints are: It has to use recursion and use only 1 loop if
necessary.
First of all you do not need to pass both target and current sum to the function, only target is enough, and checking it first will speed up whole process significantly:
void rep( int n, int target, std::string ans = std::string(), int last = 1 )
{
if( n == 0 ) {
if( target == 0 )
std::cout << "{" << ans << "}" << std::endl;
return;
}
const auto limit = std::min( 6, target );
// or even following, but not sure this is quite right though
//const auto limit = std::min( 6, target - n * last );
for( int i = last ; i <= limit; ++i )
rep(n-1, target - i, ans + to_string(i) + ( n > 1 ? ", " : "" ), i );
}
void ManyDiceSum( int howManyDice, int TargetSum )
{
if (howManyDice > 0)
rep( howManyDice, TargetSum );
}
and to avoid duplicates continue from the last number you started.
A exemplary solution based on #Jarod42's comment:
void rep(int n, std::string ans, int currentSum, int TargetSum, int startFrom) {
if (n == 0) {
if (currentSum == TargetSum)
std::cout << "{" << ans << "}" << std::endl;
} else
for (int i = startFrom; i <= 6; i++)
if (n > 1)
rep(n-1, ans + to_string(i) + ", ", currentSum + i, TargetSum, i);
else
rep(n-1, ans + to_string(i), currentSum + i, TargetSum, i);
}
void ManyDiceSum(int howManyDice, int TargetSum) {
if (howManyDice > 0)
rep(howManyDice, "", 0, TargetSum, 1);
}

function using unordered_map to determine subarray indices failing

I'm attempting to cout the elements of input array "arr" that was used to determine max sum of a subarray, hereinafter named "maxSum" (which is determined elsewhere, and confirmed to be correct). The function showSubArray() accepts as parameters the array arr, the length of the array n, and maxSum. Input array is positive and negative ints. Below is a set of test arrays with the result. Fail means that arr[0] is printed to the screen with a space separating them INFINITELY. I can't see any discernable pattern in the input that would cause this. Any help greatly appreciated and I am not beholden to the unordered_map approach. Getting the indices from the function that determined the maxSum is not an acceptable solution.
#include <unordered_map>
#include <iostream>
using std::cout;
int main() {
//int arr[] = { 1, 4, -9, 8, 1, 3, 3, 1, -1, -4, -6, 2, 8, 19, -10, -11 };
// runs ok, inputs: n=16, maxSum = 34
//int arr[] = { 2, 9, 8, 6, 5, -11, 9, -11, 7, 5, -1, -8, -3, 7, -2 };
// ***fails, inputs: n=15, maxSum = 30
//int arr[] = { 10, -11, -1, -9, 33, -45, 23, 24, -1, -7, -8, 19 };
// runs ok, n=12, maxSum = 50
//int arr[] = { 31, -41, 59, 26, -53, 58, 97, -93, -23, 84 };
// runs ok n=10 maxSum = 187
//int arr[] = { 3, 2, 1, 1, -8, 1, 1, 2, 3 };
// ***fails, inputs: n=9 maxSum = 7
int arr[] = { 12, 99, 99, -99, -27, 0, 0, 0, -3, 10 };
// ***fails, n=10 maxSum = 210
//int arr[] = { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
// runs ok, inputs: n=9 maxSum = 6
showSubArray(arr, n, maxSum);
return 0;
}
void showSubArray(int arr[], int n, int maxSum) {
std::unordered_map<int, int> aMap;
int accumulator = 0;
for (int i = 0; i < n; i++) {
accumulator += arr[i];
if (accumulator == maxSum) {
for(int j = 0; j <= i; j++) {
// ACB found error here ^ (I had it as "i")
cout << arr[j];
cout << " ";
}
cout << '\n';
return;
}
if (aMap.find(accumulator - maxSum) != aMap.end()) {
for (int j = aMap[accumulator - maxSum] + 1; j <= i; j++) {
cout << arr[j];
cout << " ";
}
cout << '\n';
return;
}
aMap[accumulator] = i;
}
cout << "Subarray not found!\n";
}
if (accumulator == maxSum) {
for(int j = 0; j <= i; i++) {
you are incrementing i here but you want to increment j cause 0 will always be smaller i for i > 0 until it overflows