Skip to content

Instantly share code, notes, and snippets.

@kevinlynx
Created October 31, 2013 11:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevinlynx/7248414 to your computer and use it in GitHub Desktop.
Save kevinlynx/7248414 to your computer and use it in GitHub Desktop.
#include <assert.h>
#include <vector>
#include <map>
class DecisionStmt {
public:
enum { DECISION_RET = (unsigned) -1 };
typedef std::map<unsigned, int> CondResult;
typedef std::vector<CondResult> AccResults;
typedef std::vector<unsigned> CondList;
public:
void addCond(unsigned cond);
void enter();
void leave(bool truePart);
void coverCond(unsigned condId, bool ret);
float compute();
private:
AccResults m_rets;
CondList m_conds;
};
bool matchByConds(unsigned cond, const DecisionStmt::CondResult &r1, const DecisionStmt::CondResult &r2) {
auto it = r1.find(cond);
auto r2It = r2.find(cond);
if (it == r1.end() && r2It == r2.end()) return false; // both are not present
if (it == r1.end() && r2It->second == 0 ||
r2It == r2.end() && it->second == 0) return false; // both are equal 0
if (it->second == r2It->second) return false; // bother are equal 0/1
// now they are different
for (auto it = r1.begin(); it != r1.end(); ++it) {
if (it->first == cond) continue;
auto r2It = r2.find(it->first);
if (it->first == DecisionStmt::DECISION_RET) { // decision result
assert(r2It != r2.end());
if (it->second == r2It->second) return false; // result equal
} else { // condition result
if (r2It == r2.end()) return false; // condition result not present
if (r2It->second != it->second) return false; // not equal
}
}
return true;
}
float DecisionStmt::compute() {
assert(m_conds.size() > 0);
if (m_conds.size() == 1) return 1.f;
int match = 0;
bool found = false;
for (auto cit = m_conds.begin(); cit != m_conds.end(); ++cit) {
unsigned cid = *cit;
for (auto rit = m_rets.begin(); !found && rit != m_rets.end(); ++rit) {
auto &oneRet = *rit;
for (auto rit2 = rit + 1; !found && rit2 != m_rets.end(); ++rit2) {
if (matchByConds(cid, oneRet, *rit2)) {
found = true;
}
}
}
if (found) {
match ++;
found = false;
}
}
return 1.f * match / m_conds.size();
}
void DecisionStmt::enter() {
CondResult result;
m_rets.push_back(result);
}
void DecisionStmt::leave(bool truePart) {
assert(m_rets.size() > 0);
auto &result = m_rets.back();
result.insert(std::make_pair((unsigned)DECISION_RET, truePart ? 1 : 0));
}
void DecisionStmt::coverCond(unsigned condId, bool ret) {
assert(m_rets.size() > 0);
auto &result = m_rets.back();
assert(result.find(condId) == result.end());
result[condId] = ret ? 1 : 0;
}
void DecisionStmt::addCond(unsigned cond) {
m_conds.push_back(cond);
}
int main(int, char **) {
DecisionStmt stmt;
stmt.addCond(100);
stmt.addCond(101);
stmt.addCond(102);
stmt.addCond(103);
// 1 1 1 0 - 0
stmt.enter();
stmt.coverCond(100, true);
stmt.coverCond(101, true);
stmt.coverCond(102, true);
stmt.coverCond(103, false);
stmt.leave(false);
// 1 0 1 0 - 1
stmt.enter();
stmt.coverCond(100, true);
stmt.coverCond(101, false);
stmt.coverCond(102, true);
stmt.coverCond(103, false);
stmt.leave(true);
// 1 0 1 1 - 0
stmt.enter();
stmt.coverCond(100, true);
stmt.coverCond(101, false);
stmt.coverCond(102, true);
stmt.coverCond(103, true);
stmt.leave(false);
// 1 0 0 1 - 1
stmt.enter();
stmt.coverCond(100, true);
stmt.coverCond(101, false);
stmt.coverCond(102, false);
stmt.coverCond(103, true);
stmt.leave(true);
// 0 1 1 0 - 1
stmt.enter();
stmt.coverCond(100, false);
stmt.coverCond(101, true);
stmt.coverCond(102, true);
stmt.coverCond(103, false);
stmt.leave(true);
// 0 0 0 0 - 1
stmt.enter();
stmt.coverCond(100, false);
stmt.coverCond(101, false);
stmt.coverCond(102, false);
stmt.coverCond(103, false);
stmt.leave(true);
printf("%.2f\n", stmt.compute());
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment