実用的な数値を計算する


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からインデックス付けされxたx 番目の実用的な数値を返すか出力するプログラム、関数、または動詞を記述します。コードは、合理的なデスクトップコンピューターで2分未満で最大250000の入力を処理できるように十分に効率的でなければなりません。(注:Javaの私のリファレンス実装は0.5秒未満で250000を管理し、Pythonの私のリファレンス実装は12秒で管理します)。

テストケース

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

(私見)最速のコードが(言語ごと?)勝てば、これが面白い移動してもすることができます
Sargeのボルシチ

4
@SargeBorschそのため、すべての回答にわたって
25万

@belisarius良い点。しかし、そのような不正行為は簡単に禁止されると思います。または、問題には任意の数の正解が必要な場合がありますが、標準ライブラリに大きな整数がない言語でそれを行う場合は困難があります...:/
Sarge Borsch 14年

アルゴリズムの最適化を念頭に置いていますが、現在のルールでは実装するのが
Sarge Borsch 14年

4
@SargeBorsch、ゴルフをしたくない場合は、コードをgist.github.comのようなものにアップロードして、ここにコメントまたはチャットでリンクをドロップしてください。FWIW次の2つの理由から、最速のコードよりも寛大なパフォーマンス制約のあるコードゴルフを好みます。第1に、コードの長さがより客観的に測定可能です。次に、トレードオフの要素を導入します。パフォーマンスを損なうことなくコードを短縮するために、どの速度の最適化を省略できますか?
ピーターテイラー14年

回答:


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リンクで言及したスチュワートの定理を使用して、各偶数が実用的かどうかをテストしました。

Jがインストールされた「合理的なデスクトップコンピューター」にすぐにアクセスできません。私の6年前のネットブックf 250000では120.6秒で計算しますが、これは2分未満ではありませんが、おそらく少し合理的なコンピューターではこれで間に合います。


6

Mathematicaの、126の 121文字

ベリサリウスに感謝します。

ウィキペディアで数式を使用します。

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
私はあなたが奇数の整数をバイパスして1つの文字を犠牲にしてより良いパフォーマンスを得ることができると思う
博士ベリサリウス

1
OEIS提出からのコードを減らすことで、実行を10倍遅くしました。「コードの実行がOEISの例よりもずっと遅いと思うのはなぜですか?」
DavidC 14年

@belisariusあなたの提案は、予想通り、時間を半分に短縮します。
DavidC 14年

2
119文字で同じ:(i=j=1;While[j<#,If[And@@Thread[#[[;;,1]]<2+Most@DivisorSum[FoldList[#Power@@#2&,1,#],#&]&@FactorInteger@++i],j++]];i)&
ベリサリウス博士14年

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]、コンパイルされた時間の制約を考えるとおそらく最良です。:)
ジョナサンヴァンマトレ14年

上記のコメントに見られるよう@JonathanVanMatreは、ghci負荷のファイルは、引数で指定された
mniip

ああ、わかった。それまでは、テストフレームワークとで実行していますghc。お使いのコンピューターは私のコンピューターよりも高速ですが、それでも98秒の時点でコンピューターのパフォーマンス基準の範囲内に収まっています。
ピーターテイラー14年

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 ラップトップで6秒。

ゴルフされていないコードのコメント:http : //jsfiddle.net/82xb9/3/のシグマテストとif条件の改善(コメントありがとう)

事前編集バージョン:http : //jsfiddle.net/82xb9/ http://jsfiddle.net/82xb9/1/


質問は関数またはプログラムを要求します(JSには動詞はありません)。したがって、最初の行をカウントしないのではなく、関数宣言で2行目をラップし、final k--;をに置き換える必要がありreturn k-1ます。これによりバイトカウントがわずかに増加しますがp[i]>=P+2p[i]>P+1(たとえば、おそらく内部関数呼び出しを削除してbreak代わりにaを使用することで)を置き換えるなどの方法でいくつかを節約できます。
ピーターテイラー14年

「testing sigma」の部分は、サイズと速度の両方でjsfiddle.net/3DTSaに書き換えることができると思います。ただし、このJSソリューションは非常に高速です。
user2846289 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.