-5

I want to print the first number that first counts to 4, for example, I have this random function, I want to see the first number that reaches 4 times. so it's the first number that prints himself 4 times. For example:

    int n;
    int count1 = 0;
    int count2 = 0;
    int count3 = 0;
    while (true) {
        cout << "Enter a number btween 1-3" << endl;
        cin >> n;
        if (n == 1) {
            count1++;
        }
        if (n == 2) {
            count2++;
        }
        if (n == 3) {
            count3++;
        }
        if (count1 == 4) {
            cout << "You printed the number 1 4 times!";
            break;
        }
        if (count2 == 4) {
            cout << "You printed the number 2 4 times!";
            break;
        }
        if (count3 == 4) {
            cout << "You printed the number 3 4 times!";
            break;
        }

But what would I do if it was 1-1000 numbers not just 1-3 what would I do then?

I want to do that but on a random function - the first number that the count of that number is 4 times print the number -

int fun() {
    srand(time(NULL));
    return rand() % 3;
}

Then I want to do in main that first number that reaches for example 4 times print this number.

I tried doing something like this:

for (int i = 0; i < 31; i++) {
        arr[fun()]++;
        cout << arr[fun()];
        if (arr[fun()] == 4) {
            cout << arr[fun()];
        }
    }
  • If it was 1000 numbers, you would use a for loop. – Axiumin_ Aug 12 '19 at 04:37
  • @Axium You missed the entire point –  Aug 12 '19 at 04:38
  • I’m not answering, I’m suggesting. – Axiumin_ Aug 12 '19 at 04:38
  • @Axium That's not even a suggestion, because if so what will the for loop be? –  Aug 12 '19 at 04:40
  • You would use map or vector (or array if this is some behinner exercise where you are forbidden from using proper containers). – hyde Aug 12 '19 at 04:41
  • To add more on my suggestion, you could use a vector which consists of a set. The set would include how many times the number has been occurred in the loop and the actual number. – Axiumin_ Aug 12 '19 at 04:41
  • it is. But how do I use it? I know that there's the arr[i]++. But I don't really understand how to use it. Besides using a vector isn't really effective it would just be too much effort. I know that. –  Aug 12 '19 at 04:42
  • @Axium Look at my last comment. –  Aug 12 '19 at 04:44
  • Too much effort? What is that supposed to mean? What else do you propose? – Axiumin_ Aug 12 '19 at 04:45
  • 1
    He used an array, which would require almost the same amount of work as a vector. I was only suggesting a bit of code. – Axiumin_ Aug 12 '19 at 04:48
  • 1
    See, the guy switched to a vector. – Axiumin_ Aug 12 '19 at 04:51

2 Answers2

4

You would use an collection (such as a vector) for that, rather than a thousand separate variables :-)

For a start, if you want random numbers in the range 1..3, you would use (rand() % 3) + 1. However, you can use the range 0..n-1 rather than 1..n and just adjust the value after the loop.

First step is to create and initialise the counts of each number to zero:

const int SZ = 1000;
std::vector<int> count(SZ, 0);

Then your loop just generates random numbers and adjusts the relevant count, until one of them reaches the target value:

int num;
for (;;) { // infinite loop
    num = rand() % SZ;
    ++count[num];
    if (count[num] == 4)
        break; // exit infinite loop when one of them reaches four.
}

Then you just simply output the one that reached four first. Note that, since we're doing 0..999, we map that to 1.1000:

std::cout << ++num << " reached a count of four first\n";

A complete program showing this can be seen below:

#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>

int main() {
    srand(time(nullptr));

    const int SZ = 1000;
    std::vector<int> count(SZ, 0);

    int num;
    for (;;) { // infinite loop
        num = rand() % SZ;
        ++count[num];
        if (count[num] == 4)
            break; // exit loop when one of them reaches four.
    }

    std::cout << ++num << " reached a count of four first\n";
}

A sample run of that (ensuring a delay so random number generator gets different seed):

