get index of smallest number of array

Feb 6, 2022 at 5:11pm
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
Feb 6, 2022 at 6:50pm
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);
}

Feb 7, 2022 at 9:28am
@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.
Feb 7, 2022 at 11:23am
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.