Negotiate Reasonable Groups

Problem Description

This problem is from Zhihu https://www.zhihu.com/question/596919226

problem_description

Write a program to find a reasonable answer.

Assume there is a meeting and there are 5 possible studunts as attendees - A, B, C, D, and E. Distinguish who will attend the meeting according to the below conditions:

  1. If A attends, B will also attend.
  2. B and C can’t attend at the same time.
  3. Either C and D will both attend, or they both won’t attend.
  4. At least one person from D and E will attend.
  5. If E attends, then A and D will also attend.

Solutions

bitset

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
#include <bitset>
#include <iostream>

bool check(const std::bitset<5>& student) {
// Quick fail strategy
if (student[0]) {
if (!student[1]) {
return false;
}
}

if (student[1] && student[2]) {
return false;
}

if (student[2] != student[3]) {
return false;
}

if (!student[3] && !student[4]) {
return false;
}

if (student[4]) {
if (!student[0] || !student[3]) {
return false;
}
}

return true;
}

int main() {
constexpr int n = 5;
for (int i = 0; i < 1 << n; ++i) {
std::bitset<n> s(i);
if (check(s)) {
std::cout << s.to_string() << std::endl;
}
}
return 0;
}

The result 01100 means that two person - C and D - will attend.

Condition Conjunction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bool check(const std::bitset<5>& student) {
auto cond1 = [&]() {
return !student[0] || student[1];
};
auto cond2 = [&]() {
return !student[1] || !student[2];
};
auto cond3 = [&]() {
return student[2] == student[3];
};
auto cond4 = [&]() {
return student[3] || student[4];
};
auto cond5 = [&]() {
return !student[4] || (student[0] && student[3]);
};

return cond1() && cond2() && cond3() && cond4() && cond5();
}

Plug-in Transformation

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <bitset>
#include <functional>
#include <iostream>
#include <vector>

template <size_t Size>
class Solver {
public:
using ConditionCallback = std::function<bool(const std::bitset<Size>&)>;
void register_condition(ConditionCallback condition) {
m_conditions.push_back(std::move(condition));
m_is_clean = false;
}

void solve() {
// return directly if the result is clean
if (m_is_clean) {
return;
}

clear_result();

auto check = [this]() {
for (const ConditionCallback& condition : m_conditions) {
if (!condition(m_bitset)) {
return false;
}
};

return true;
};

for (int i = 0; i < (1 << Size); ++i) {
m_bitset = i;
if (check()) {
m_results.push_back(m_bitset.to_string());
}
}

m_is_clean = true;
}

void print() {
for (const std::string& result : m_results) {
std::cout << result << std::endl;
}
}

private:
void clear_result() {
m_bitset = 0;
m_results.clear();
}

std::bitset<Size> m_bitset;
std::vector<ConditionCallback> m_conditions;
std::vector<std::string> m_results;

bool m_is_clean{true};
};

int main() {
Solver<5> solver;

solver.register_condition([](const auto& student) {
return !student[0] || student[1];
});
solver.register_condition([](const auto& student) {
return !student[1] || !student[2];
});
solver.register_condition([](const auto& student) {
return student[2] == student[3];
});
solver.register_condition([](const auto& student) {
return student[3] || student[4];
});
solver.register_condition([](const auto& student) {
return !student[4] || (student[0] && student[3]);
});

solver.solve();
solver.print();

return 0;
}

Negotiate Reasonable Groups
http://wasprime.github.io/SystemDesign/Negotiate-Reasonable-Groups/
Author
wasPrime
Posted on
April 22, 2023
Updated on
May 3, 2023
Licensed under