本人编写的一个计算24的有趣小程序,可以计算任意多个参数情况下计算任意目标值,如:用{1,7,8,9,10,11,12,13}来计算目标值7,结果是:11 - (1 + 7 + 8 + 9 + 10 + 13) / 12 = 7,计算方法的总入口为calcTarget函数,所以使用该源代码时,需要自己写main函数调用。
程序功能非常强大,以目前我所知道的网络上各种算法来看,本算法是最好的,核心代码其实不多,大多数代码是为了处理细节,比如括号的处理,以最精练的方式处理括号,试试看吧,一定会让你满意。
本人编写的一个计算24的有趣小程序,可以计算任意多个参数情况下计算任意目标值,如:用{1,7,8,9,10,11,12,13}来计算目标值7,结果是:11 - (1 + 7 + 8 + 9 + 10 + 13) / 12 = 7,计算方法的总入口为calcTarget函数,所以使用该源代码时,需要自己写main函数调用。
程序功能非常强大,以目前我所知道的网络上各种算法来看,本算法是最好的,核心代码其实不多,大多数代码是为了处理细节,比如括号的处理,以最精练的方式处理括号,试试看吧,一定会让你满意。
调用举例
#include "calc24.h"
int main(int argc, char* argv[])
{
cout << calcTarget(24,{2,3,4,5}) << endl;
}
代码如下(示例):
c24int.h
#pragma once
#include <string>
using namespace std;
class c24int{
int a_;
int b_;
public:
c24int() :a_(0), b_(1){}
c24int(int _a) :a_(_a), b_(1){}
c24int(int _a, int _b) :a_(_a), b_(_b){}
public:
int a() const{ return a_; }
int b() const{ return b_; }
public:
void reduce(){ if(b_ == 0 || b_ == 1)return; int t = a_ / b_; if(a_ == t * b_){ a_ = t; b_ = 1; } }
bool same(int _v) const{ return a_ == _v && b_ == 1; }
bool great(int _v) const{ return a_ > _v && b_ == 1; }
bool great_same(int _v) const{ return a_ >= _v && b_ == 1; }
bool less(int _v) const{ return a_ < _v&& b_ == 1; }
bool less_same(int _v) const{ return a_ <= _v && b_ == 1; }
bool same(const c24int& _v) const{ return a_ * _v.b_ == b_ * _v.a_; }
bool great(const c24int& _v) const{ return a_ * _v.b_ > b_ * _v.a_; }
bool great_same(const c24int& _v) const{ return a_ * _v.b_ >= b_ * _v.a_; }
bool less(const c24int& _v) const{ return a_ * _v.b_ < b_* _v.a_; }
bool less_same(const c24int& _v) const{ return a_ * _v.b_ <= b_ * _v.a_; }
double dou() const{ return double(a_) / double(b_); }
string str() const{ if(b_ == 1)return to_string(a_); return "{" + to_string(a_) + "/" + to_string(b_) + "}"; }
public:
c24int& operator=(int _v){ a_ = _v, b_ = 1; return *this; }
c24int& operator=(const c24int& _v){ a_ = _v.a_; b_ = _v.b_; return *this; }
c24int& operator+=(int _v){ a_ += b_ * _v; return *this; }
c24int& operator+=(const c24int& _v){
int t_a = a_ * _v.b_ + b_ * _v.a_;
b_ = b_ * _v.b_;
a_ = t_a;
reduce();
return *this;
}
c24int& operator-=(int _v){ a_ -= b_ * _v; return *this; }
c24int& operator-=(const c24int& _v){
int t_a = a_ * _v.b_ - b_ * _v.a_;
b_ = b_ * _v.b_;
a_ = t_a;
reduce();
return *this;
}
c24int& operator*=(int _v){ a_ *= _v; reduce(); return *this; }
c24int& operator*=(const c24int& _v){
int t_a = a_ * _v.a_;
b_ = b_ * _v.b_;
a_ = t_a;
reduce();
return *this;
}
c24int& operator/=(int _v){ b_ *= _v; reduce(); return *this; }
c24int& operator/=(const c24int& _v){
int t_a = a_ * _v.b_;
b_ = b_ * _v.a_;
a_ = t_a;
reduce();
return *this;
}
};
inline bool operator==(const c24int& _x, int _y){ return _x.same(_y); }
inline bool operator==(int _x, const c24int& _y){ return _y.same(_x); }
inline bool operator==(const c24int& _x, const c24int& _y){ return _x.same(_y); }
inline bool operator!=(const c24int& _x, int _y){ return !_x.same(_y); }
inline bool operator!=(int _x, const c24int& _y){ return !_y.same(_x); }
inline bool operator!=(const c24int& _x, const c24int& _y){ return !_x.same(_y); }
inline bool operator>(const c24int& _x, int _y){ return _x.great(_y); }
inline bool operator>(int _x, const c24int& _y){ return !_y.less_same(_x); }
inline bool operator>(const c24int& _x, const c24int& _y){ return _x.great(_y); }
inline bool operator>=(const c24int& _x, int _y){ return _x.great_same(_y); }
inline bool operator>=(int _x, const c24int& _y){ return !_y.less(_x); }
inline bool operator>=(const c24int& _x, const c24int& _y){ return !_y.great_same(_x); }
inline bool operator<(const c24int& _x, int _y){ return _x.less(_y); }
inline bool operator<(int _x, const c24int& _y){ return !_y.great_same(_x); }
inline bool operator<(const c24int& _x, const c24int& _y){ return _x.less(_y); }
inline bool operator<=(const c24int& _x, int _y){ return _x.less_same(_y); }
inline bool operator<=(int _x, const c24int& _y){ return !_y.great(_x); }
inline bool operator<=(const c24int& _x, const c24int& _y){ return !_y.less_same(_x); }
inline c24int operator+(const c24int& _x, int _y){ c24int ret = _x; ret += _y; return ret; }
inline c24int operator+(int _x, const c24int& _y){ c24int ret(_x); ret += _y; return ret; }
inline c24int operator+(const c24int& _x, const c24int& _y){ c24int ret = _x; ret += _y; return ret; }
inline c24int operator-(const c24int& _x, int _y){ c24int ret = _x; ret -= _y; return ret; }
inline c24int operator-(int _x, const c24int& _y){ c24int ret(_x); ret -= _y; return ret; }
inline c24int operator-(const c24int& _x, const c24int& _y){ c24int ret = _x; ret -= _y; return ret; }
inline c24int operator*(const c24int& _x, int _y){ c24int ret = _x; ret *= _y; return ret; }
inline c24int operator*(int _x, const c24int& _y){ c24int ret(_x); ret *= _y; return ret; }
inline c24int operator*(const c24int& _x, const c24int& _y){ c24int ret = _x; ret *= _y; return ret; }
inline c24int operator/(const c24int& _x, int _y){ c24int ret = _x; ret /= _y; return ret; }
inline c24int operator/(int _x, const c24int& _y){ c24int ret(_x); ret /= _y; return ret; }
inline c24int operator/(const c24int& _x, const c24int& _y){ c24int ret = _x; ret /= _y; return ret; }
calc24.h
```cpp
#pragma once
#include "c24int.h"
#include <vector>
#include <iostream>
#include <functional>
#include <set>
using namespace std;
#define OP_ADD 1
#define OP_DEC 2
#define OP_MUL 3
#define OP_DIV 4
#define OP_LEFT true
#define OP_RIGHT false
using result_proc = function<bool(const string& _result)>;
//6, 8, 10, 13, 1, 1, 6, 13, 12, 13
using result_proc = function<bool(const string& _result)>;
bool isSame(double a, double b);
struct c24dat{
bool isNull_ = true;
bool isExp_ = false;
char op_ = 0;
c24int val_ = 0;
string exp_ = "";
public:
bool isNull() const{ return isNull_; }
c24dat() = default;
c24dat(int _val) :isNull_(false), val_(_val), exp_(val_.str()){}
c24dat(const c24int& _val) :isNull_(false), val_(_val), exp_(val_.str()){}
c24dat clone() const{ return *this; }
string qexp(char _op, bool _left = true) const;
c24dat& operator=(int _val){ val_ = _val; isNull_ = false; return *this; }
string toString() const{
if(isNull())return "null";
return exp_ + " = " + val_.str();
}
};
c24dat operator+(const c24dat& _dat, const c24int& _val);
c24dat operator-(const c24dat& _dat, const c24int& _val);
c24dat operator*(const c24dat& _dat, const c24int& _val);
c24dat operator/(const c24dat& _dat, const c24int& _val);
//
c24dat operator+(const c24int& _val, const c24dat& _dat);
c24dat operator-(const c24int& _val, const c24dat& _dat);
c24dat operator*(const c24int& _val, const c24dat& _dat);
c24dat operator/(const c24int& _val, const c24dat& _dat);
//
c24dat operator+(const c24dat& _val, const c24dat& _dat);
c24dat operator-(const c24dat& _val, const c24dat& _dat);
c24dat operator*(const c24dat& _val, const c24dat& _dat);
c24dat operator/(const c24dat& _val, const c24dat& _dat);
struct c24dats : public vector<c24int>{
public:
using vector::vector;
public:
string toString() const{
string ret;
for(auto& r : *this){
if(ret.size() == 0)ret.append(r.str());
else ret.append(", ").append(r.str());
}
return ret;
}
c24dats& delIdx(size_t _idx){
erase(begin() + _idx);
return *this;
}
c24dats clone() const{ return *this; }
};
class calc24{
public:
c24int target_;
result_proc resultproc_;
c24dat result_;
public:
calc24(const c24int& _target) :target_(_target){}
bool getResult(const c24dat& _result){result_ = _result;return true;}
public:
bool calc(const c24dat& _parent, const c24dats& _dats);
};
string calcTarget(const c24int& _target, const c24dats& _dats);
calc24.cpp
#include "calc24.h"
#include <set>
bool isSame(double a, double b)
{
double r = a - b;
if(r < 0)r = b - a;
return r < 0.000000001;
}
string c24dat::qexp(char _op, bool _left) const{
if(isNull() || exp_ == "" || !isExp_)return exp_;
if(_op == OP_ADD) return exp_;
if(_op == OP_DEC){
if(_left || op_ == OP_MUL || op_ == OP_DIV)return exp_;
else return "(" + exp_ + ")";
}
if(_op == OP_MUL){
if(op_ == OP_MUL || op_ == OP_DIV)return exp_;
else return "(" + exp_ + ")";
} else{
if(!_left)return "(" + exp_ + ")";
if(op_ == OP_MUL || op_ == OP_DIV)return exp_;
return "(" + exp_ + ")";
}
return "(" + exp_ + ")";
}
c24dat operator+(const c24dat& _dat, const c24int& _val){
c24dat ret = _dat;
ret.val_ += _val;
ret.exp_ = ret.qexp(OP_ADD, OP_LEFT) + " + " + _val.str();
ret.op_ = OP_ADD;
ret.isExp_ = true;
return ret;
}
c24dat operator-(const c24dat& _dat, const c24int& _val){
c24dat ret = _dat;
ret.val_ -= _val;
ret.exp_ = ret.qexp(OP_DEC, OP_LEFT) + " - " + _val.str();
ret.op_ = OP_DEC;
ret.isExp_ = true;
return ret;
}
c24dat operator*(const c24dat& _dat, const c24int& _val){
c24dat ret = _dat;
ret.val_ *= _val;
ret.exp_ = ret.qexp(OP_MUL, OP_LEFT) + " * " + _val.str();
ret.op_ = OP_MUL;
ret.isExp_ = true;
return ret;
}
c24dat operator/(const c24dat& _dat, const c24int& _val){
c24dat ret = _dat;
ret.val_ /= _val;
ret.exp_ = ret.qexp(OP_DIV, OP_LEFT) + " / " + _val.str();
ret.op_ = OP_DIV;
ret.isExp_ = true;
return ret;
}
//
c24dat operator+(const c24int& _val, const c24dat& _dat){
c24dat ret(_val);
ret.val_ += _dat.val_;
ret.exp_ = ret.qexp(OP_ADD, OP_LEFT) + " + " + _dat.qexp(OP_ADD, OP_RIGHT);
ret.op_ = OP_ADD;
ret.isExp_ = true;
return ret;
}
c24dat operator-(const c24int& _val, const c24dat& _dat){
c24dat ret(_val);
ret.val_ -= _dat.val_;
ret.exp_ = ret.qexp(OP_DEC, OP_LEFT) + " - " + _dat.qexp(OP_DEC, OP_RIGHT);
ret.op_ = OP_DEC;
ret.isExp_ = true;
return ret;
}
c24dat operator*(const c24int& _val, const c24dat& _dat){
c24dat ret(_val);
ret.val_ *= _dat.val_;
ret.exp_ = ret.qexp(OP_MUL, OP_LEFT) + " * " + _dat.qexp(OP_MUL, OP_RIGHT);
ret.op_ = OP_MUL;
ret.isExp_ = true;
return ret;
}
c24dat operator/(const c24int& _val, const c24dat& _dat){
c24dat ret(_val);
ret.val_ /= _dat.val_;
ret.exp_ = ret.qexp(OP_DIV, OP_LEFT) + " / " + _dat.qexp(OP_DIV, OP_RIGHT);
ret.op_ = OP_DIV;
ret.isExp_ = true;
return ret;
}
//
c24dat operator+(const c24dat& _val, const c24dat& _dat){
c24dat ret = _val;
ret.val_ += _dat.val_;
ret.exp_ = ret.qexp(OP_ADD, OP_LEFT) + " + " + _dat.qexp(OP_ADD, OP_RIGHT);
ret.op_ = OP_ADD;
ret.isExp_ = true;
return ret;
}
c24dat operator-(const c24dat& _val, const c24dat& _dat){
c24dat ret = _val;
ret.val_ -= _dat.val_;
ret.exp_ = ret.qexp(OP_DEC, OP_LEFT) + " - " + _dat.qexp(OP_DEC, OP_RIGHT);
ret.op_ = OP_DEC;
ret.isExp_ = true;
return ret;
}
c24dat operator*(const c24dat& _val, const c24dat& _dat){
c24dat ret(_val);
ret.val_ *= _dat.val_;
ret.exp_ = ret.qexp(OP_MUL, OP_LEFT) + " * " + _dat.qexp(OP_MUL, OP_RIGHT);
ret.op_ = OP_MUL;
ret.isExp_ = true;
return ret;
}
c24dat operator/(const c24dat& _val, const c24dat& _dat){
c24dat ret(_val);
ret.val_ /= _dat.val_;
ret.exp_ = ret.qexp(OP_DIV, OP_LEFT) + " / " + _dat.qexp(OP_DIV, OP_RIGHT);
ret.op_ = OP_DIV;
ret.isExp_ = true;
return ret;
}
bool calc24::calc(const c24dat& _parent, const c24dats& _dats){
if(_dats.size() == 1){
if(_parent.isNull()){
if(_dats[0] == target_)return getResult(_dats[0]);
return false;
}
if(_parent.val_ + _dats[0] == target_)return getResult(_parent + _dats[0]);
if(_parent.val_ - _dats[0] == target_)return getResult(_parent - _dats[0]);
if(_dats[0] - _parent.val_ == target_)return getResult(_dats[0] - _parent);
if(_parent.val_ * _dats[0] == target_)return getResult(_parent * _dats[0]);
if(_dats[0] != 0 && _parent.val_ / _dats[0] == target_)return getResult(_parent / _dats[0]);
if(_parent.val_ != 0 && _dats[0] / _parent.val_ == target_)return getResult(_dats[0] / _parent);
return false;
}
//有两个及以上数据
set<c24int> calced;
if(_parent.isNull()){
for(size_t i = 0; i < _dats.size(); i++){
c24int t = _dats[i];
if(calced.find(t)!=calced.end())continue;
if(calc(c24dat{ t }, _dats.clone().delIdx(i)))return true;
calced.insert(t);
}
return false;
}
calced.clear();
for(size_t i = 0; i < _dats.size(); i++){
c24int t = _dats[i];
if(calced.find(t) != calced.end())continue;
c24dats tmp = _dats.clone().delIdx(i);
if(calc(_parent + t, tmp))return true;
if(calc(_parent - t, tmp))return true;
if(calc(_dats[i] - _parent, tmp))return true;
if(calc(_parent * t, tmp))return true;
if(t != 0 && calc(_parent / t, tmp))return true;
if(_parent.val_ != 0 && calc(t / _parent, tmp))return true;
calced.insert(t);
}
calced.clear();
// a+x=t => x=t-a
calc24 x_add(target_ - _parent.val_);
if(x_add.calc(c24dat(), _dats))return getResult(_parent + x_add.result_);
// a-x=t => x=a-t
calc24 x_dec(_parent.val_ - target_);
if(x_dec.calc(c24dat(), _dats))return getResult(_parent - x_dec.result_);
// x-a=t => x=a+t
calc24 x_dec2(_parent.val_ + target_);
if(x_dec2.calc(c24dat(), _dats))return getResult(x_dec2.result_ - _parent);
// a*x=t => x=t/a
calc24 x_mult(target_ / _parent.val_);
if(x_mult.calc(c24dat(), _dats))return getResult(_parent * x_mult.result_);
// a/x=t => x=a/t
if(target_ != 0){
calc24 x_div(_parent.val_ / target_);
if(x_div.calc(c24dat(), _dats) && x_div.result_.val_ != 0)return getResult(_parent / x_div.result_);
}
// x/a=t => x=a*t
if(_parent.val_ != 0){
calc24 x_div2(_parent.val_ * target_);
if(x_div2.calc(c24dat(), _dats))return getResult(x_div2.result_ / _parent);
}
return false;
}
//得到以_dats为参数(可以任意多个整数),以_target为目标值的计算方案
string calcTarget(const c24int& _target/*目标值*/, const c24dats& _dats/*计算参数*/){
calc24 calc(_target);
if(calc.calc(c24dat(), _dats)){
//cout << calc.result_.toString() << endl;
return calc.result_.toString();
} else{
//cout << " no solution " << endl;
string ret = "no solution for: { " + _dats[0].str();
for(int i=1;i<_dats.size();i++){
ret.append(", ").append(_dats[i].str());
}
ret.append(" } = ").append(_target.str());
return ret;
}
}