Tính số thực tế


18

Định nghĩa

Một số nguyên dương nlà một số thực tế (chuỗi OEIS A005153 ) nếu tất cả các số nguyên dương nhỏ hơn có thể được biểu diễn dưới dạng tổng của các ước số riêng biệt của n.

Ví dụ, 18là một số thực tế: các ước của nó là 1, 2, 3, 6, 9 và 18, và các số nguyên dương khác nhỏ hơn 18 có thể được hình thành như sau:

 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

Nhưng 14không phải là một con số thực tế: các ước số của nó là 1, 2, 7 và 14, và không có tập hợp con nào trong số này thêm vào 4, 5, 6, 11, 12 hoặc 13.

Thử thách

Viết chương trình, hàm hoặc động từ lấy đầu vào là số nguyên dương xvà trả về hoặc in số thực tế thứ x , được lập chỉ mục từ 1 để thống nhất với OEIS. Mã của bạn phải đủ hiệu quả để có thể xử lý các đầu vào lên tới 250000 trong vòng chưa đầy hai phút trên một máy tính để bàn hợp lý. (NB triển khai tham chiếu của tôi trong Java quản lý 250000 trong chưa đầy 0,5 giây và triển khai tham chiếu của tôi trong Python quản lý nó trong 12 giây).

Các trường hợp thử nghiệm

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

(IMHO) điều này thậm chí có thể di chuyển thú vị nếu mã nhanh nhất (theo ngôn ngữ?) Giành chiến thắng
Sarge Borsch

4
@SargeBorsch Vì vậy, bạn sẽ thấy các bảng gồm 250K mục trên tất cả các câu trả lời
Tiến sĩ belisarius

@ Belisarius điểm tốt. nhưng tôi nghĩ gian lận như vậy có thể dễ dàng bị cấm. Hoặc vấn đề có thể yêu cầu câu trả lời đúng cho bất kỳ số nào , nhưng sau đó sẽ gặp khó khăn khi thực hiện bằng ngôn ngữ không có số nguyên lớn trong thư viện chuẩn ...: /
Sarge Borsch

Tôi có một ý tưởng tối ưu hóa thuật toán, nhưng với các quy tắc hiện tại, tôi quá lười để thực hiện nó: P
Sarge Borsch

4
@SargeBorsch, nếu bạn không muốn chơi mã của mình, vui lòng tải nó lên một cái gì đó như gist.github.com và thả một liên kết trong một nhận xét ở đây hoặc trong trò chuyện. FWIW Tôi thích chơi golf mã với các ràng buộc hiệu suất hào phóng với mã nhanh nhất vì hai lý do: thứ nhất, độ dài của mã có thể đo lường khách quan hơn; thứ hai, nó giới thiệu một yếu tố của sự đánh đổi: những tối ưu hóa tốc độ nào có thể bị bỏ qua để rút ngắn mã mà không làm hỏng hiệu suất?
Peter Taylor

Câu trả lời:


5

J (99 ký tự)

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
)

Vì tuyên bố vấn đề yêu cầu "chương trình, chức năng hoặc động từ ", nên ai đó đã phải nộp J. Mọi người sẽ nhận thấy tôi không thực sự chơi golf (!) Hoặc tối ưu hóa điều này. Giống như các mục khác, tôi đã sử dụng định lý của Stewart, được đề cập tại liên kết OEIS, để kiểm tra xem mỗi số chẵn có thực tế hay không.

Tôi chưa sẵn sàng truy cập vào "máy tính để bàn hợp lý" có cài đặt J. Trên chiếc netbook sáu năm tuổi của tôi f 250000tính toán trong 120,6 giây, không hoàn toàn dưới hai phút, nhưng có lẽ trên bất kỳ máy tính nào hợp lý hơn một chút, điều này sẽ kết thúc đúng lúc.


6

Toán học, 126 121 ký tự

Cảm ơn belisarius.

Sử dụng công thức trên wikipedia.

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

Ví dụ:

f[1]

1

f[8]

18

f[250000]

2764000

Phải mất 70 giây để tính toán f[250000]trên máy tính của tôi.


3
Tôi nghĩ rằng bạn có thể có được hiệu suất tốt hơn với chi phí của một char bằng cách bỏ qua các số nguyên lẻ
Tiến sĩ belisarius

1
Khi giảm mã từ trình OEIS, bạn đã làm chậm quá trình thực thi 10 lần. Chỉ tự hỏi, "tại sao bạn nghĩ mã của bạn chạy chậm hơn nhiều so với ví dụ OEIS?"
DavidC

@ Belisarius Đề xuất của bạn giảm thời gian xuống một nửa, như mong đợi.
DavidC

2
Điều tương tự trong 119 ký tự:(i=j=1;While[j<#,If[And@@Thread[#[[;;,1]]<2+Most@DivisorSum[FoldList[#Power@@#2&,1,#],#&]&@FactorInteger@++i],j++]];i)&
Tiến sĩ belisarius

3

Haskell - 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..])!!)

Ví dụ:

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

Đây là một bộ thử nghiệm nhỏ (thêm vào phần trên):

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]

Kết quả kiểm tra sau khi được biên dịch với 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]

Khi tôi thử điều này trong ghci nó phàn nàn parse error on input `='. Tôi có cần sử dụng một số cờ hoặc khác?
Peter Taylor

1
@PeterTaylor Bạn không thể dán định nghĩa hàm vào ghci như thế. Đơn giản nhất bạn có thể làm là lưu nó vào asdf.hsvà chạy ghci asdf.hs, sau đó từ đó bạn sẽ có thể truy cậpf
mniip

@PeterTaylor ghc --make -O3 [filename]. Bạn cũng có thể tải nó trong ghci :l [filename]nhưng với các ràng buộc về thời gian được biên dịch có lẽ là tốt nhất. :)
Jonathan Van Matre

@JonathanVanMatre như đã thấy trong nhận xét trên, ghcitải các tệp được chỉ định trong các đối số của nó
mniip

À, được rồi Trong khi đó, tôi đã có nó chạy với khung thử nghiệm của bạn và ghc. Máy tính của bạn nhanh hơn máy tính của tôi, nhưng nó vẫn nằm trong tiêu chí hiệu suất trên máy tính của tôi ở mức 98 giây.
Peter Taylor

2

Javascript, 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 trong khoảng. 6s trên máy tính xách tay của tôi.

Đã nhận xét mã không được đánh gôn: http://jsfiddle.net/82xb9/3/ ngay bây giờ với thử nghiệm sigma tốt hơn và tốt hơn nếu có điều kiện (cảm ơn bạn đã bình luận)

Phiên bản chỉnh sửa trước: http://jsfiddle.net/82xb9/ http://jsfiddle.net/82xb9/1/


Câu hỏi yêu cầu một chức năng hoặc chương trình (JS không có động từ), vì vậy thay vì không tính dòng đầu tiên, bạn nên bọc dòng thứ hai trong khai báo hàm và thay thế cuối cùng k--;bằng return k-1. Mặc dù điều đó làm tăng số byte của bạn một chút, bạn có thể tiết kiệm một vài thứ bằng cách thay thế p[i]>=P+2bằng p[i]>P+1(và có thể bằng cách loại bỏ lệnh gọi hàm bên trong và sử dụng breakthay thế).
Peter Taylor

Tôi nghĩ phần "sigma thử nghiệm" có thể được viết lại cho cả kích thước và tốc độ: jsfiddle.net/3DTSa . Mặc dù giải pháp JS này rất nhanh.
dùng2846289
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.