Рассчитать символ Кронекера

9

Соответствующие ссылки здесь и здесь , но вот краткая версия:

У вас есть входные данные двух целых чисел aи bмежду отрицательной бесконечностью и бесконечностью (хотя при необходимости я могу ограничить диапазон, но функция все равно должна принимать отрицательные входные данные).

Определение символа Кронекера

Вы должны вернуть символ Кронекера (a|b)для ввода aи bгде

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

где b = p_1^e_1 * p_2^e_2 * ... * p_n^e_n, и p_iи e_iявляются простыми числами и показателями в основной факторизации b.

Для нечетного простого числа p, (a|p)=a^((p-1)/2) (mod p)как определено здесь .

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

Для b == -1,(n|-1)={-1 for n<0; 1 for n>0

Если a >= b, (a|b) == (z|b)где z == a % b. Этим свойством и, как объясняется здесь и здесь , aявляется квадратичный остаток от bif z, хотя a >= b.

(-1|b)= 1если b == 0,1,2 (mod 4)и -1если b == 3 (mod 4). (0|b)является , 0за исключением (0|1)что 1, потому что (a|1)всегда 1и для отрицательных a, (-a|b) == (-1|b) * (a|b).

Вывод символа Кронекера всегда -1, 0 or 1, где вывод, 0если aи bимеют какие-либо общие факторы. If b- нечетное простое число, (a|b) == 1if a- квадратичный вычет mod b, а -1if - это не квадратичный вычет.

правила

  • Ваш код должен быть программой или функцией.

  • Входы должны быть в порядке a b.

  • Выход должен быть либо -1, 0либо 1.

  • Это кодовый гольф, поэтому ваш код не обязательно должен быть эффективным, просто коротким.

  • Нет встроенных модулей, которые напрямую вычисляют Кронекера или связанные символы Якоби и Лежандра. Другие встроенные модули (например, для первичной факторизации) являются честной игрой.

Примеры

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

Это сложная функция, поэтому, пожалуйста, дайте мне знать, если что-то неясно.

Sherlock9
источник
Вы уверены, что не хотите запретить встроенные модули? reference.wolfram.com/language/ref/KroneckerSymbol.html
Мартин Эндер,
@ MartinBüttner Я редактировал примеры, когда увидел твой комментарий. Я не позволю встроенным модулям, которые напрямую вычисляют символы Кронекера, Якоби или Лежандра, но все остальное (включая основные функции факторизации) должно быть честной игрой.
Sherlock9
Я не совсем уверен, почему (31 | 5) дает 1. Не должно быть квадратичного остатка, так почему же это не -1?
Eumel
также 7/19 должно быть 1, а 19/7 должно быть -1 в соответствии с вашей вики
Eumel
3
Если решения должны корректно обрабатывать отрицательные и нулевые входные данные, вы должны обязательно добавить для этого несколько тестов.
Мартин Эндер

Ответы:

2

CJam (70 байт)

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

Демо онлайн (тестовые случаи, созданные с помощью Mathematica).

рассечение

{               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)для одного и того же количества символов, и решил использовать тот, который дает наиболее четкое представление.

integer array <W= Это IMO довольно элегантный способ сделать запасные варианты: если целое число больше, чем длина массива, мы выбираем последний элемент.

Другие комментарии

Вызывает разочарование то, что для нечетного прайма pпрямой стиль Ферма (a|p)настолько короток, потому что есть очень хороший способ найти (a|n)положительный вариант, nкоторый я хотел использовать. Основой является лемма Золотарева:

Если pнечетное простое aчисло и взаимно простое число, pто символ Лежандра (a|p)является знаком перестановки.x -> ax (mod p)

Это было усилено Фробениусом, чтобы

Если aи bявляются взаимно простыми положительными нечетными целыми числами, то символ Якоби (a|b)является знаком перестановкиx -> ax (mod b)

и Лерх к

Если bявляется положительным нечетным целым числом и aявляется целочисленным взаимно простым, bто символ Якоби (a|b)является знаком перестановкиx -> ax (mod b)

См. Brunyate and Clark, Расширение подхода Золотарева-Фробениуса к квадратичной взаимности , Ramanujan Journal 37.1 (2014): 25-50 для ссылок.

И это может быть легко укреплено еще на один шаг (хотя я не видел этого в литературе), чтобы

Если bположительное нечетное целое число и aцелое число, то символ Якоби (a|b)является символом Леви-Чивиты карты x -> ax (mod b).

Доказательство: если aвзаимно, bто мы используем Золотарева-Фробениуса-Лерха; в противном случае карта не является перестановкой, и символ Леви-Чивита является 0желаемым.

Это дает вычисление символа Якоби

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

Но особая обработка требует (a|-1)и (a|2)означает, что я не нашел способ вычисления символа Кронекера, который короче при таком подходе: он короче для разложения и обработки простых чисел индивидуально.

Питер Тейлор
источник
4

Python 3, 747 369 335 байт

В качестве примера ответ, только слегка гольф, и дать вам представление о том, как ответ будет выглядеть.

И да, основные биты факторизации и кодирования длин серий написаны Pyth с извинениями за 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
источник
4
Извинения приняты - я рад, что кто-то читает исходный код Pyth.
Исаак
2

Mathematica, 169 175 165 байтов

(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
источник
2

LabVIEW, 44 байта Примитивы LabVIEW

Поскольку он симметричный, я поменял местами входы, если a было больше, чем b.

Представляет реальную формулу сейчас

считая как всегда согласно

для истинного случая

Eumel
источник
К сожалению, (a|b) != (b|a)во всех случаях. В большинстве случаев да, но не во всех. Хотя это будет работать, если вы уменьшите их a mod bвместо того, чтобы поменять их местами.
Sherlock9
так как у меня есть объяснение, теперь я могу его отредактировать, дайте мне минус
Eumel
1
Есть ли способ проверить это? Я не очень понимаю, как работает LabView.
Sherlock9
это хороший вопрос, я могу придумать 2 пути. Во-первых, я могу создать .exe и отправить его вам, во-вторых, вы можете получить тестовую версию labview и я могу выслать вам vi или вы можете пересобрать его с картинки.
Eumel
7
Это не 44 байта. Если вы определяете систему оценки, которая не основана на размере файла, вы должны называть это как-то иначе, чем в байтах.
feersum
1

Юлия, 195 байт

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

Это рекурсивная функция, kкоторая принимает два целых числа и возвращает целое число.

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 байт

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)

Вероятно, не полностью оптимизирован, но отважные усилия. Символ Кронекера определяется как инфиксная функция a # b, т.е.

*Main>323#455265 
1
killmous
источник