-3

I have an std::vector with fixed size N = 5. I want every element of the vector to be randomly selected between two positive numbers, in particular 1 and 12. (zeros are not allowed).Each element should be unique on the vector.

How can I do this? The implementation so far allows elements to be zero and have duplicates in the vector. I want to improve in order not to allow zeros and duplicates

Code so far:

#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <random>

int main() {
    std::random_device rd;
    std::mt19937 gen(rd());

    constexpr int MAX = 20;
    constexpr int LINES = 5;

    int sum{};
    int maxNum = 12;
    int minNum = 1;

    std::array<int, LINES> nums;

    for (int i = 0; i < LINES; ++i) {
        maxNum = std::min(maxNum, MAX - sum);
        minNum = std::min(maxNum, std::max(minNum, MAX - maxNum * (LINES - i)));
        std::cout << minNum << " " << maxNum << std::endl;
        std::uniform_int_distribution<> dist(minNum, maxNum);
        int num = dist(gen);

        nums[i] = num;
        sum += num;
    }

    std::shuffle(std::begin(nums), std::end(nums), gen);
    std::copy(std::begin(nums), std::end(nums), std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;
}
cateof
  • 6,608
  • 25
  • 79
  • 153

2 Answers2

0

Ok, there are three requirements:

  • Sum should be fixed
  • Non-repetitive numbers
  • Numbers should be in the range

For requirement #1 it is better sample from distribution which already have the property - Dirichlet distribution. For simplest case where all parameters are equal to 1, it is also known as simplex sampling, producing numbers uniformly distributed on N dimensional simplex. HEre is link to the C++ code.

To satisfy second&third requirement, just use acceptance/rejection

std::linear_congruential_engine<uint64_t, 2806196910506780709ULL, 1ULL, (1ULL<<63ULL)> ugen;

float MAX = 20.0f;
Simplex s(0.0f, 20.0f);

std::vector<float> v(5, 0.0f);
std::vector<int>   r(5, 0);

for( ;; ) {
    s.sample(v, ugen); // sampled Dirichlet
    for(int k = 0; k != v.size(); ++k) {
        r[k] = 1 + int(v[k]);
    }
    std::sort(r.begin(), r.end());
    if (*r.rbegin() > 12) // array is sorted, just check last largest element
        continue;
    if (std::unique(r.begin(), r.end()) == r.end()) // no duplicates, good to go
        break;
}

return r;
Severin Pappadeux
  • 18,636
  • 3
  • 38
  • 64
-2

declare a boolean that starts at false, after that do a while that whill iterate until that flag is true, inside that while you will iterate until the sum of both of them = 5, you will check if the sum = 5 with an If statement, if they are then you will change the value of the flag to true. Easy as that.

I recommend you study a bit more, since you are probably new to programming (at least thats what the question makes me think, if you aren't then there is something clearly wrong).

Also, there ya go: If statements
While loop

MrSanchez
  • 317
  • 4
  • 14
  • Thank you. Indeed I am really new to programming. I will start reading the "if statement" immediately. – cateof May 31 '17 at 15:17
  • Ok then that explains it, read the while loop if you haven't also, and I recommend that you look for some c++ book to read. – MrSanchez May 31 '17 at 15:20
  • It is called segmentation fault. Have a look here: https://stackoverflow.com/questions/2346806/what-is-a-segmentation-fault – cateof May 31 '17 at 15:23