prologの事実みたいなことをやりたいFact
prolog知らない人のために説明
例えば
(1,3,5),(2,4,6),(1,4,9)
みたいなのがあったとして
(1,?,?)
と聞くと
(3,5),(4,9)
と返してくれる。そんなのが欲しかったんだ
class Fact
{
public:
typedef boost::optional<T> Arg;
typedef std::vector<T> Result;
typedef std::vector<std::vector<T>> Results;
typedef boost::optional<Results> result_type;
template<class CONTAINER>
result_type operator()(const CONTAINER&container)const
{
return operator()(container.begin(),container.end());
}
template<class Iter>
result_type operator()(const Iter&begin,const Iter&end)const
{
std::set<size_t> pushs; //返り値になるもの
typedef std::map<size_t,Iter> Args;
Args args; //引数的なもの
size_t i=0;
for(auto it=begin;it!=end;++it,++i)
{
if(*it)
args.insert(Args::value_type(i,it));
else
pushs.insert(i);
}
const size_t len=std::distance(begin,end);
if(pushs.empty())
{
std::vector<T> temp;
for(auto it=begin;it!=end;++it)
temp.push_back(**it);
if(std::find(data.begin(),data.end(),temp)==data.end())
return result_type();
else
return Results();
}
Results result;
std::function<bool(const ELEM&)> check=[&](const ELEM&x)
{
return len==x.size()&&std::all_of(args.begin(),args.end(),[&](const Args::value_type&y)
{
return x.at(y.first) == *(y.second);
});
};
std::function<Result(const ELEM&)> Make=[&](const ELEM&x)
{
Result temp;
for(auto i:pushs)
temp.push_back(x.at(i));
return temp;
};
for(auto&x:data)
{
if(check(x))
result.push_back(Make(x));
}
if(result.empty())return result_type();
return result;
}
template<class CONTAINER>
void Set(const CONTAINER&container)
{
Set(container.begin(),container.end());
}
template<class Iter>
void Set(const Iter&begin,const Iter&end)
{
data.push_back(ELEM(begin,end));
}
private:
typedef std::vector<T> ELEM;
std::vector<ELEM> data;
};
//main
using boost::assign::list_of;
Fact<int> f;
typedef Fact<int>::Arg Arg;
f.Set(list_of(3)(1)(0)(1));//事実を入れている
f.Set(list_of(3)(2)(2)(3));
f.Set(list_of(3)(1)(9)(1));
auto r=f(list_of<Arg>(3)(1)()(3));//条件
output(r);//出力してます
出力
false
条件を(3)()()(1)にすると
true
1,0
1,9
となる