Oblicz symbol Kroneckera

9

Ważne linki tutaj i tutaj , ale oto krótka wersja:

Masz wejście dwóch liczb całkowitych ai bmiędzy ujemną nieskończonością a nieskończonością (chociaż w razie potrzeby mogę ograniczyć zakres, ale funkcja musi nadal akceptować ujemne dane wejściowe).

Definicja symbolu Kronecker

Musisz zwrócić symbol Kronecker (a|b)dla danych wejściowych ai bgdzie

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

gdzie b = p_1^e_1 * p_2^e_2 * ... * p_n^e_ni p_ii e_isą liczbami pierwszymi i wykładnikami w rozkładzie liczb pierwszych na b.

Dla nieparzystej liczby pierwszej p, (a|p)=a^((p-1)/2) (mod p)jak zdefiniowano tutaj .

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

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

W przypadku a >= b, (a|b) == (z|b)w którym z == a % b. Ta właściwość, jak wyjaśniono tu i tutaj , ajest kwadratową pozostałością bif z, chociaż a >= b.

(-1|b)= 1jeśli b == 0,1,2 (mod 4)i -1jeśli b == 3 (mod 4). (0|b)jest 0wyjątkiem (0|1), który jest 1, bo (a|1)jest zawsze 1i dla negatywu a, (-a|b) == (-1|b) * (a|b).

Dane wyjściowe symbolu Kronecker są zawsze -1, 0 or 1, gdzie dane wyjściowe są, 0jeśli ai bmają jakieś wspólne czynniki. If bjest nieparzystą liczbą pierwszą, (a|b) == 1jeśli ajest kwadratowym modem pozostałościb , a -1jeśli nie jest kwadratowym reszty.

Zasady

  • Twój kod musi być programem lub funkcją.

  • Dane wejściowe muszą być w kolejności a b.

  • Dane wyjściowe muszą być albo -1, 0albo 1.

  • To jest kod golfowy, więc twój kod nie musi być wydajny, tylko krótki.

  • Brak wbudowanych funkcji, które bezpośrednio obliczają Kronecker lub powiązane symbole Jacobi i Legendre. Inne wbudowane elementy (na przykład w przypadku pierwszej faktoryzacji) to uczciwa gra.

Przykłady

>>> 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

Jest to skomplikowana funkcja, więc daj mi znać, jeśli coś jest niejasne.

Sherlock9
źródło
Czy na pewno nie chcesz zabronić wbudowanych funkcji? reference.wolfram.com/language/ref/KroneckerSymbol.html
Martin Ender
@ MartinBüttner Edytowałem w przykładach, kiedy zobaczyłem twój komentarz. Nie zezwalam na wbudowane funkcje, które bezpośrednio obliczają symbole Kroneckera, Jacobiego lub Legendre, ale wszystko inne (w tym funkcje faktoryzacji liczby pierwszej) powinno być uczciwą grą.
Sherlock9,
nie jestem do końca pewien, dlaczego (31 | 5) daje 1. Nie powinno być qudratycznej pozostałości, więc dlaczego nie jest -1?
Eumel,
również 7/19 powinno wynosić 1, a 19/7 powinno wynosić -1, zgodnie z wiki, które
podłączyłeś
3
Jeśli rozwiązania muszą poprawnie obsługiwać wartości ujemne i zerowe, zdecydowanie powinieneś dodać do tego kilka przypadków testowych.
Martin Ender

Odpowiedzi:

2

CJam (70 bajtów)

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

Demo online (przypadki testowe wygenerowane za pomocą Mathematica).

Sekcja

{               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
}

Znalazłem kilka sposobów oceniania (a|2)dla tej samej liczby znaków i zdecydowałem się użyć tego z najczystszą prezentacją.

integer array <W= jest IMO dość eleganckim sposobem na wykonywanie awarii: jeśli liczba całkowita jest większa niż długość tablicy, wybieramy ostatni element.

Inne komentarze

Rozczarowuje fakt , że w przypadku liczby nieparzystej pbezpośredni styl Fermata (a|p)jest tak krótki, ponieważ istnieje bardzo golfowy sposób na znalezienie (a|n)dodatniej liczby nieparzystej, z nktórej chciałem skorzystać. Podstawą jest lemat Zolotareva:

