get index of smallest number of array

hello
I'm trying to get the index of the smallest element of an array, IF this element index satisfies a condition in another array. explaining:
i have an int array and a bool array
int count[] = {0, 0, 0, 0};
bool avail[] = {true, true, true, true};

every iteration i choose the bools randomly. i want to get the smallest number in count[] which is also 'true' in avail[]. like in
count {10, 20, 30, 40}
avail {false, false, true, true}
should return 2 (third element of both arrays)

I got to this, but sometimes I get the index 0 even if it is false (it happens when the index 0 is smaller than the others). But I feel there must be a simpler way to do it...

oh, and every iteration I also increase count[] by one in the current choosen index.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <random>
#include <chrono>

int main(){
    std::default_random_engine gen(std::chrono::system_clock::now().time_since_epoch().count());
    std::uniform_int_distribution<int> dist(0, 1);
    int count[] = {0, 0, 0, 0};
    for(size_t i=0; i<100; i++){
        bool avail[] = {true, true, true, true};
        for (size_t n=0; n<sizeof(avail)/sizeof(avail[0]); n++){
            avail[n] = dist(gen);
        }
        size_t choosen = 0;
        for (size_t n=0; n<sizeof(count)/sizeof(count[0]); n++){
            if (count[n] <= count[choosen] && avail[n] == true){
                choosen = n;
            }
        }
        count[choosen]++;
        std::cout << "choosen: " << choosen << "\tTrue: " << avail[choosen] << std::endl;
    }
    for (size_t n=0; n<sizeof(count)/sizeof(count[0]); n++){
            std::cout << count[n] << std::endl;
    }
}


possible output (what shouldn't happen is in bold)
choosen: 1	True: 1
choosen: 2	True: 1
choosen: 0	True: 1
choosen: 1	True: 1
choosen: 1	True: 1
choosen: 0	True: 0
choosen: 3	True: 1
choosen: 0	True: 0
choosen: 1	True: 1
choosen: 2	True: 1
choosen: 2	True: 1
choosen: 3	True: 1
choosen: 0	True: 1
choosen: 2	True: 1
choosen: 1	True: 1
choosen: 3	True: 1
choosen: 3	True: 1
choosen: 2	True: 1
choosen: 0	True: 0
choosen: 1	True: 1
choosen: 0	True: 1
25
25
25
25
It's an unusual algorithm. Is it meant to model something?

I think your problem is that you start chosen at 0, whether or not element 0 is avail.

As an example of something obviously wrong, avail could easily be all false since it's filled randomly and is only 4 long. Even if there is no available elements from count, your code still increments count[chosen].

To fix it you could either:
1. find the lowest avail element and start there, handling the special case where there are no avail elements.
2. Or you could start chosen in an "unset" state.
For size_t it's pretty common to use size_t(-1) to mean "unset".
I used the UNSET idea below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <iomanip>
#include <random>
#include <chrono>

void print(const int *count, size_t size) {
    for (size_t n = 0; n < size; n++) std::cout << std::setw(2) << count[n] << ' ';
    std::cout << '\n';
}

int main(){
    using std::cout;
    const size_t UNSET {size_t(-1)};

    std::default_random_engine gen(std::random_device{}());
    std::uniform_int_distribution<int> dist(0, 1);

    const size_t Size { 4 };
    int count[Size] { };

    for (size_t i = 0; i < 100; i++) {

        print(count, Size);

        bool avail[Size] { };
        for (size_t n = 0; n < Size; n++) {
            avail[n] = dist(gen);
            cout << std::setw(2) << avail[n] << ' ';
        }
        cout << '\n';
            
        size_t chosen {UNSET};
        for (size_t n = 0; n < Size; n++)
            if (avail[n] && (chosen == UNSET || count[n] <= count[chosen]))
                chosen = n;

        if (chosen != UNSET) {
            for (size_t j = 0; j < chosen; j++) cout << "   ";
            cout << " ^\n";

            count[chosen]++;
        }
    }

    print(count, Size);
}

@Stauricus,
What are you actually trying to do? (NOT ... how are you trying to do it).

As @DizzyDon has pointed out, there are going to be cases where there are no unmasked indices (here: 1 in 16 iterations, or more than 6 in 100), yet you will, by default, have set 'choosen' [sic] to 0, because that was the initial value and it is not subsequently changed.

Explain what your ultimate purpose is. Otherwise we have an XY problem.
hey guys. I'm using it to choose positions for buildings in a grid. the four bools represent available directions (N, S, W, E) that I already evaluated, so in the original algorithm there are no cases where all bools are false. neverthless I still check for this possibility, for safety. the count[] just holds how many buildings are turned to each side, so I can keep track of balance.

@DizzyDon thank you! just did like you said, UNSET state. it's working perfectly now.

by the way, it's a small game i'm making for personal fun
https://i.postimg.cc/P5GVs8z7/Captura-de-tela-de-2022-02-07-08-10-16.png

thanks for the help!
Topic archived. No new replies allowed.