>> for i in {1..10} ; do sleep 1 ; ./testprog ; done )
296 reached a count of four first
520 reached a count of four first
205 reached a count of four first
239 reached a count of four first
822 reached a count of four first
260 reached a count of four first
421 reached a count of four first
444 reached a count of four first
21 reached a count of four first
92 reached a count of four first
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    I understand that `rand()` comes from the post, but why would you use `#define` instead of `const`? –  Aug 12 '19 at 04:48
  • Yeah... I gave the rand() function for the example I usually use the random library anyway. But can you see what I've tried and tell me what is wrong with it? (I did a loop that initialize everything to 0) –  Aug 12 '19 at 04:50
  • 2
    @dyukha, I originally wrote it in C with an array. Converted to C++ when I saw the tag :-) – paxdiablo Aug 12 '19 at 04:51
  • 1
    @paxdiablo, Isn't it better to use `std::vector count{SZ, 0}`, than `push_back()` 1000 times? – kuro Aug 12 '19 at 04:53
  • @kuro, yes. Not relevant to the method itself but I suppose I should be showing best practices even in support code :-) Will change. – paxdiablo Aug 12 '19 at 04:56
  • 1
    @SomeGuy, It works, but it can lead to bad consequences in larger programs. don't use `rand`: https://stackoverflow.com/a/26440334/2956272, prefer `const` over `define`: https://stackoverflow.com/a/14041847/2956272, don't use c-style arrays: https://stackoverflow.com/a/18869117/2956272. –  Aug 12 '19 at 05:00
  • 2
    @SomeGuy, I suggest you recheck the code you're running. The code I've given has been running for a couple hundred iterations without fault. – paxdiablo Aug 12 '19 at 05:29
  • @SomeGuy, it got through 1757 iterations without a problem. Then I got bored and killed it :-) – paxdiablo Aug 12 '19 at 05:58
  • 1
    Thanks, @Ted, I think I'd transcribed an earlier (buggy) version and just forgot to update it in toto - I probably should have replaced the lot rather than trying to do it piecemeal. – paxdiablo Aug 13 '19 at 11:43
-1

The last answer was out of range. My answer is using only an array

while(1) {
        int f = rand() % 3;
        count[f]++;
        cout << f << endl;
        if (count[f] == 4) {
            cout <<"4 times" <<f;
            break;
        }
    }
  • Why not use a while loop instead of a for loop? – Axiumin_ Aug 12 '19 at 05:20
  • 1
    @Axium Because it doesn't matter. But if you want it with a while loop sure. –  Aug 12 '19 at 05:21
  • It’s inherently better practice, and it makes your code more readable. So, it does in fact matter. – Axiumin_ Aug 12 '19 at 05:21
  • 1
    @Axium It's just I don't see how it's more readable. I guess 1 year ago I could but now it just seems the same. –  Aug 12 '19 at 05:25
  • `while(true)` is literal. It just means while the statement `true` is evaluated to be `true`. `for(;;)` may confuse others. That’s why I’m saying that it improves general readability. If I was a “newbie”, I would likely be confused and wouldn’t understand what it meant. – Axiumin_ Aug 12 '19 at 05:28
  • 2
    @Axium: `for(;;)` is also literal and should be understood. The `for` loop has no preamble, no termination condition, and no iteration post-processing. Since it will be seen in a lot of code, developers should put in the effort to learn it :-) – paxdiablo Aug 12 '19 at 05:34
  • 1
    @Axium Though I prefer `while (true)`, `for(;;)` is by no means bad practice. See https://stackoverflow.com/questions/20186809/endless-loop-in-c-c As shown in the question, in the Linux kernel code, `for(;;)` shows up the most. The accepted answer highlights the fact that "If even a C beginner knows that for(;;) means an eternal loop, then who are you trying to make the code more readable for?" – iz_ Aug 12 '19 at 05:35
  • `#define forever for(;;)`. Or, maybe better: `#define until_break_return_or_goto ...` :-) – paxdiablo Aug 12 '19 at 05:40
  • 3
    "_The last answer was out of range_" - Care to explain? @paxdiablo's answer gives an answer in the range `[1, 1000]` as was asked for and has no out of range problems as I can see. – Ted Lyngmo Aug 12 '19 at 08:00
  • @TedLyngmo I forgot. You can run the code and you'll see –  Aug 13 '19 at 02:40
  • 2
    @SomeGuy Oh, I see what you mean. I found a subtle bug in the previous answer and (hopefully) fixed it. – Ted Lyngmo Aug 13 '19 at 11:26
  • @TedLyngomo Yes, but still, I think the way that I did it it's better. better to understand too. –  Aug 14 '19 at 12:36