Jeśli pjest nieparzystą liczbą pierwszą i ajest liczbą całkowitą dla, pto symbol Legendre (a|p)jest znakiem permutacjix -> ax (mod p)

Zostało to wzmocnione przez Frobeniusa do

Jeśli ai bsą liczbami całkowitymi dodatnimi nieparzystymi, to symbol Jacobiego (a|b)jest znakiem permutacjix -> ax (mod b)

i przez Lerch do

Jeśli bjest dodatnią nieparzystą liczbą całkowitą i ajest całkowitym koprime do, bto symbol Jacobi (a|b)jest znakiem permutacjix -> ax (mod b)

Patrz Brunyate i Clark, Rozszerzanie podejścia Zolotareva -Frobeniusa do kwadratowej wzajemności , The Ramanujan Journal 37.1 (2014): 25-50 w celach informacyjnych.

I można to z łatwością wzmocnić o krok dalej (chociaż nie widziałem tego w literaturze) do

Jeśli bjest dodatnią nieparzystą liczbą całkowitą i aliczbą całkowitą, to symbol Jacobi (a|b)jest symbolem Levi-Civita mapy x -> ax (mod b).

Dowód: jeśli ajest to prawo autorskie, bwówczas używamy Zolotarev-Frobenius-Lerch; w przeciwnym razie mapa nie jest permutacją, a symbol Levi-Civita jest odpowiedni 0.

Daje to obliczenie symbolu Jacobi

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

Ale specjalne traktowanie wymagane (a|-1)i (a|2)oznacza, że ​​nie znalazłem sposobu na obliczenie symbolu Kroneckera, który byłby krótszy przy takim podejściu: krótszy jest faktoryzować liczby pierwsze i traktować je indywidualnie.

Peter Taylor
źródło
4

Python 3, 747 369 335 bajtów

Jako przykładowa odpowiedź, tylko lekko golfa, i dać ci wyobrażenie, jak będzie wyglądać odpowiedź.

I tak, główne czynniki i bity kodujące długość przebiegu są kopiowane z Pytha z przeprosinami do isaacga .

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
źródło
4
Przeprosiny przyjęte - Cieszę się, że ktoś czyta kod źródłowy Pyth.
isaacg
2

Mathematica, 169 175 165 bajtów

(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
źródło
2

LabVIEW, 44 bajty Prymitywy LabVIEW

Ponieważ jest symetryczny, zamieniłem wejścia, jeśli a było większe niż b.

Reprezentuje teraz prawdziwą formułę

liczenie jak zawsze według

w prawdziwym przypadku

Eumel
źródło
Niestety (a|b) != (b|a)we wszystkich przypadkach. W większości przypadków tak, ale nie we wszystkich. Chociaż zadziałałoby, gdybyś je zmniejszył a mod bzamiast zamienić.
Sherlock9,
skoro mam teraz wyjaśnienie, mogę je edytować, daj mi min
Eumel
1
Czy jest jakiś sposób, żeby to przetestować? Naprawdę nie rozumiem, jak działa LabView.
Sherlock9,
to dobre pytanie, mogę wymyślić 2 sposoby. Po pierwsze mogę zbudować .exe i wysłać go do ciebie, po drugie możesz uzyskać wersję testową labview i mogę ci wysłać vi lub możesz go odbudować z obrazu.
Eumel,
7
To nie jest 44 bajtów. Jeśli zdefiniujesz system oceniania, który nie jest oparty na rozmiarze pliku, powinieneś nazwać go czymś innym niż bajty.
feersum
1

Julia, 195 bajtów

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)))

Jest to funkcja rekurencyjna, kktóra akceptuje dwie liczby całkowite i zwraca liczbę całkowitą.

Nie golfowany:

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.
źródło
1

Haskell, 286 bajtów

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)

Prawdopodobnie nie do końca zoptymalizowany, ale dzielny wysiłek. Symbol Kroneckera jest zdefiniowany jako funkcja infix a # b, tj

*Main>323#455265 
1
zabójca
źródło