#include <iostream>
#include <vector>
#include <map>
#include <cassert>
using namespace std;
class BoolMatr {
size_t start;
std::vector<std::map<size_t, bool>> data;
public:
BoolMatr () : start(0) {}
BoolMatr (size_t n, size_t m, size_t start) : start(start) {
resize (n, m);
}
void resize (size_t n, size_t m) {
data.resize (n);
for (size_t i=0; i < n; ++i)
for (size_t j=0; j < m; ++j)
if (data[i].find (j) == data[i].end())
data[i][j] = false;
}
size_t rows() const { return data.size(); }
size_t cols() const { return data[0].size(); }
size_t from() const { return start; }
bool& operator()(size_t i, size_t j) {
assert (i-start < data.size() && j-start < data[i-start].size());
return data[i-start][j-start];
}
bool operator()(size_t i, size_t j) const {
return const_cast<BoolMatr*>(this)->operator()(i,j);
}
BoolMatr& operator+= (const BoolMatr& rhs) {
assert (data.size() != 0 && data.size() == rhs.data.size() && data[0].size() == rhs.data[0].size());
for (size_t i=0; i < data.size(); ++i)
for (size_t j=0; j < data[i].size(); ++j)
(*this)(i+from(), j+from()) ^= rhs(i+rhs.from(), j+rhs.from());
return *this;
}
};
BoolMatr operator+ (const BoolMatr& lhs, const BoolMatr& rhs) {
return BoolMatr (lhs)+=rhs;
}
std::ostream& operator << (std::ostream& os, const BoolMatr& m) {
for (size_t i=0; i < m.rows(); ++i) {
for (size_t j=0; j < m.cols(); ++j)
std::cout << m(i+m.from(),j+m.from()) << ' ';
std::cout << std::endl;
}
return os;
}
int main() {
BoolMatr a(2,3,1), b(2,3,1);
for (size_t i=a.from(); i < a.from()+a.rows(); ++i)
for (size_t j=a.from(); j < a.from()+a.cols(); ++j)
a(i,j)= (i+j)%2 == 0;
for (size_t i=b.from(); i < b.from()+b.rows(); ++i)
for (size_t j=b.from(); j < b.from()+b.cols(); ++j)
b(i,j)= (i+j)%4 == 0;
BoolMatr c = a+b;
std::cout << a << std::endl << b << std::endl << c << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8Y2Fzc2VydD4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgpjbGFzcyBCb29sTWF0ciB7CiAgc2l6ZV90IHN0YXJ0OwogIHN0ZDo6dmVjdG9yPHN0ZDo6bWFwPHNpemVfdCwgYm9vbD4+IGRhdGE7CgogIHB1YmxpYzoKICAgIEJvb2xNYXRyICgpIDogc3RhcnQoMCkge30KCiAgICBCb29sTWF0ciAoc2l6ZV90IG4sIHNpemVfdCBtLCBzaXplX3Qgc3RhcnQpIDogc3RhcnQoc3RhcnQpIHsKICAgICAgICByZXNpemUgKG4sIG0pOwogICAgfQoKICAgdm9pZCByZXNpemUgKHNpemVfdCBuLCBzaXplX3QgbSkgewogICAgICAgZGF0YS5yZXNpemUgKG4pOwogICAgICAgZm9yIChzaXplX3QgaT0wOyBpIDwgbjsgKytpKQogICAgICAgICBmb3IgKHNpemVfdCBqPTA7IGogPCBtOyArK2opCiAgICAgICAgICAgaWYgKGRhdGFbaV0uZmluZCAoaikgPT0gZGF0YVtpXS5lbmQoKSkKICAgICAgICAgICAgIGRhdGFbaV1bal0gPSBmYWxzZTsKICAgfQogICAKICAgc2l6ZV90IHJvd3MoKSBjb25zdCB7IHJldHVybiBkYXRhLnNpemUoKTsgfQogICBzaXplX3QgY29scygpIGNvbnN0IHsgcmV0dXJuIGRhdGFbMF0uc2l6ZSgpOyB9CiAgIHNpemVfdCBmcm9tKCkgY29uc3QgeyByZXR1cm4gc3RhcnQ7IH0KCiAgIGJvb2wmIG9wZXJhdG9yKCkoc2l6ZV90IGksIHNpemVfdCBqKSB7CiAgICAgIGFzc2VydCAoaS1zdGFydCA8IGRhdGEuc2l6ZSgpICYmIGotc3RhcnQgPCBkYXRhW2ktc3RhcnRdLnNpemUoKSk7CiAgICAgIHJldHVybiBkYXRhW2ktc3RhcnRdW2otc3RhcnRdOwogICB9CgogICBib29sIG9wZXJhdG9yKCkoc2l6ZV90IGksIHNpemVfdCBqKSBjb25zdCB7CiAgIAkgIHJldHVybiBjb25zdF9jYXN0PEJvb2xNYXRyKj4odGhpcyktPm9wZXJhdG9yKCkoaSxqKTsKICAgfQogICAJCiAgIEJvb2xNYXRyJiBvcGVyYXRvcis9IChjb25zdCBCb29sTWF0ciYgcmhzKSB7CiAgICAgIGFzc2VydCAoZGF0YS5zaXplKCkgIT0gMCAmJiBkYXRhLnNpemUoKSA9PSByaHMuZGF0YS5zaXplKCkgJiYgZGF0YVswXS5zaXplKCkgPT0gcmhzLmRhdGFbMF0uc2l6ZSgpKTsKICAgICAgZm9yIChzaXplX3QgaT0wOyBpIDwgZGF0YS5zaXplKCk7ICsraSkKICAgICAgICBmb3IgKHNpemVfdCBqPTA7IGogPCBkYXRhW2ldLnNpemUoKTsgKytqKQogICAgICAgICAgKCp0aGlzKShpK2Zyb20oKSwgaitmcm9tKCkpIF49IHJocyhpK3Jocy5mcm9tKCksIGorcmhzLmZyb20oKSk7CiAgICAgIHJldHVybiAqdGhpczsKICAgfQp9OwoKQm9vbE1hdHIgb3BlcmF0b3IrIChjb25zdCBCb29sTWF0ciYgbGhzLCBjb25zdCBCb29sTWF0ciYgcmhzKSB7CiAgcmV0dXJuIEJvb2xNYXRyIChsaHMpKz1yaHM7Cn0KCnN0ZDo6b3N0cmVhbSYgb3BlcmF0b3IgPDwgKHN0ZDo6b3N0cmVhbSYgb3MsIGNvbnN0IEJvb2xNYXRyJiBtKSB7Cglmb3IgKHNpemVfdCBpPTA7IGkgPCBtLnJvd3MoKTsgKytpKSB7CiAgCSAgZm9yIChzaXplX3Qgaj0wOyBqIDwgbS5jb2xzKCk7ICsraikKICAJICAgIHN0ZDo6Y291dCA8PCBtKGkrbS5mcm9tKCksaittLmZyb20oKSkgPDwgJyAnOwoJICBzdGQ6OmNvdXQgPDwgc3RkOjplbmRsOwoJfQogIHJldHVybiBvczsKfQoKaW50IG1haW4oKSB7CglCb29sTWF0ciBhKDIsMywxKSwgYigyLDMsMSk7CgkKCWZvciAoc2l6ZV90IGk9YS5mcm9tKCk7IGkgPCBhLmZyb20oKSthLnJvd3MoKTsgKytpKQogIAkgIGZvciAoc2l6ZV90IGo9YS5mcm9tKCk7IGogPCBhLmZyb20oKSthLmNvbHMoKTsgKytqKQoJICAgICBhKGksaik9IChpK2opJTIgPT0gMDsKCSAgICAgCglmb3IgKHNpemVfdCBpPWIuZnJvbSgpOyBpIDwgYi5mcm9tKCkrYi5yb3dzKCk7ICsraSkKICAJICBmb3IgKHNpemVfdCBqPWIuZnJvbSgpOyBqIDwgYi5mcm9tKCkrYi5jb2xzKCk7ICsraikKCSAgICAgYihpLGopPSAoaStqKSU0ID09IDA7CgkKCUJvb2xNYXRyIGMgPSBhK2I7CgkKCXN0ZDo6Y291dCA8PCBhIDw8IHN0ZDo6ZW5kbCA8PCBiIDw8IHN0ZDo6ZW5kbCA8PCBjIDw8IHN0ZDo6ZW5kbDsKCQoJcmV0dXJuIDA7Cn0=