状态枚举类Enumerator源代码,欢迎拍砖!
初衷是解决智力题中的较复杂的推理题,比如:
有5个人参加某项比赛,但是参赛人员必须满足:
1、如果A参加,则B一定参加
2、C和D有且只有一人参加
3、D和E要么都参加,要么都不参加
4、如果C参加,则B一定不参加
5、最多有两个人参加
问满足条件的参赛人选。
我知道Prolog擅于解决此类问题,但是我擅用的语言是C++,所以就有了下面的代码。至于实用于否就不管了,权当是做了一个codekata,欢迎大家拍砖!
我的空间里也有
我用的是VS2012,我必须要undef max才能使用std::limits<>::max()函数,很上火!
#pragma once
#include<limits>
#include<vector>
#include<string>
#include<boost/lexical_cast.hpp>
#undef max
template<unsigned int BASE, class TYPE=unsigned>
class Enumerator
{
static_assert(BASE > 2, "template parameter should greater than 2!");
public:
//typedef unsigned int TYPE;
Enumerator(unsigned int count, TYPE stat = 0)
{
status.clear();
status.resize(count, stat);
}
bool operator ++()
{
int c = 1;
for (size_t i = 0 ; c != 0 && i < status.size() ; ++i)
{
status[i] += c;
if(status[i] >= BASE)
{
status[i] = 0;
c = 1;
}
else
{//不需要再继续进位
c = 0;
}
}
return c == 0;
}
bool operator++(int)
{
return this->operator++();
}
TYPE get(size_t i) const
{
if(i >= status.size())
throw std::out_of_range(std::string("i should less than ")
+ lexical_cast<string>(status.size()));
return status[i];
}
void set(size_t i, TYPE s)
{
if(i >= status.size())
throw std::out_of_range(string("i should less than ")
+ lexical_cast<string>(status.size()));
status[i] = s;
}
size_t count(TYPE s) const
{
size_t result = 0;
for (const auto& p : status)
{
if(p == s) result++;
}
return result;
}
size_t size() const
{
return status.size();
}
protected:
private:
std::vector<TYPE> status;
};
template<class T>
class Enumerator<2, T>
{
//只要是这种2状态的东西,直接采用unsigned类型,忽略类型参数T
typedef unsigned int TYPE;
public:
Enumerator(unsigned int count, bool statu = 0)
:SIZE(count)
{
status.clear();
status.resize(SIZE / BITS + 1, statu ? std::numeric_limits<TYPE>::max() : 0);
}
bool operator++()
{
static const auto MAX = std::numeric_limits<TYPE>::max();
int c = 1;
for (size_t i = 0 ; c != 0 && i < status.size() ; ++i)
{
if(status[i] == MAX)
{
status[i] = 0;
c = 1;
}
else
{
status[i]+=c;
c = 0;
}
}
return c == 0 && (status.back() >> (SIZE % BITS)) == 0;
}
bool operator++(int)
{
return operator++();
}
short get(size_t i) const
{
if(i >= SIZE) throw std::out_of_range(std::string("i should less than ") + boost::lexical_cast<std::string>(SIZE));
return (status[i / BITS] >> (i % BITS)) & 1;
}
void set(size_t i , bool s)
{
if(s)
status[i / BITS] |= 1 << (i % BITS);
else
status[i / BITS] &= ~(1 <<( i % BITS));
}
size_t count(bool s) const
{
unsigned result = 0;
for (auto p : status)
{
while(p)
{
result += p & 1;
p >>= 1;
}
}
return s ? result : SIZE - result;
}
size_t size() const
{
return SIZE;
}
protected:
private:
static const auto BITS = std::numeric_limits<TYPE>::digits;
const size_t SIZE;
std::vector<TYPE> status;
};
#include<cstdio>
using namespace std;
int pow(int a)
{
if(a==0)return 1;
else return 2*pow(a-1);
}
void HaveFun()
{
for(int i=0;i<=pow(6)-1;i++)
if(i&0x10?(i&0x8?1:0):1)
if(i&0x4
[解决办法]
i&0x2)
if(i&0x2 && i&0x1
[解决办法]
!(i&0x2 && i&0x1)){
int amount=2;
for(int offset=0;offset<=4;offset++)
if(i&1<<offset)amount--;
if(amount>=0)printf("%d\n",i);
}
}
int main()
{
HaveFun();
getchar();
return 0;
}
#define NO_MINMAX