정규식 (ECMAScript), 131 바이트
Deadcode 덕분에 최소한 -12 바이트 (채팅 중)
(?=((xx+)(?=\2+$)|x+)+)(?=((x*?)(?=\1*$)(?=(\4xx+?)(\5*(?!(xx+)\7+$)\5)?$)(?=((x*)(?=\5\9*$)x)(\8*)$)x*(?=(?=\5$)\1|\5\10)x)+)\10|x
온라인으로 사용해보십시오!
출력은 일치하는 길이입니다.
ECMAScript 정규식은 무엇이든 계산하기가 매우 어렵습니다. 루프 외부에 정의 된 모든 역 참조는 루프 동안 일정하며 루프 내부에 정의 된 모든 역 참조는 반복 할 때 재설정됩니다. 따라서 루프 반복에서 상태를 전달하는 유일한 방법은 현재 일치 위치를 사용하는 것입니다. 그것은 하나의 정수이고, 그것은 단지 감소 할 수 있습니다 (글쎄, 위치는 증가하지만 꼬리의 길이는 감소하며 이것이 우리가 수학 할 수있는 것입니다).
이러한 제한을 감안할 때 단순히 코 프림 수를 계산하는 것은 불가능한 것 같습니다. 대신에, 우리는 Euler의 공식 을 사용하여 계급을 계산합니다.
의사 코드에서 다음과 같이 표시됩니다.
N = input
Z = largest prime factor of N
P = 0
do:
P = smallest number > P that’s a prime factor of N
N = N - (N / P)
while P != Z
return N
이것에 대해 두 가지 모호한 점이 있습니다.
먼저 입력을 저장하지 않고 현재 제품 만 저장하므로 입력의 주요 요소를 어떻게 얻을 수 있습니까? 비결은 (N-(N / P))에 N과 같은 소인수> P가 있다는 것입니다. 새로운 소인수 <P를 얻을 수도 있지만 어쨌든 무시합니다. 우리는 가장 작은 것에서 가장 큰 것까지 주요 요소를 반복하고 다른 방법으로는 실패하기 때문에 작동합니다.
둘째, 루프 반복에서 두 개의 숫자를 기억해야합니다 (P와 N, Z는 상수이므로 계산하지 않습니다). 고맙게도이 두 숫자를 하나의 숫자로 쓸어 넘길 수 있습니다. 루프가 시작될 때 N은 항상 Z의 배수이고 P는 항상 Z보다 작습니다. 따라서 N + P를 기억하고 모듈로 P를 추출 할 수 있습니다.
약간 더 자세한 의사 코드는 다음과 같습니다.
N = input
Z = largest prime factor of N
do:
P = N % Z
N = N - P
P = smallest number > P that’s a prime factor of N
N = N - (N / P) + P
while P != Z
return N - Z
주석이 달린 정규식은 다음과 같습니다.
# \1 = largest prime factor of N
# Computed by repeatedly dividing N by its smallest factor
(?= ( (xx+) (?=\2+$) | x+ )+ )
(?=
# Main loop!
(
# \4 = N % \1, N -= \4
(x*?) (?=\1*$)
# \5 = next prime factor of N
(?= (\4xx+?) (\5* (?!(xx+)\7+$) \5)? $ )
# \8 = N / \5, \9 = \8 - 1, \10 = N - \8
(?= ((x*) (?=\5\9*$) x) (\8*) $ )
x*
(?=
# if \5 = \1, break.
(?=\5$) \1
|
# else, N = (\5 - 1) + (N - B)
\5\10
)
x
)+
) \10
그리고 보너스로…
정규식 (ECMAScript 2018, 일치 수), 23 바이트
x(?<!^\1*(?=\1*$)(x+x))
온라인으로 사용해보십시오!
출력은 일치 횟수입니다. ECMAScript 2018에서는 가변 길이 룩-비하인드 (오른쪽에서 왼쪽으로 평가됨)를 사용하여 입력과 함께 모든 숫자를 함께 계산할 수 있습니다.
이것은 독립적으로 Leaky Nun의 Retina 솔루션 에서 사용하는 것과 동일한 방법 이며, 정규식도 같은 길이 ( 및 상호 교환 가능 )입니다. 이 방법이 ECMAScript 2018 (.NET뿐만 아니라)에서도 작동하는 것이 흥미로울 수 있으므로 여기에 남겨 두겠습니다.
# Implicitly iterate from the input to 0
x # Don’t match 0
(?<! ) # Match iff there is no...
(x+x) # integer >= 2...
(?=\1*$) # that divides the current number...
^\1* # and also divides the input