#include
#include
#include
#include
#include
//基本操作符枚举
enum class Operator {
NONE,
ADD,
DEC,
MUL,
SUB
};
//重载输出基本操作符运算符
std::ostream & operator << (std::ostream & out, const enum class Operator op) {
switch (op) {
case Operator::ADD:
out << "+"; break;
case Operator::DEC:
out << "-"; break;
case Operator::MUL:
out << "*"; break;
case Operator::SUB:
out << "/"; break;
}
return out;
}
//结果节点
struct ResultNode {
ResultNode(int val) :result(val) {}
int result;
Operator calc_operator{ Operator::NONE };
const ResultNode * left{ nullptr };
const ResultNode * right{ nullptr };
ResultNode(const ResultNode &rh) {
result = rh.result;
calc_operator = rh.calc_operator;
left = rh.left;
right = rh.right;
}
ResultNode & operator = (const ResultNode& rh) {
result = rh.result;
calc_operator = rh.calc_operator;
left = rh.left;
right = rh.right;
return *this;
}
bool operator < (const ResultNode &rh) const
{
return result < rh.result;
}
bool isSingle() const{
return left == nullptr && right == nullptr;
}
};
//打印出一棵节点树
void PrintResult(std::ostream &out, const ResultNode & result){
if (result.left == nullptr) {
out << result.result;
return;
}
if (!result.left->isSingle())out << "(";
PrintResult(out, *result.left);
if (!result.left->isSingle())out << ")";
out << result.calc_operator;
if (!result.right->isSingle())out << "(";
PrintResult(out, *result.right);
if (!result.right->isSingle())out << ")";
}
//组合类实现,实现从一个结果集中取出N个的可能性 C(S,N)
template
class combination {
public:
explicit combination(const std::vector &val) : value(val) {
//std::sort(value.begin(), value.end());
auto size = value.size();//std::unique(value.begin(), value.end()) - value.begin();
bitsets.assign(size, 0);
if (size >= N) {
for (int i = 0; i < N; ++i) {
bitsets[i] = 1;
}
initflag = true;
}
}
void get_value(std::vector & in, std::vector & other){
for (auto i = 0; i < bitsets.size(); ++i) {
if (bitsets[i] == 1) {
in.push_back(value[i]);
}
else {
other.push_back(value[i]);
}
}
for (auto v = value.begin() + bitsets.size(); v != value.end(); ++v) {
other.push_back(*v);
}
}
//取出下一个可能的结果,如果没有结果了就返回false
bool next(std::vector & out, std::vector & other){
if (bitsets.size() < N) {
return false;
}
if (initflag) {
get_value(out, other);
initflag = false;
}
else {
auto f = std::prev_permutation(bitsets.begin(), bitsets.end());
if (f) get_value(out, other);
return f;
}
return true;
}
bool initflag;
std::vector bitsets;
std::vector value;
};
//最终结果集
std::set<:string> ResultSet;
//计算主要递归函数
int CalcEx(const std::vector &set, const int result){
if (set.size() == 1) {
if (result == set[0].result) {
std::stringstream ss;
PrintResult(ss, set[0]);
//std::cout << std::endl;
ResultSet.insert(ss.str());//这里可以有效避免重复
}
return 0;
}
combination source{ set };
std::vector next, other;
//不断的从结果集中取组合,然后组合成新的结果集,再次调用递归
while (source.next(next, other)) {
//ADD
{
auto _next = next;
auto _other = other;
ResultNode r(_next[0].result + _next[1].result);
r.left = &_next[0];
r.right = &_next[1];
r.calc_operator = Operator::ADD;
_other.push_back(r);
CalcEx(_other, result);
}
//DEC first-second
{
auto _next = next;
auto _other = other;
ResultNode r(_next[0].result - _next[1].result);
r.left = &_next[0];
r.right = &_next[1];
r.calc_operator = Operator::DEC;
_other.push_back(r);
CalcEx(_other, result);
}
//DEC second-first
{
auto _next = next;
auto _other = other;
ResultNode r(_next[1].result - _next[0].result);
r.left = &_next[1];
r.right = &_next[0];
r.calc_operator = Operator::DEC;
_other.push_back(r);
CalcEx(_other, result);
}
//MUL
{
auto _next = next;
auto _other = other;
ResultNode r(_next[0].result * _next[1].result);
r.left = &_next[0];
r.right = &_next[1];
r.calc_operator = Operator::MUL;
_other.push_back(r);
CalcEx(_other, result);
}
//SUB first/second
{
auto _next = next;
auto _other = other;
if (_next[1].result == 0 || (_next[0].result % _next[1].result) != 0)
goto NEXTSUB;
ResultNode r(_next[0].result / _next[1].result);
r.left = &_next[0];
r.right = &_next[1];
r.calc_operator = Operator::SUB;
_other.push_back(r);
CalcEx(_other, result);
}
NEXTSUB:
//SUB second/first
{
auto _next = next;
auto _other = other;
if (_next[0].result == 0 || (_next[1].result % _next[0].result) != 0)
goto CONTINUE;
ResultNode r(_next[1].result / _next[0].result);
r.left = &_next[1];
r.right = &_next[0];
r.calc_operator = Operator::SUB;
_other.push_back(r);
CalcEx(_other, result);
}
CONTINUE:
next.clear();
other.clear();
continue;
}
return 0;
}
TEST(Game24Test, TowValue) {
//计算2个值的情况
{
std::vector v;
v.push_back(12); v.push_back(12);
CalcEx(v, 24);
//输出 12+12
for (auto & result : ResultSet) {
std::cout << result << std::endl;
}
}
}
TEST(Game24Test, Unsolvable) {
ResultSet.clear();
//计算无解的情况
{
std::vector v;
v.push_back(3); v.push_back(2); v.push_back(3); v.push_back(4);
CalcEx(v, 24);
//无输出
for (auto & result : ResultSet) {
std::cout << result << std::endl;
}
}
}
int main(){
std::vector v;
v.push_back(3); v.push_back(3); v.push_back(6); v.push_back(6);
CalcEx(v, 24);
//无输出
for (auto & result : ResultSet) {
std::cout << result << std::endl;
}
return 0;
}