0

I would like to check how many subsets S of the set [1, ..., 15] there are so that it is impossible to choose two elements from S such that their sum is a multiple of 3.

The algorithm to check this is as follows: there is a natural bijection between the subsets of [1, ..., 15] and the strings of length 15 with two characters (assume the two characters are '0' and '1' to fix a convention), where the character '0' in position i means that the integer i is not in the subset, while the character '1' in position i means that the integer i is in the subset. For example, the string "111001000000000" is associated to the subset {1, 2, 3, 6}. This subset does not fulfill the constraint described above.

I wrote a C++ code to generate all such strings, convert them to a vector of ints between 1 and 15, and check for all couples in this set if there is one whose sum is a multiple of 3.

This is the code:

#include <algorithm>
#include <bitset>
#include <cmath>
#include <iostream>
#include <vector>


bool check(const std::vector<int>& dset) {
    if (dset.size() == 1) {
        if (dset[0] % 3 == 0) { return false; }
    }
    for (size_t i = 0; i < dset.size() - 1; ++i) {
        auto a = dset[i];
        for (size_t j = i + 1; j < dset.size(); ++j) {
            auto b = dset[j];
            if ((a + b) % 3 == 0) { return false; }
        }
    }
    return true;
}


int main() {
    const int N = 15;  // We consider subsets of [1, ..., N].
    int approved = 1;  // We automatically approve the empty set.
    std::bitset<N> set;
    for (int n = 1; n < std::pow(2, N); ++n) {
        set = std::bitset<N>(n);
        std::vector<int> dset(set.count());
        size_t j = 0;
        for (int i = 1; i <= N; ++i) {
            if (set[i - 1]) {
                dset[j++] = i;
            }
        }
        // Sweep through all couples in dset.
        if (check(dset)) {
            ++approved;
        }
    }
    std::cout << approved << " out of " << std::pow(2, N) << std::endl;
}

The problem is that my code returns 373, which is the wrong answer (the correct one should be 378). I guess I am doing something wrong here, but I cannot find the error in my code.

J. D.
  • 279
  • 1
  • 9
  • Change your code to print the approved sets and then diff those against a known-good solution generated in Python or by some other program (perhaps with smaller N). – John Zwinck Nov 27 '19 at 11:26
  • Maybe it is just a matter of conventions: I just checked that if I approve all subsets with only one element, I get the expected result. But still I don't understand what is going on, since the additional subsets I accept in this way are just 3, not 5 (= 378 - 373). – J. D. Nov 27 '19 at 11:53

1 Answers1

0

In check() function you don't need to check for dset size being 1, since it is taken care below in the for loop from index i = 0 till valid size. Remove below if statement which should result valid number whose sum is multiple of 3:

if (dset.size() == 1) {
    if (dset[0] % 3 == 0) { return false; }
}
Sunil Bojanapally
  • 12,528
  • 4
  • 33
  • 46
  • If I do so, the code would approve these subsets: {3}, {6}, {9}, which should be rejected instead. – J. D. Nov 27 '19 at 11:53