CELAH , 368 Bytes
Untuk matematikawan, ini adalah perkalian dalam cincin polinom F_2 [x], mengidentifikasi polinomial dengan bilangan asli dengan mengevaluasi pada x = 2 sebagai polinomial lebih dari Z.
Tentu, mari kita lakukan itu! (ini hanya golf longgar, intinya lebih ke pindah ke F 2 [x] dan melakukan perhitungan lebih dari upaya untuk menjadi entri yang menang)
Ini kodenya
f:=function(i,j)R:=PolynomialRing(GF(2));x:=IndeterminatesOfPolynomialRing(R);x:=x[1];a:=function(i)local n,r;r:=0*x;while not i=0 do n:=0;while 2^n<=i do n:=n+1;od;n:=n-1;r:=r+x^n;i:=i-2^n;od;return r;end;b:=function(r)local c,i,n;i:=0;n:=0;for c in CoefficientsOfUnivariatePolynomial(r) do if c=Z(2)^0 then n:=n+2^i;fi;i:=i+1;od;return n;end;return b(a(i)*a(j));end;
Berikut adalah kode yang tidak dipisahkan dengan penjelasan:
xor_multiplication:=function(i,j)
R:=PolynomialRing(GF(2));
x:=IndeterminatesOfPolynomialRing(R);
x:=x[1];
to_ring:=function(i)
local n,r;
r:=0*x;
while not i=0 do
n:=0;
while 2^n<=i do
n:=n+1;
od;
n:=n-1;
r:=r+x^n;
i:=i-2^n;
od;
return r;
end;
to_ints:=function(r)
local c,i,n;
i:=0;n:=0;
for c in CoefficientsOfUnivariatePolynomial(r) do
if c=Z(2)^0 then
n:=n+2^i;
fi;
i:=i+1;
od;
return n;
end;
return to_ints( to_ring(i)*to_ring(j));
end;
Oke, jadi pertama-tama, kita buat cincin polinomial univariat di atas bidang F 2 dan sebut saja R
. Perhatikan bahwa GF(2)
F 2 dalam GAP.
R:=PolynomialRing(GF(2));
Selanjutnya, kita akan menetapkan variabel GAP x
ke tak tentu cincin R
. Sekarang, setiap kali saya mengatakan x
dalam GAP, sistem akan tahu saya berbicara tentang tak tentu cincin R
.
x:=IndeterminatesOfPolynomialRing(R);
x:=x[1];
Selanjutnya, kami memiliki dua fungsi, yang merupakan peta terbalik satu sama lain. Peta-peta ini sama-sama masuk, tetapi tidak melestarikan struktur, jadi saya tidak tahu cara yang lebih baik untuk mengimplementasikannya dalam GAP. Hampir pasti ada cara yang lebih baik, jika Anda mengetahuinya, silakan komentar!
Peta pertama, to_ring
mengambil bilangan bulat dan memetakannya ke elemen cincin yang sesuai. Ia melakukan ini dengan menggunakan konversi ke algoritma biner, di mana setiap 1
yang akan muncul dalam biner digantikan oleh di x^n
mana n
adalah kekuatan yang tepat yang akan diambil 2 jika angka itu memang biner.
to_ring:=function(i)
local n,r;
r:=0*x; # initiate r to the zero element of R
while not i=0 do # this is a modified binary algorithm
n:=0;
while 2^n<=i do
n:=n+1;
od;
n:=n-1;
r:=r+x^n;
i:=i-2^n;
od;
return r;
end;
Fungsi selanjutnya membalikkan ini. to_ints
mengambil elemen cincin dan memetakannya ke integer yang sesuai. Saya melakukan ini dengan mendapatkan daftar koefisien polinomial dan untuk setiap koefisien bukan nol, hasilnya meningkat 2 ^ n, dengan cara yang sama kita akan mengkonversi biner ke desimal.
to_ints:=function(r)
local c,i,n;
i:=0;n:=0;
for c in CoefficientsOfUnivariatePolynomial(r) do
if c=Z(2)^0 then
# ^-- Right here you'll notice that the Z(2) is basically '1' in GF(2). So Z(2)^0 ~ 1 and Z(2)*0 ~ 0
# effectively, this line checks for nonzero coefficients
n:=n+2^i;
fi;
i:=i+1;
od;
return n;
end;
Untuk langkah terakhir, kami memanggil fungsi-fungsi ini. Kami mengambil dua input bilangan bulat, mengubahnya menjadi elemen-elemen di dalam cincin R
, kemudian mengalikan elemen-elemen ini bersama-sama, dan mengirimkan produk kembali ke bilangan bulat.
return to_ints( to_ring(i)*to_ring(j));
PCLMULQDQ
dari ekstensi CLMUL. Sayangnya saya downvoted untuk pengetahuan saya tentang set instruksi x86 sebelumnya (TerkaitPEXT/PDEP
), jadi saya akan meninggalkan ini sebagai komentar di sini.