#include <bitset>
#include <iostream>
#include <string>
#include <utility>
using namespace std;
template<unsigned N> class BitArray : public bitset<N> {
public:
typedef typename bitset<N>::reference reference;
bool operator[](unsigned i) const { return bitset<N>::operator[](i-1); }
reference operator[](unsigned i) { return bitset<N>::operator[](i-1); }
BitArray() : bitset<N>() { }
explicit BitArray(string const& s) : bitset<N>(string(s.rbegin(), s.rend())) { }
string to_string() const {
string s = bitset<N>::to_string();
return string(s.rbegin(), s.rend());
}
friend ostream& operator<<(ostream& os, BitArray const& a) {
os << a.to_string();
return os;
}
};
template<unsigned N>
pair< BitArray<N/2>, BitArray<N/2> > split(BitArray<N> const& a) {
pair< BitArray<N/2>, BitArray<N/2> > p;
for (unsigned i = 1; i <= N/2; ++i) {
p.first[i] = a[i];
}
for (unsigned i = 1; i <= N/2; ++i) {
p.second[i] = a[N/2+i];
}
return p;
}
//------------------------------------------------------------------------------
unsigned const N = 8;
BitArray<N> encode(BitArray<N> const& A) {
// Split the input into two halves.
pair< BitArray<N/2>, BitArray<N/2> > const& halves = split(A);
BitArray<N/2> const& A1 = halves.first;
BitArray<N/2> const& A2 = halves.second;
// Initialize the result with all bits to zero.
BitArray<N> B;
// Do the work.
for (unsigned i = 1; i <= N/2; ++i) {
for (unsigned j = 1; j <= N/2; ++j) {
B[i+j] = B[i+j] ^ (A1[i] & A2[j]);
}
}
return B;
}
//------------------------------------------------------------------------------
void test(string const& s) {
cout << s << " -> " << encode(BitArray<N>(s)) << endl;
}
int main() {
string s1, s2;
s1 = "00000000";
test(s1);
cout << endl;
s1 = "11111111";
test(s1);
cout << endl;
s1 = "00001111";
s2 = "11110000";
test(s1);
test(s2);
cout << endl;
s1 = "01101101";
s2 = "11010110";
test(s1);
test(s2);
cout << endl;
s1 = "10001111";
s2 = "11111000";
test(s1);
test(s2);
s1 = "11001010";
s2 = "10101100";
test(s1);
test(s2);
return 0;
}