Finite function moved to another file
This commit is contained in:
164
finite_function.hpp
Normal file
164
finite_function.hpp
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
typedef int8_t CellType;
|
||||||
|
|
||||||
|
// Пока положим, что только два аргумента, чтобы упростить реализацию
|
||||||
|
template <CellType BASE>
|
||||||
|
class FiniteFunction {
|
||||||
|
public:
|
||||||
|
FiniteFunction() {}
|
||||||
|
|
||||||
|
// Устанавливает результат функции, использую другую функцию как
|
||||||
|
// инициализатор
|
||||||
|
template <class Callable>
|
||||||
|
FiniteFunction(Callable initer) : _num(0) {
|
||||||
|
for (CellType first = 0; first < BASE; ++first)
|
||||||
|
for (CellType second = 0; second < BASE; ++second) {
|
||||||
|
auto inited_result = initer(first, second);
|
||||||
|
set_result(first, second, inited_result);
|
||||||
|
}
|
||||||
|
update_num();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit FiniteFunction(std::string text_repr) {
|
||||||
|
size_t cur_ind = 0;
|
||||||
|
for (auto ch: text_repr) {
|
||||||
|
if ( !isdigit(ch) )
|
||||||
|
continue;
|
||||||
|
_results.at(cur_ind) = std::stoi(std::string(1, ch));
|
||||||
|
++cur_ind;
|
||||||
|
}
|
||||||
|
update_num();
|
||||||
|
}
|
||||||
|
~FiniteFunction() {}
|
||||||
|
|
||||||
|
// Устанавливает результат функции по двум аргументам
|
||||||
|
void set_result(CellType first, CellType second, CellType result) {
|
||||||
|
_results[get_index(first, second)] = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int operator() (CellType first, CellType second) const {
|
||||||
|
return _results[get_index(first, second)];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator < (const FiniteFunction &f) const {
|
||||||
|
return _num < f._num;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator == (const FiniteFunction &f) const {
|
||||||
|
return _num == f._num;
|
||||||
|
}
|
||||||
|
|
||||||
|
FiniteFunction reversed() const {
|
||||||
|
// f(x,y) -> f(y,x)
|
||||||
|
FiniteFunction res;
|
||||||
|
for (CellType first = 0; first < BASE; ++first)
|
||||||
|
for (CellType second = 0; second < BASE; ++second) {
|
||||||
|
res.set_result(first, second, (*this)(second, first));
|
||||||
|
}
|
||||||
|
res.update_num();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
FiniteFunction equaled() const {
|
||||||
|
// f(x,y) -> f(x,x)
|
||||||
|
FiniteFunction res;
|
||||||
|
for (CellType first = 0; first < BASE; ++first)
|
||||||
|
for (CellType second = 0; second < BASE; ++second) {
|
||||||
|
res.set_result(first, second, (*this)(first, first));
|
||||||
|
}
|
||||||
|
res.update_num();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
FiniteFunction apply_to_first_partial(const FiniteFunction &g) const {
|
||||||
|
// -> this(g(x,y), x)
|
||||||
|
FiniteFunction res;
|
||||||
|
for (CellType first = 0; first < BASE; ++first)
|
||||||
|
for (CellType second = 0; second < BASE; ++second) {
|
||||||
|
res.set_result(first, second, (*this)(g(first, second), first));
|
||||||
|
}
|
||||||
|
res.update_num();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<FiniteFunction, FiniteFunction> apply_to_first(const FiniteFunction &g) const {
|
||||||
|
// -> this(g(x,y), x), this(g(x,y), y)
|
||||||
|
FiniteFunction res_1, res_2;
|
||||||
|
for (CellType first = 0; first < BASE; ++first)
|
||||||
|
for (CellType second = 0; second < BASE; ++second) {
|
||||||
|
res_1.set_result(first, second, (*this)(g(first, second), first));
|
||||||
|
res_2.set_result(first, second, (*this)(g(first, second), second));
|
||||||
|
}
|
||||||
|
res_1.update_num();
|
||||||
|
res_2.update_num();
|
||||||
|
return std::make_tuple(res_1, res_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
FiniteFunction apply_two(const FiniteFunction &g, const FiniteFunction &h) const {
|
||||||
|
FiniteFunction res;
|
||||||
|
for (CellType first = 0; first < BASE; ++first)
|
||||||
|
for (CellType second = 0; second < BASE; ++second) {
|
||||||
|
res.set_result(
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
(*this)(g(first, second), h(first, second))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
res.update_num();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
FiniteFunction apply_permutation(std::array<int, BASE> perm) const {
|
||||||
|
FiniteFunction res;
|
||||||
|
for (CellType first = 0; first < BASE; ++first)
|
||||||
|
for (CellType second = 0; second < BASE; ++second) {
|
||||||
|
res.set_result(
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
std::find(
|
||||||
|
perm.begin(),
|
||||||
|
perm.end(),
|
||||||
|
(*this)(perm[first], perm[second])
|
||||||
|
) - perm.begin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
res.update_num();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_hash() const {
|
||||||
|
return _num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t get_index(CellType first, CellType second) {
|
||||||
|
return first * BASE + second;
|
||||||
|
}
|
||||||
|
template <CellType _BASE>
|
||||||
|
friend std::ostream& operator << (std::ostream& os, const FiniteFunction<_BASE> &f);
|
||||||
|
private:
|
||||||
|
void update_num() {
|
||||||
|
_num = 0;
|
||||||
|
for (auto&& val: _results) {
|
||||||
|
_num *= BASE;
|
||||||
|
_num += val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t _num;
|
||||||
|
std::array<CellType, BASE*BASE> _results;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <CellType BASE>
|
||||||
|
std::ostream& operator << (std::ostream& os, const FiniteFunction<BASE> &f){
|
||||||
|
for (int first = 0; first < BASE; ++first) {
|
||||||
|
for (int second = 0; second < BASE; ++second) {
|
||||||
|
os << f(first, second);
|
||||||
|
}
|
||||||
|
if ( first != BASE-1 )
|
||||||
|
os << " ";
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
165
main.cpp
165
main.cpp
@@ -12,171 +12,16 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
|
|
||||||
|
#include "finite_function.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
typedef int8_t CellType;
|
|
||||||
|
|
||||||
const CellType CUR_BASE = 3;
|
const CellType CUR_BASE = 3;
|
||||||
const int ARGS_COUNT = 2;
|
const int ARGS_COUNT = 2;
|
||||||
|
|
||||||
// Пока положим, что только два аргумента, чтобы упростить реализацию
|
|
||||||
template <CellType BASE>
|
|
||||||
class FiniteFunction {
|
|
||||||
public:
|
|
||||||
FiniteFunction() {}
|
|
||||||
|
|
||||||
// Устанавливает результат функции, использую другую функцию как
|
|
||||||
// инициализатор
|
|
||||||
template <class Callable>
|
|
||||||
FiniteFunction(Callable initer) : _num(0) {
|
|
||||||
for (CellType first = 0; first < BASE; ++first)
|
|
||||||
for (CellType second = 0; second < BASE; ++second) {
|
|
||||||
auto inited_result = initer(first, second);
|
|
||||||
set_result(first, second, inited_result);
|
|
||||||
}
|
|
||||||
update_num();
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit FiniteFunction(string text_repr) {
|
|
||||||
size_t cur_ind = 0;
|
|
||||||
for (auto ch: text_repr) {
|
|
||||||
if ( !isdigit(ch) )
|
|
||||||
continue;
|
|
||||||
_results.at(cur_ind) = stoi(string(1, ch));
|
|
||||||
++cur_ind;
|
|
||||||
}
|
|
||||||
update_num();
|
|
||||||
}
|
|
||||||
~FiniteFunction() {}
|
|
||||||
|
|
||||||
// Устанавливает результат функции по двум аргументам
|
|
||||||
void set_result(CellType first, CellType second, CellType result) {
|
|
||||||
_results[get_index(first, second)] = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int operator() (CellType first, CellType second) const {
|
|
||||||
return _results[get_index(first, second)];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator < (const FiniteFunction &f) const {
|
|
||||||
return _num < f._num;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator == (const FiniteFunction &f) const {
|
|
||||||
return _num == f._num;
|
|
||||||
}
|
|
||||||
|
|
||||||
FiniteFunction reversed() const {
|
|
||||||
// f(x,y) -> f(y,x)
|
|
||||||
FiniteFunction res;
|
|
||||||
for (CellType first = 0; first < BASE; ++first)
|
|
||||||
for (CellType second = 0; second < BASE; ++second) {
|
|
||||||
res.set_result(first, second, (*this)(second, first));
|
|
||||||
}
|
|
||||||
res.update_num();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
FiniteFunction equaled() const {
|
|
||||||
// f(x,y) -> f(x,x)
|
|
||||||
FiniteFunction res;
|
|
||||||
for (CellType first = 0; first < BASE; ++first)
|
|
||||||
for (CellType second = 0; second < BASE; ++second) {
|
|
||||||
res.set_result(first, second, (*this)(first, first));
|
|
||||||
}
|
|
||||||
res.update_num();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
FiniteFunction apply_to_first_partial(const FiniteFunction &g) const {
|
|
||||||
// -> this(g(x,y), x)
|
|
||||||
FiniteFunction res;
|
|
||||||
for (CellType first = 0; first < BASE; ++first)
|
|
||||||
for (CellType second = 0; second < BASE; ++second) {
|
|
||||||
res.set_result(first, second, (*this)(g(first, second), first));
|
|
||||||
}
|
|
||||||
res.update_num();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
tuple<FiniteFunction, FiniteFunction> apply_to_first(const FiniteFunction &g) const {
|
|
||||||
// -> this(g(x,y), x), this(g(x,y), y)
|
|
||||||
FiniteFunction res_1, res_2;
|
|
||||||
for (CellType first = 0; first < BASE; ++first)
|
|
||||||
for (CellType second = 0; second < BASE; ++second) {
|
|
||||||
res_1.set_result(first, second, (*this)(g(first, second), first));
|
|
||||||
res_2.set_result(first, second, (*this)(g(first, second), second));
|
|
||||||
}
|
|
||||||
res_1.update_num();
|
|
||||||
res_2.update_num();
|
|
||||||
return make_tuple(res_1, res_2);
|
|
||||||
}
|
|
||||||
|
|
||||||
FiniteFunction apply_two(const FiniteFunction &g, const FiniteFunction &h) const {
|
|
||||||
FiniteFunction res;
|
|
||||||
for (CellType first = 0; first < BASE; ++first)
|
|
||||||
for (CellType second = 0; second < BASE; ++second) {
|
|
||||||
res.set_result(
|
|
||||||
first,
|
|
||||||
second,
|
|
||||||
(*this)(g(first, second), h(first, second))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
res.update_num();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
FiniteFunction apply_permutation(array<int, BASE> perm) const {
|
|
||||||
FiniteFunction res;
|
|
||||||
for (CellType first = 0; first < BASE; ++first)
|
|
||||||
for (CellType second = 0; second < BASE; ++second) {
|
|
||||||
res.set_result(
|
|
||||||
first,
|
|
||||||
second,
|
|
||||||
find(
|
|
||||||
perm.begin(),
|
|
||||||
perm.end(),
|
|
||||||
(*this)(perm[first], perm[second])
|
|
||||||
) - perm.begin()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
res.update_num();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t get_hash() const {
|
|
||||||
return _num;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t get_index(CellType first, CellType second) {
|
|
||||||
return first * BASE + second;
|
|
||||||
}
|
|
||||||
template <CellType _BASE>
|
|
||||||
friend ostream& operator << (ostream& os, const FiniteFunction<_BASE> &f);
|
|
||||||
private:
|
|
||||||
void update_num() {
|
|
||||||
_num = 0;
|
|
||||||
for (auto&& val: _results) {
|
|
||||||
_num *= BASE;
|
|
||||||
_num += val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint32_t _num;
|
|
||||||
array<CellType, BASE*BASE> _results;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <CellType BASE>
|
|
||||||
ostream& operator << (ostream& os, const FiniteFunction<BASE> &f){
|
|
||||||
for (int first = 0; first < BASE; ++first) {
|
|
||||||
for (int second = 0; second < BASE; ++second) {
|
|
||||||
os << f(first, second);
|
|
||||||
}
|
|
||||||
if ( first != BASE-1 )
|
|
||||||
os << " ";
|
|
||||||
}
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t BASE>
|
template <size_t BASE>
|
||||||
class FixedIniter {
|
class FixedIniter {
|
||||||
public:
|
public:
|
||||||
|
|||||||
Reference in New Issue
Block a user