Hitung simbol Kronecker

9

Tautan yang relevan di sini dan di sini , tetapi di sini adalah versi singkatnya:

Anda memiliki input dua bilangan bulat adan bantara infinity negatif dan infinity (walaupun jika perlu, saya dapat membatasi rentang, tetapi fungsinya masih harus menerima input negatif).

Definisi simbol Kronecker

Anda harus mengembalikan simbol Kronecker (a|b)untuk input adan di bmana

(a|b) = (a|p_1)^e_1 * (a|p_2)^e_2 * ... * (a|p_n)^e_n

di mana b = p_1^e_1 * p_2^e_2 * ... * p_n^e_n, dan p_idan e_iadalah bilangan prima dan eksponen dalam faktorisasi utama b.

Untuk prime yang aneh p, (a|p)=a^((p-1)/2) (mod p)seperti yang didefinisikan di sini .

Untuk b == 2,(n|2)={0 for n even; 1 for n odd, n=+/-1 (mod 8); -1 for n odd, n=+/-3 (mod 8)

Untuk b == -1,(n|-1)={-1 for n<0; 1 for n>0

Jika a >= b, (a|b) == (z|b)dimana z == a % b. Dengan properti ini, dan seperti yang dijelaskan di sini dan di sini , aadalah residu kuadrat dari bif zadalah, meskipun a >= b.

(-1|b)= 1jika b == 0,1,2 (mod 4)dan -1jika b == 3 (mod 4). (0|b)adalah 0kecuali untuk (0|1)yang 1, karena (a|1)selalu 1dan untuk negatif a, (-a|b) == (-1|b) * (a|b).

Output dari simbol Kronecker selalu -1, 0 or 1, di mana outputnya adalah 0jika adan bmemiliki faktor umum. If badalah prime odd, (a|b) == 1if aadalah residu mod kuadratikb , dan -1jika bukan residu kuadrat.

Aturan

  • Kode Anda harus berupa program atau fungsi.

  • Masukan harus dalam urutan a b.

  • Outputnya harus berupa -1, 0atau 1.

  • Ini kode golf, jadi kode Anda tidak harus efisien, cukup singkat.

  • Tidak ada bawaan yang secara langsung menghitung Kronecker atau simbol Jacobi dan Legendre terkait. Built-in lainnya (untuk faktorisasi utama, misalnya) adalah permainan yang adil.

Contohnya

>>> kronecker(1, 5)
1
>>> kronecker(3, 8)
-1
>>> kronecker(15, 22)
1
>>> kronecker(21, 7)
0
>>> kronecker(5, 31)
1
>>> kronecker(31, 5)
1
>>> kronecker(7, 19)
1
>>> kronecker(19, 7)
-1
>>> kronecker(323, 455625)
1
>>> kronecker(0, 12)
0
>>> kronecker(0, 1)
1
>>> kronecker(12, 0)
0
>>> kronecker(1, 0)
1
>>> kronecker(-1, 5)
1
>>> kronecker(1, -5)
1
>>> kronecker(-1, -5)
-1
>>> kronecker(6, 7)
-1
>>> kronecker(-1, -7)
1
>>> kronecker(-6, -7)
-1

Ini adalah fungsi yang rumit, jadi tolong beri tahu saya jika ada sesuatu yang tidak jelas.

Sherlock9
sumber
Apakah Anda yakin tidak ingin melarang built-in? reference.wolfram.com/language/ref/KroneckerSymbol.html
Martin Ender
@ MartinBüttner Saya mengedit dalam contoh ketika saya melihat komentar Anda. Saya akan melarang built-in yang secara langsung menghitung simbol Kronecker, Jacobi atau Legendre, tetapi hal lain (termasuk fungsi faktorisasi utama) harus menjadi permainan yang adil.
Sherlock9
im tidak sepenuhnya yakin mengapa (31 | 5) memberikan 1. Tidak boleh ada residu qudratic jadi mengapa isnt -1?
Eumel
juga 7/19 harus 1 dan 19/7 harus -1 menurut wiki Anda terhubung
Eumel
3
Jika solusi harus menangani input negatif dan nol dengan benar, Anda harus menambahkan beberapa test case untuk itu.
Martin Ender

Jawaban:

2

CJam (70 byte)

{_g\zmf+f{:P2+"W>2*(
z1=
;1
7&4-z[0W0X0]=
P%P+P(2/#P%_1>P*-"N/<W=~}:*}

Demo online (test case dibuat dengan Mathematica).

Pembedahan

{               e# Anonymous function. Stack: a b
  _g\zmf+       e# Factorise b, with special treatment for negatives
                e# CJam also gives special treatment to 0 and 1
                e# Stack: e.g. a [-1 2 2 5]; or a [-1 1]; or a [0 0]; or a [1 2 2 5]
  f{            e# For each "prime" factor P, find (a|P)
    :P2+        e# Extract code for P from an array formed by splitting a string
    "W>2*(      e#   a -> (a|-1)
z1=             e#   a -> (a|0)
;1              e#   a -> (a|1)
7&4-z[0W0X0]=   e#   a -> (a|2)
P%P+P(2/#P%_1>P*-" e# a -> (a|P) for odd prime P
    N/<W=~      e# Split string and select appropriate element
  }
  :*            e# Multiply the components together
}

Saya menemukan beberapa cara mengevaluasi (a|2)untuk jumlah karakter yang sama, dan telah memilih untuk menggunakan yang dengan presentasi paling jelas.

integer array <W= adalah IMO cara yang cukup elegan untuk melakukan fallback: jika integer lebih besar dari panjang array, kita pilih elemen terakhir.

Komentar lain

Sangat mengecewakan bahwa untuk prime odd pgaya Fermat langsung (a|p)sangat pendek, karena ada cara yang sangat golf untuk menemukan (a|n)aneh aneh nyang ingin saya gunakan. Dasarnya adalah lemma Zolotarev:

Jika pprima ganjil dan amerupakan bilangan bulat bilangan bulat untuk pmaka simbol Legendre (a|p)adalah tanda permutasix -> ax (mod p)

Ini diperkuat oleh Frobenius untuk

Jika adan bbilangan bulat positif coprime maka simbol Jacobi (a|b)adalah tanda permutasix -> ax (mod b)

dan oleh Lerch ke

Jika bbilangan bulat ganjil positif dan amerupakan bilangan bulat koprime untuk bmaka simbol Jacobi (a|b)adalah tanda permutasix -> ax (mod b)

Lihat Brunyate dan Clark, Memperluas pendekatan Zolotarev-Frobenius untuk timbal balik kuadratik , The Ramanujan Journal 37.1 (2014): 25-50 untuk referensi.

Dan itu dapat dengan mudah diperkuat satu langkah lebih jauh (walaupun saya belum melihat ini dalam literatur) untuk

Jika bbilangan bulat ganjil positif dan abilangan bulat maka simbol Jacobi (a|b)adalah simbol Levi-Civita dari peta x -> ax (mod b).

Bukti: jika amemang coprime bmaka kita menggunakan Zolotarev-Frobenius-Lerch; jika tidak, peta bukanlah permutasi, dan simbol Levi-Civita adalah 0seperti yang diinginkan.

Ini memberikan perhitungan simbol Jacobi

{_2m*{~>},@ff*\ff%::-:*g}

Tetapi perlakukan khusus diperlukan untuk (a|-1)dan (a|2)berarti bahwa saya belum menemukan cara menghitung simbol Kronecker yang lebih pendek dengan pendekatan ini: lebih pendek untuk membuat faktor dan memperlakukan bilangan prima secara individual.

Peter Taylor
sumber
4

Python 3, 747 369 335 byte

Sebagai contoh jawaban, hanya sedikit bermain golf, dan untuk memberi Anda gambaran seperti apa jawaban itu.

Dan ya, faktorisasi utama dan bit enkode run-length dikumpulkan dari Pyth dengan permintaan maaf kepada isaacg .

from itertools import*
def k(d,r):
 if d<0:a=-d;m=1
 else:a=d;m=0
 if r==1:return 1
 p=1;w=r;n=2;f=[]
 while n*n<=w:
  while w%n<1:w//=n;f+=n,
  n+=1
 if w>1:f+=w,
 z=[[k,len(list(g))]for k,g in groupby(f)]
 for i,j in z:
  if i==2:p*=pow(-1,(a*a-1)//8)
  x=pow(a,(i-1)//2,i)
  if x>1:x-=i
  p*=x**j
 if m:p*=pow(-1,(r-1)//2)
 return p
Sherlock9
sumber
4
Permintaan maaf diterima - Saya senang seseorang membaca kode sumber Pyth.
isaacg
2

Mathematica, 169 175 165 byte

(1|-1)~k~0=_~k~1=1
_~k~0=0
a_~k~-1=If[a<0,-1,1]
a_~k~2=DirichletCharacter[8,2,a]
a_~k~p_/;PrimeQ@p=Mod[a^((p-1)/2),p,-1]
a_~k~b_:=1##&@@(a~k~#^#2&@@@FactorInteger@b)
alephalpha
sumber
2

LabVIEW, 44 Bytes LabVIEW Primitif

Karena simetrisnya, saya menukar input jika a lebih besar dari b.

Merupakan formula sebenarnya sekarang

menghitung seperti biasa menurut

untuk kasus yang sebenarnya

Eumel
sumber
Sayangnya, (a|b) != (b|a)dalam semua kasus. Dalam kebanyakan kasus, ya, tetapi tidak di semua dari mereka. Meskipun itu akan berhasil jika Anda mengurangi a mod balih-alih menukar mereka.
Sherlock9
karena saya punya explantion sekarang saya dapat mengeditnya, beri saya min
Eumel
1
Apakah ada cara saya bisa menguji ini? Saya tidak begitu mengerti bagaimana cara kerja LabView.
Sherlock9
itu pertanyaan yang bagus, saya bisa memikirkan 2 cara. Pertama saya bisa membangun .exe dan mengirimkannya kepada Anda, kedua Anda bisa mendapatkan versi uji labview dan saya bisa mengirimkan Anda vi atau Anda dapat membangunnya kembali dari pic.
Eumel
7
Ini bukan 44 byte. Jika Anda menetapkan sistem penilaian yang tidak didasarkan pada ukuran file, Anda harus menyebutnya sesuatu selain byte.
feersum
1

Julia, 195 byte

k(a,b)=b==0?a∈[1,-1]?1:0:b==1?1:b==2?iseven(a)?0:a%8∈[1,-1]?1:-1:b==-1?a<1?-1:1:isprime(b)&&b>2?a%b==0?0:a∈[i^2%b for i=0:b-1]?1:-1:k(a,sign(b))*prod(i->k(a,i)^factor(b)[i],keys(factor(b)))

Ini adalah fungsi rekursif kyang menerima dua bilangan bulat dan mengembalikan bilangan bulat.

Tidak Disatukan:

function k(a::Integer, b::Integer)
    if b == 0
        return a  [1, -1] ? 1 : 0
    elseif b == 1
        return 1
    elseif b == 2
        return iseven(a) ? 0 : a % 8  [1, -1] ? 1 : -1
    elseif b == -1
        return a < 1 ? -1 : 1
    elseif isprime(b) && b > 2
        return a % b == 0 ? 0 : a  [i^2 % b for i = 1:b-1] ? 1 : -1
    else
        p = factor(b)
        return k(a, sign(b)) * prod(i -> k(a, i)^p[i], keys(p))
    end
end
Alex A.
sumber
1

Haskell, 286 byte

a#0|abs a==1=1|1<2=0
a#1=1
a#2|even a=0|mod a 8`elem`[1,7]=1|1<2=(-1)
a#b|b<0=a`div`abs a*a#(-b)|all((/=0).mod b)[2..b-1]=if elem n[0,1] then n else(-1)|1<2=product$map(a#)$f b where n=a^(div(b-1)2)`mod`b
f 1=[]
f n|n<0=(-1):f(-n)|1<2=let p=head$filter((==0).mod n)[2..n]in p:f(div n p)

Mungkin tidak sepenuhnya dioptimalkan, tetapi upaya yang berani. Simbol Kronecker didefinisikan sebagai fungsi infiks a # b, yaitu

*Main>323#455265 
1
mematikan
sumber