실제 숫자 계산


18

정의

양의 정수 n실제 숫자입니다 (OEIS 시퀀스 A005153 ). 모든 작은 양의 정수는 별개의 제수의 합으로 표시 될 수 있습니다 n.

예를 들어, 18실제 숫자입니다. 제수는 1, 2, 3, 6, 9 및 18이며 ​​18보다 작은 양의 정수는 다음과 같이 형성 할 수 있습니다.

 4 = 1 + 3          5 = 2 + 3           7 = 1 + 6
 8 = 2 + 6          10 = 1 + 9         11 = 2 + 9
12 = 3 + 9 = 1 + 2 + 9 = 1 + 2 + 3 + 6
13 = 1 + 3 + 9      14 = 2 + 3 + 9      15 = 6 + 9
16 = 1 + 6 + 9      17 = 2 + 6 + 9

그러나 14실제 숫자는 아닙니다. 제수는 1, 2, 7, 14이며 4, 5, 6, 11, 12 또는 13에 추가되는 하위 집합이 없습니다.

도전

양의 정수를 입력으로 받아 OEIS와의 일관성을 위해 1부터 색인 된 xx 번째 실제 숫자 를 리턴하거나 인쇄 하는 프로그램, 함수 또는 동사를 작성하십시오 . 코드는 합리적인 데스크톱 컴퓨터에서 2 분 이내에 최대 250000 개의 입력을 처리 할 수있을 정도로 효율적이어야합니다. (NB Java 내 참조 구현은 0.5 초 미만으로 250000을 관리하고 Python에서 내 참조 구현은 12 초 안에 그것을 관리합니다).

테스트 사례

Input        Expected output
1            1
8            18
1000         6500
250000       2764000
1000000      12214770
3000000      39258256

(IMHO) 가장 빠른 코드 (언어 당?)가 이기면 흥미로울 수 있습니다
Sarge Borsch

4
@SargeBorsch 그래서 당신은 답변 전체 250K 항목의 표를 볼 수 있습니다
Dr. belisarius

@belisarius 좋은 지적. 하지만 그런 부정 행위는 쉽게 금지 될 수 있다고 생각합니다. 또는 문제는 모든 숫자에 대한 정답이 필요할 수 있지만 표준 라이브러리에서 큰 정수가없는 언어로 수행하는 데 어려움이 있습니다 ... : /
Sarge Borsch

알고리즘 최적화를 염두에두고 있지만 현재 규칙으로는 구현하기에는 너무 게으
릅니다

4
@SargeBorsch, 코드를 골프화하지 않으려면 gist.github.com과 같은 코드에 자유롭게 업로드하고 여기에 의견이나 채팅에 링크를 넣으십시오. FWIW 저는 두 가지 이유로 인해 가장 빠른 코드보다 성능에 제약이 많은 코드 골프를 선호합니다. 첫째, 코드 길이가 더 객관적으로 측정 가능합니다. 둘째, 성능 저하없이 코드를 단축하기 위해 어떤 속도 최적화를 생략 할 수 있는가?
피터 테일러

답변:


5

J (99 자)

f=:3 :0
'n c'=.0 1
while.c<y do.
'p e'=.__ q:n=.n+2
c=.c+*/(}.p)<:}:1+*/\(<:p^e+1)%<:p
end.
n+n=0
)

문제 진술은 "프로그램, 기능 또는 동사를 요구하기 때문에 "를 누군가 J 제출을해야했다. J 사람들은 내가 실제로 골프를하지 않았거나 이것을 최적화하지 않았다는 것을 알 것입니다. 다른 항목과 마찬가지로, OEIS 링크에서 언급 한 Stewart의 정리를 사용하여 각 짝수의 실용 여부를 테스트했습니다.

J가 설치된 "합리적인 데스크톱 컴퓨터"에 액세스 할 수 없습니다. 내 6 살짜리 넷북 f 250000에서 120.6 초 안에 계산하는데, 2 분도 안 걸리지 만 아마도 좀 더 합리적인 컴퓨터에서 시간이 지나면 끝납니다.


6

매쓰, 126 개 121 문자

벨리 사리우스에게 감사합니다.

Wikipedia에서 수식 사용

