Kronecker sembolünü hesapla


9

Burada ve burada alakalı bağlantılar , ancak kısa sürüm:

İki tamsayı var ave bnegatif sonsuzluk ile sonsuzluk arasında bir giriş var (gerekirse, aralığı sınırlayabilirim, ancak işlev yine de negatif girişleri kabul etmelidir).

Kronecker sembolünün tanımı

Sen Kronecker sembolünü geri dönmelidir (a|b)girişler için aveb

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

nerede b = p_1^e_1 * p_2^e_2 * ... * p_n^e_nve p_ive e_iasal çarpanlarına ayırmanın asalları ve üsleri b.

Garip bir asal için p, (a|p)=a^((p-1)/2) (mod p)olarak tanımlanır burada .

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

İçin b == -1,(n|-1)={-1 for n<0; 1 for n>0

Eğer a >= b, (a|b) == (z|b)nerede z == a % b. Açıklandığı gibi bu özellik ile, ve burada ve burada , abir kuadratik kalan ise beğer zrağmen olduğunu a >= b.

(-1|b)= 1if b == 0,1,2 (mod 4)ve -1if b == 3 (mod 4). (0|b)olduğu 0haricinde (0|1)hangi 1çünkü (a|1)her zaman 1ve negatif için a, (-a|b) == (-1|b) * (a|b).

Kronecker sembolünün çıktı daima -1, 0 or 1çıkış olduğu, 0eğer ave bherhangi bir ortak faktörler vardır. Eğer b, bir tek asal olup (a|b) == 1olmadığını abir olduğunu kuadratik kalan mod bve -1eğer bu bir kuadratik kalan değil.

kurallar

  • Kodunuz bir program veya işlev olmalıdır.

  • Girişler sırayla olmalıdır a b.

  • Çıkış ya olmalıdır -1, 0ya da 1.

  • Bu kod golf, bu nedenle kodunuzun verimli olması gerekmez, sadece kısa.

  • Doğrudan Kronecker veya ilgili Jacobi ve Legendre sembollerini hesaplayan yerleşik yapı yoktur. Diğer yerleşikler (örneğin asal çarpanlara ayırma için) adil oyundur.

Örnekler

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

Bu karmaşık bir işlev, bu yüzden net olmayan bir şey varsa lütfen bana bildirin.


Yerleşik yapılara izin vermek istemediğinizden emin misiniz? reference.wolfram.com/language/ref/KroneckerSymbol.html
Martin Ender

@ MartinBüttner Yorumunuzu görünce örneklerde düzenleme yapıyordum. Kronecker, Jacobi veya Legendre sembollerini doğrudan hesaplayan yerleşiklere izin vermeyeceğim, ancak başka bir şey (asal çarpanlara ayırma işlevleri dahil) adil bir oyun olmalı.
Sherlock9

im (31 | 5) neden 1 verdiğinden tam olarak emin değilim. İkinci dereceden bir kalıntı olmamalı, neden -1 değil?
Eumel

Ayrıca, bağladığınız wiki'ye göre 7/19 1 ve 19/7 -1 olmalıdır
Eumel

3
Çözümlerin negatif ve sıfır girişleri doğru şekilde işlemesi gerekiyorsa, bunun için kesinlikle bazı test senaryoları eklemelisiniz.
Martin Ender

Yanıtlar:


2

CJam (70 bayt)

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

Çevrimiçi demo (Mathematica ile oluşturulan test senaryoları).

teşrih

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

(a|2)Aynı karakter sayısını değerlendirmenin birkaç yolunu buldum ve en net sunumla olanı kullanmayı seçtim.

integer array <W= IMO, yedek yapmanın oldukça zarif bir yoludur: tamsayı dizinin uzunluğundan büyükse, son öğeyi seçeriz.

Diğer yorumlar

Garip prime piçin doğrudan Fermat stilinin (a|p)çok kısa olması hayal kırıklığı yaratıyor , çünkü kullanmak istediğim (a|n)pozitif tuhaflığı bulmanın çok golfik bir yolu var n. Temel Zolotarev'in lemmasıdır:

Eğer ptuhaf abir asalsa ve tamsayı bir tamsayı pise Legendre sembolü (a|p)permütasyonun işaretidirx -> ax (mod p)

Bu Frobenius tarafından

Eğer ave baralarında asal pozitif tek tam sayılardır sonra Jacobi sembolü (a|b)permütasyon işaretidirx -> ax (mod b)

ve Lerch tarafından

Eğer bbir pozitif tek tamsayı ve abir tamsayı aralarında asal olduğu bo Jacobi sembol (a|b)permütasyon işaretidirx -> ax (mod b)

Bakınız Brunyate ve Clark, Zolotarev-Frobenius yaklaşımını ikinci dereceden karşılıklılığa genişletme, referanslar için Ramanujan Journal 37.1 (2014): 25-50.

Ve (literatürde görmemiş olmama rağmen) bir adım daha kolayca güçlendirilebilir

Eğer bbir pozitif tek tamsayı ve abir tam sayıdır sonra Jacobi sembolü (a|b)haritanın Levi-Civita sembolü olduğunu x -> ax (mod b).

İspat: eğer abir coprime ise bZolotarev-Frobenius-Lerch kullanırız; aksi halde harita bir permütasyon değildir ve Levi-Civita sembolü 0istenildiği gibidir.

Bu Jacobi sembolü hesaplamasını verir

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

Ancak, gerekli olan (a|-1)ve (a|2)bu yaklaşımla daha kısa olan Kronecker sembolünü hesaplamanın bir yolunu bulamadığım anlamına gelir ve primerleri ayrı ayrı çarpanlara ayırmak ve tedavi etmek daha kısadır.


4

Piton 3, 747 369 335 bayt

Örnek bir cevap olarak, sadece hafifçe golf oynadı ve bir cevabın nasıl görüneceğine dair bir fikir vermek.

Ve evet, birincil çarpanlara ayırma ve çalışma uzunluğu kodlama bitleri Pyth'ten isaacg'a özür diler .

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
Özür kabul edildi - Birisinin Pyth kaynak kodunu okumasına sevindim.
isaacg

2

Mathematica, 169 175 165 bayt

(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 Bayt LabVIEW Temel Öğeleri

Simetrik olduğundan, b'den büyükse girişleri değiştirdim.

Şimdi gerçek formülü temsil eder

her zamanki gibi saymak

gerçek dava için


Ne yazık ki, (a|b) != (b|a)her durumda. Çoğu durumda, evet, ama hepsinde değil. Gerçi a mod bonları değiştirmek yerine azalttıysanız işe yarayacaktır.
Sherlock9

Ben şimdi açıklama var beri düzenleyebilir, bana bir dak vermek
Eumel

1
Bunu test edebilmemin bir yolu var mı? LabView'un nasıl çalıştığını gerçekten anlamıyorum.
Sherlock9

bu iyi bir soru, 2 yol düşünebilirim. İlk önce bir .exe oluşturabilir ve size gönderebilir, ikinci olarak bir labview test sürümü alabilir ve size vi gönderebilir veya pic'den yeniden oluşturabilirsiniz.
Eumel

7
Bu 44 bayt değil. Dosyanın boyutuna göre olmayan bir puanlama sistemi tanımlarsanız, bunu bayt dışında bir şey olarak adlandırmalısınız.
feersum

1

Julia, 195 bayt

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

Bu, kiki tamsayıyı kabul eden ve bir tam sayı döndüren özyinelemeli bir işlevdir .

Ungolfed:

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 bayt

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)

Muhtemelen tamamen optimize edilmemiş, cesur bir çaba. Kronecker sembolü a # b infix fonksiyonu olarak tanımlanır, yani

*Main>323#455265 
1
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.