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.


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.


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

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)

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


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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.