f=(i=j=1;While[j<#,If[And@@Thread[#[[;;,1]]<2+Most@DivisorSum[FoldList[#Power@@#2&,1,#],#&]&@FactorInteger@++i],j++]];i)&

예 :

f[1]

1

f[8]

18

f[250000]

2764000

f[250000]내 컴퓨터 에서 계산 하는 데 70 대가 걸렸습니다 .


3
홀수 정수를 우회하여 하나의 문자를 사용하여 더 나은 성능을 얻을 수 있다고 생각합니다.
Dr. belisarius

1
OEIS 제출 코드를 줄이면 실행 속도가 10 배 느려집니다. "코드가 OEIS 예제보다 너무 느리게 실행된다고 생각하는 이유는 무엇입니까?"
DavidC

@belisarius 귀하의 제안은 예상대로 시간을 반으로 줄입니다.
DavidC

2
119 자에서 동일 : (i=j=1;While[j<#,If[And@@Thread[#[[;;,1]]<2+Most@DivisorSum[FoldList[#Power@@#2&,1,#],#&]&@FactorInteger@++i],j++]];i)&
Dr. belisarius

3

하스켈-329

s 1=[]
s n=p:(s$div n p)where d=dropWhile((/=0).mod n)[2..ceiling$sqrt$fromIntegral n];p=if null d then n else head d
u=foldr(\v l@((n,c):q)->if v==n then(n,c+1):q else(v,1):l)[(0,1)]
i z=(z<2)||(head w==2)&&(and$zipWith(\(n,_)p->n-1<=p)(tail n)$scanl1(*)$map(\(n,c)->(n*n^c-1)`div`(n-1))n)where w=s z;n=u w
f=((filter i[0..])!!)

예 :

> f 1
1
> f 13
32
> f 1000
6500

다음은 소규모 테스트 스위트입니다 (위에 추가).

import Data.Time.Clock
import System.IO

test x = do
    start <- getCurrentTime
    putStr $ (show x) ++ " -> " ++ (show $ f x)
    finish <- getCurrentTime
    putStrLn $ " [" ++ (show $ diffUTCTime finish start) ++ "]"

main = do
    hSetBuffering stdout NoBuffering
    mapM_ test [1, 8, 1000, 250000, 1000000, 3000000]

다음으로 컴파일 한 후 테스트 결과 ghc -O3:

1 -> 1 [0.000071s]
8 -> 18 [0.000047s]
1000 -> 6500 [0.010045s]
250000 -> 2764000 [29.084049s]
1000000 -> 12214770 [201.374324s]
3000000 -> 39258256 [986.885397s]

내가 ghci에서 이것을 시도하면 그것은 불평한다 parse error on input `='. 깃발이나 다른 깃발을 사용해야합니까?
피터 테일러

1
@PeterTaylor 그런 함수 정의를 ghci에 붙여 넣을 수 없습니다. 당신이 할 수있는 가장 간단한 방법은 저장 asdf.hs하고 실행하는 것입니다 ghci asdf.hs. 그러면 거기에서 액세스 할 수 있습니다f
mniip

@PeterTaylor ghc --make -O3 [filename]. ghci로로드 할 수도 :l [filename]있지만 컴파일 된 시간 제약 조건이 가장 좋습니다. :)
Jonathan Van Matre

위의 주석에서 볼 수 있듯이 ghci
@JonathanVanMatre

그래. 그동안 테스트 프레임 워크 및으로 실행했습니다 ghc. 컴퓨터가 내 컴퓨터보다 빠르지 만 여전히 98 초 내 컴퓨터의 성능 기준 내에 있습니다.
피터 테일러

2

자바 스크립트, 306 307 282B

function y(r){for(n=r-1,k=1;n;k++)if(p=[],e=[],c=0,P=s=1,!((x=k)%2|1==x)){while(x>1){for(f=x,j=2;j<=Math.sqrt(f);j++)if(f%j==0){f=j;break}f!=p[c-1]?(p.push(f),e.push(2),c++):e[c-1]++,x/=f}for(i=0;c>i;i++){if(p[i]>P+1){s=0;break}P*=(Math.pow(p[i],e[i])-1)/(p[i]-1)}s&&n--}return k-1}

약 250k 내 노트북에 6s.

주석 처리되지 않은 코드 : http://jsfiddle.net/82xb9/3/ 이제 더 나은 시그마 테스트 및 더 나은 if 조건을 제공합니다 (주석 감사합니다)

사전 편집 버전 : http://jsfiddle.net/82xb9/ http://jsfiddle.net/82xb9/1/


질문은 함수 또는 프로그램을 요구하므로 (JS에는 동사가 없음) 첫 번째 줄을 계산하지 않고 함수 선언에서 두 번째 줄을 감싸고 마지막을 k--;로 바꿔야합니다 return k-1. 이렇게하면 바이트 수가 약간 증가하지만 대체 (및 내부 함수 호출 제거 ​​및 대신 사용) p[i]>=P+2와 같은 몇 가지를 저장할 수 있습니다 . p[i]>P+1break
피터 테일러

둘 다 크기와 속도를 재 작성 할 수 있습니다 부분 "시그마 테스트"생각 : jsfiddle.net/3DTSa를 . 이 JS 솔루션은 매우 빠르지 만.
user2846289
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.