#include "message.h"
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1e9;
void send_packet_d(vector<bool> &a) { send_packet(a); } //void send_packet_d(vector<bool> &a) { static int cnt = 1; cout << cnt++ << ": "; for (bool x : a) cout << x << " "; cout << endl; send_packet(a); }
void send_message(std::vector<bool> M, std::vector<bool> C) {
M.push_back(1);
auto check = [&](int s, int e, int d) -> array<int, 3> {
int cost = 1e9;
int f1 = -1;
for (int i = 0; i < 8; i++) {
if (C[s+d*i] == 0) {
f1 = s+d*i;
break;
}
}
if (f1 == -1) return {INF, 0, 0};
int f2 = -1;
for (int i = 0; i < 8; i++) {
if (C[f1+d+d*i] == 0) {
f2 = f1+d+d*i;
break;
}
}
if (f2 == -1) return {INF, 0, 0};
//cout << f1 << " " << f2 << endl;
int cnt = 2;
cost = 7;
int i = f2+d;
while (cnt < 16) {
cost++;
//cout << cnt << ": ";
int old = cnt;
for (int it = 0; it < old && ((s <= e && s <= i && i <= e) || (e <= s && e <= i && i <= s)) && cnt < 16; i += d, it++) {
if (C[i] == 0) cnt++;
//cout << i << " ";
}
//cout << endl;
}
return {cost, f1, f2};
};
auto encode = [&](int x, int d = 0) {
vector<bool> a(31);
if (d) {
a = vector<bool>(31, d == -1);
send_packet_d(a);
}
//cout << "x: " << x << endl;
for (int i = 0; i < 3; i++) {
a = vector<bool>(31, (x&(1<<i)) != 0);
send_packet_d(a);
}
};
auto c1 = check(0, 30, +1);
//cout << "Check +1: " << c1[0] << " " << c1[1] << " " << c1[2] << endl;
auto c2 = check(30, 0, -1);
//cout << "Check -1: " << c2[0] << " " << c2[1] << " " << c2[2] << endl;
int d, f1, f2, s, e;
if (c1[0] < c2[0]) {
encode(c1[1], +1), encode(c1[2]-c1[1]-1);
d = +1, f1 = c1[1], f2 = c1[2], s = 0, e = 30;
}
else {
encode(30-c2[1], -1), encode(c2[1]-c2[2]-1);
d = -1, f1 = c2[1], f2 = c2[2], s = 30, e = 0;
}
int cnt = 2;
vector<int> pos{f1, f2};
int i = f2+d;
while (cnt < 16) {
int old = cnt;
vector<int> npos;
vector<bool> a(31);
for (int it = 0; it < old && ((s <= e && s <= i && i <= e) || (e <= s && e <= i && i <= s)) && cnt < 16; i += d, it++) {
if (C[i] == 0) cnt++, npos.push_back(i);
a[pos[it]] = !C[i];
}
send_packet_d(a);
for (int np : npos) pos.push_back(np);
}
vector<bool> a(31);
auto flush = [&]() -> void {
send_packet_d(a);
a = vector<bool>(31);
};
i = 0;
for (bool bit : M) {
a[pos[i]] = bit;
i++;
if (i == 16) flush(), i = 0;
}
if (i) flush();
//cout << "C: ";for (bool x : C) cout << x << " "; cout << endl;
//cout << "---" << endl<<endl;
}
std::vector<bool> receive_message(std::vector<std::vector<bool>> R) {
auto readblob = [&](vector<bool> a) -> int {
int one = 0;
for (bool b : a) one += b;
return one >= 16;
};
int drev = readblob(R[0]), d, s, e;
int f1 = readblob(R[1])+readblob(R[2])*2+readblob(R[3])*4;
int f2 = readblob(R[4])+readblob(R[5])*2+readblob(R[6])*4;
if (drev) {
f1 = 30-f1;
f2 = f1-f2-1;
d = -1, s = 30, e = 0;
}
else {
f2 = f1+f2+1;
d = +1, s = 0, e = 30;
}
vector<int> pos{f1, f2}, c(31, 1);
c[f1] = 0, c[f2] = 0;
int j = f2+d;
int p = 7;
while (pos.size() < 16) {
vector<int> npos;
auto a = R[p++];
for (int i = s; min(s, e) <= i && i <= max(s, e); i += d) if (c[i] == 0) {
if (a[i]) npos.push_back(j);
j += d;
}
for (int np : npos) pos.push_back(np), c[np] = 0;
}
//cout << "C: ";for (int x : c) cout << x << " "; cout << endl;
//cout << drev << " f1: " << f1 << " f2: " << f2 << endl;
vector<bool> ans;
while (p < (int)R.size()) {
auto a = R[p++];
for (int ps : pos) ans.push_back(a[ps]);
}
while (ans.back() == 0) ans.pop_back();
ans.pop_back();
//cout << "---" << endl<<endl;
return ans;
}