#include <bits/stdc++.h>
#include "message.h"
using namespace std;
// std::vector<bool> send_packet(std::vector<bool> A)
//de aplicat o permuatre random sau ceva la inceput
//ar trebui sa micsoreze numarul de mesaje trimise cu gen 10
const int BULAN = 10;
int perm[31];
int iperm[31];
void init() {
mt19937 rng(36545);
for (int i = 0; i < 31; i ++) {
perm[i] = i;
}
shuffle(perm, perm + 31, rng);
for (int i = 0; i < 31; i ++) {
iperm[perm[i]] = i;
}
//for (int i = 0; i < 31; i ++) {
//cout << perm[i] << " ";
//}
//cout << '\n';
//for (int i = 0; i < 31; i ++) {
//cout << iperm[i] << " ";
//}
//cout << '\n';
}
vector<bool> apply_perm(vector<bool> x) {
vector<bool> nx(31);
for (int i = 0; i < 31; i ++) {
nx[i] = x[perm[i]];
}
return nx;
}
vector<bool> apply_iperm(vector<bool> x) {
vector<bool> nx(31);
for (int i = 0; i < 31; i ++) {
nx[i] = x[iperm[i]];
}
return nx;
}
void send_message(vector<bool> M, vector<bool> C) {
init();
C = apply_perm(C);
vector<vector<bool>> trim(BULAN + (M.size() + 15) / 16, vector<bool>(31));
vector<int> bune;
for (int i = 0; i < 31; i ++) {
if (!C[i]) {
bune.push_back(i);
}
}
//for (int i = 0; i < 31; i ++) {
//cout << (int)C[i] << " ";
//}
//cout << '\n';
bune.push_back(bune[0] + 31);
for (int i = 0; i < 16; i ++) {
trim[bune[i + 1] - bune[i] - 1][bune[i]] = 1;
}
int col = 0, rand = BULAN;
for (auto i : M) {
trim[rand][bune[col]] = i;
col ++;
if (col == 16) {
col = 0;
rand ++;
}
}
for (auto i : trim) {
//cout << i.size() << " ";
//cout << apply_iperm(i).size() << '\n';
send_packet(apply_iperm(i));
}
vector<bool> last(31);
col --;
if (col == -1) {
col = 15;
}
for (int i = 0; i <= col; i ++) {
last[bune[i]] = 1;
}
send_packet(apply_iperm(last));
}
vector<bool> receive_message(vector<vector<bool>> R) {
init();
for (auto &i : R) {
i = apply_perm(i);
}
//for (int i = 0; i < BULAN; i ++, cout << '\n') {
//for (int j = 0; j < 31; j ++) {
//cout << (int)R[i][j] << " ";
//}
//}
vector<int> nxt(31, 0);
for (int i = 0; i < 31; i ++) {
for (int j = 0; j < BULAN; j ++) {
if (R[j][i] == 1) {
nxt[i] = (i + j + 1) % 31;
break;
}
}
}
//cout << "SKIB\n";
vector<int> bune;
for (int i = 0; i < 31; i ++) {
vector<int> v;
vector<bool> viz(31, 0);
int loc = nxt[i];
v.push_back(i);
viz[i] = 1;
while (!viz[loc]) {
v.push_back(loc);
viz[loc] = 1;
loc = nxt[loc];
}
if (v.size() == 16) {
bune = v;
break;
}
}
sort(bune.begin(), bune.end());
vector<bool> ans;
for (int i = BULAN; i < (int)R.size() - 2; i ++) {
for (auto j : bune) {
ans.push_back(R[i][j]);
}
}
for (auto j : bune) {
if (R[R.size() - 1][j]) {
ans.push_back(R[R.size() - 2][j]);
}
}
return ans;
}