Pyth, 83 82 바이트
=eAQM.^GHQKf%=/H=2;1=gftgT/Q;1HJg~gGHh/H2WtG=*J=gT^2t-K=Kfq1gG^2T1=%*G=^T2Q;hS%_BJ
테스트 스위트
이 프로그램은 Tonelli-Shanks 알고리즘을 구현합니다 . 나는 Wikipedia 페이지를 꼼꼼히 따랐다. 입력으로 사용 (n, p)
됩니다.
제곱근이 없으면 다음 오류로보고됩니다.
TypeError: pow() 3rd argument not allowed unless all arguments are integers
이것은 Pyth의보다 일반적인 기능적 스타일과 달리 명령형으로 작성된 매우 복잡한 코드입니다.
내가 사용 =
하고있는 Pyth의 미묘한 측면은 바로 다음에 변수가 나오지 않으면 프로그램에서 다음 변수를 검색 한 다음 다음 표현식의 결과를 해당 변수에 할당 한 다음 결과를 반환합니다. 설명을 통해 Wikipedia 페이지 인 Tonelli-Shanks algorithm 을 참조 할 것입니다. 이것이 구현중인 알고리즘입니다.
설명:
=eAQ
A
입력으로서 2- 터플을 취하고,에 값을 할당 G
하고 H
, 각각, 그 입력을 반환한다. Q
초기 입력입니다. e
시퀀스의 마지막 요소를 반환합니다. 이 스 니펫 다음 G
은 is n
및 H
and Q
입니다 p
.
M.^GHQ
M
g
입력이 G
및 인 2 입력 함수를 정의합니다 H
. .^
Pyth의 빠른 모듈 식 지수 함수입니다. 이 스 니펫은 g
지수 모드를 의미하도록 정의 합니다 Q
.
Kf%=/H=2;1
f
false 루프까지 반복을 정의 1
하고 입력으로 지정된 반복 횟수를 리턴합니다 . 루프가 반복 될 때마다 H
2로 나누고 H
그 값으로 설정 한 후 결과가 홀수인지 확인합니다. 일단 끝나면 우리는 멈 춥니 다.K
이 반복 횟수를 저장합니다.
매우 까다로운 것은 =2;
비트입니다. =
다음 변수 인을 검색합니다. 즉 T
, T
2로 설정됩니다. 그러나 루프 T
내부 f
에는 반복 카운터가 있으므로 전역 환경에서 ;
값을 가져 오는 데 사용 T
합니다. 이것은 숫자를 분리하는 데 필요한 몇 바이트의 공백을 저장하기 위해 수행됩니다.
이 조각 한 후, K
인 S
위키 피 디아 기사 (위키)에서하고 H
있다 Q
위키에서하고 T
있습니다 2
.
=gftgT/Q;1H
이제 2 차 비 잔류 모드를 찾아야합니다 p
. Euler 기준을 사용하여 이것을 무차별 적용 할 것입니다. /Q2
이다 (p-1)/2
때문에, /
바닥의 분할이며, 그래서 ftgT/Q;1
제 정수 찾으면 원하는를. 리콜 다시 끌어 여전히이 결과 2 인 글로벌 환경에서는 위키에서.T
T ^ ((p-1)/2) != 1
;
T
z
다음으로 c
위키에서 생성 하려면을 필요 z^Q
로하므로 위의 내용을 감싸서 g ... H
결과를에 할당합니다 T
. 이제 T
입니다 c
위키에서.
Jg~gGHh/H2
이것을 분리하자 : ~gGH
. ~
와 =
같지만 새 값이 아닌 변수의 원래 값을 반환합니다. 따라서을 반환합니다 G
.n
위키에서.
이 할당 J
의 값 n^((Q+1)/2)
이며, R
위키에서합니다.
이제 다음이 적용됩니다.
~gGH
이 할당 G
값 n^Q
이며, t
위키에서합니다.
이제 루프 변수가 설정되었습니다. M, c, t, R
위키에서 K, T, G, J
입니다.
루프의 몸체는 복잡하므로 공백을 쓴 방식으로 제시합니다.
WtG
=*J
=
gT^2
t-
K
=Kfq1gG^2T1
=%*G=^T2Q;
먼저 1인지 확인합니다 G
. 그렇다면 루프를 종료합니다.
다음으로 실행되는 코드는 다음과 같습니다.
=Kfq1gG^2T1
여기, 우리의 첫 번째 값을 검색 i
등 그 G^(2^i) mod Q = 1
결과는 저장 1.부터 시작 K
.
=gT^2t-K=Kfq1gG^2T1
여기서 우리는 이전 값인 K
, 새로운 값 K
빼기, 1 빼기, 2를 그 거듭 제곱으로 올린 다음 T
그 거듭 제곱 모드 로 올린 Q
다음 결과를에 할당합니다 T
. 이것은 위키와 T
동일합니다 b
.
또한이 경우에 새로운 값이 있기 때문에, 루프를 종료하고, 솔루션이 없을 경우 실패 라인 K
의 이전 값과 같아야한다 K
받는 발생한다 (2), -1
및 모듈러 지수화는 에러를 발생한다.
=*J
다음으로, 우리는 다중 J
위의 결과에 의해 다음 다시 보관 J
유지, R
업데이트되었습니다.
=^T2
그런 다음 Wiki에서 다시 설정 T
하여 결과를 정사각형 으로 저장합니다 .T
T
c
=%*G=^T2Q
그런 다음 G
그 결과를 곱하고 mod를 가져 와서 Q
결과를 다시 저장합니다 G
.
;
그리고 우리는 루프를 종료합니다.
루프가 끝나면 mod의 J
제곱근입니다 . 가장 작은 것을 찾으려면 다음 코드를 사용하십시오.n
p
hS%_BJ
_BJ
목록 J
과 해당 부정을 작성하고 %
내재적 Q
으로 두 번째 인수로 사용하며 Pyth의 기본 동작을 사용 % ... Q
하여 시퀀스의 각 구성원에 적용 합니다. 그런 다음 S
목록을 정렬 h
하고 첫 번째 구성원 인 최소값을 가져옵니다.