# Find the linear transformation

Given a set of bit vectors $$\A\$$ and a binary matrix $$\M\$$, we can define the set $$\MA = \{ Mx : x \in A \}\$$, where $$\ M x \$$ is the result of the matrix multiplication of $$\ M \$$ by $$\ x \$$ over $$\\mathbb{F}_2\$$, the field with two elements.

Given the set $$\ A \$$ and the set $$\ M A \$$, your task is to recover a possible value for $$\ M \$$ in as little time as possible.

Note that since these are sets, they are unordered.

# Scoring

For all pairs of integers $$\ 0 < a \leq 15\$$, $$\a < b \leq 32\$$, I produced a random $$\32 \times b\$$ binary matrix $$\M\$$, a set $$\ A \$$ of size $$\2^a\$$ with random vectors of size $$\ b \$$, and calculated $$\ M A \$$.

Your score is the time you take to solve all these samples.

# I/O

Your program will recieve input from stdin in the following format:

t
b1 n1
x1 x2 x3 x4 ... xn1
y1 y2 y3 y4 ... yn1
...
bt nt
x1 x2 x3 x4 ... xnt
y1 y2 y3 y4 ... ynt


t is the number of instances of the problem you are required to solve. For each instance, you will get the number b, the number of bits in the input, and n, the number of vectors. In the next line, you will get n integers $$\0 \leq x < 2^b\$$, whose binary representation is the input vectors. In the following line, you will get the n integers $$\0 \leq x < 2^{32}\$$ whose binary representation is the vectors in $$\MA\$$.

You are to output t lines to stdout in the format

x1 x2 ... x32
x1 x2 ... x32
...
x1 x2 ... x32
x1 x2 ... x32


each containing 32 integers $$\0 \leq x < 2^b\$$ representing the rows of $$\ M \$$.

# Example

For the input

1
7 16
5 14 21 23 26 36 38 45 55 74 76 80 95 100 109 123
114917382 260133574 340793034 1730627271 1755714561 1818746903 2816946300 2860390058 3157685360 3190685792 3599242337 3720917681 3919737131 4067636519 4180906999 4260521953


A possible matrix is

48 43 76 13 102 126 98 125 88 51 76 69 72 27 76 115 89 11 33 29 0 96 64 87 64 39 48 118 61 115 78 43


Under this matrix, 0000101 (5), for example, comes out to be 01101100011001111110000000010111 (1818746903)

# Rules

• Standard loopholes are disallowed.
• The programming language you use must be freely available.
• The code will be timed on my computer which has Intel Core i7-9700 with 8 threads and 32GB RAM.
• You may not exploit the PRNG (e.g. find its seed and from that find which matrices were generated).
• You may assume all other properties implied by the generation method (e.g. that n is a power of two, or that the sets are given sorted).

This is the code used to generate the samples (on stdout, stderr just logs the matrices, which of course won't be provided to your program):

#include <set>
#include <assert.h>
#include <random>
#include <iostream>
#define maxv(b) (b==32?-1u:(1u<<b)-1u)

uint32_t matmul(uint32_t M, uint32_t x) {
uint32_t ans = 0;
for (int i = 0; i < 32; i++) ans |= ((uint32_t)__builtin_parity(M[i] & x)) << (31-i);
return ans;
}

std::mt19937 rng(time(0));

int main() {
std::cout << "360\n";
for (int a = 1; a <= 15; a++) {
for (int b = a+1; b <= 32; b++) {
std::set<uint32_t> A;
uint32_t M;
for (int i = 0; i < 32; i++) {
M[i] = std::uniform_int_distribution<uint32_t>(0, maxv(b))(rng);
std::cerr << M[i] << ' ';
}
std::cerr << '\n';
std::set<uint32_t> MA;
for (int i = 0; i < 1<<a; i++) {
uint32_t x;
do x = std::uniform_int_distribution<uint32_t>(0, maxv(b))(rng); while (A.count(x));
A.insert(x);
MA.insert(matmul(M, x));
}
assert(A.size()==MA.size());
std::cout << b << ' ' << (1<<a) << '\n';
for (uint32_t a : A) std::cout << a << ' ';
std::cout << '\n';
for (uint32_t a : MA) std::cout << a << ' ';
std::cout << '\n';
}
}
}
$$$$
`
• This seems like a hard problem. Do you have a working solution? Mar 24 at 12:26
• @user1502040 An efficient one? No. Mar 24 at 18:12