Scala 263文字
新しい要件に合わせて更新されました。コードの25%は、以下の素数を計算するための合理的な上限を見つけることに対処しています。
object P extends App{
def c(M:Int)={
val p=collection.mutable.BitSet(M+1)
p(2)=true
(3 to M+1 by 2).map(p(_)=true)
for(i<-p){
var j=2*i;
while(j<M){
if(p(j))p(j)=false
j+=i}
}
p
}
val i=args(0).toInt
println(c(((math.log(i)*i*1.3)toInt)).take(i).mkString("\n"))
}
ふるいももらった。
以下は、分析のために計算されていない計算コストの実証的テストです。
object PrimesTo extends App{
var cnt=0
def c(M:Int)={
val p=(false::false::true::List.range(3,M+1).map(_%2!=0)).toArray
for (i <- List.range (3, M, 2)
if (p (i))) {
var j=2*i;
while (j < M) {
cnt+=1
if (p (j))
p(j)=false
j+=i}
}
(1 to M).filter (x => p (x))
}
val i = args(0).toInt
/*
To get the number x with i primes below, it is nearly ln(x)*x. For small numbers
we need a correction factor 1.13, and to avoid a bigger factor for very small
numbers we add 666 as an upper bound.
*/
val x = (math.log(i)*i*1.13).toInt+666
println (c(x).take (i).mkString("\n"))
System.err.println (x + "\tcount: " + cnt)
}
for n in {1..5} ; do i=$((10**$n)); scala -J-Xmx768M P $i ; done
次のカウントにつながります:
List (960, 1766, 15127, 217099, 2988966)
スコアの計算方法がわかりません。さらに5文字を書く価値はありますか?
scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.13).toInt+666)
res42: List[Int] = List(672, 756, 1638, 10545, 100045, 1000419, 10068909, 101346800, 1019549994)
scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.3)toInt)
res43: List[Int] = List(7, 104, 1119, 11365, 114329, 1150158, 11582935, 116592898, 1172932855)
nが大きくなると、その範囲で計算が約16%減少しますが、スコアの式については、定数因子を考慮しませんか?
新しいBig-Oに関する考慮事項:
1 000、10000、100,000素数などを見つけるには、実行中の外側のループを決定する素数x =>(math.log(x)* x * 1.3の密度に関する式を使用します。
したがって、1から6 => NPrimes(10 ^ i)の値iの場合、外側のループの9399、133768 ...倍を実行します。
このO関数は、Peter Taylorのコメントの助けを借りて反復的に見つけました。PeterTaylorは、1.01ではなく、1.5を提案した指数のはるかに高い値を提案しました。
def O(n:Int) = (math.pow((n * math.log (n)), 1.01)).toLong
O:(n:Int)Long
val ns = List(10, 100, 1000, 10000, 100000, 1000*1000).map(x=>(math.log(x)*x*1.3)toInt).map(O)
ns:List [Long] = List(102、4152、91532、1612894、25192460、364664351)
That's the list of upper values, to find primes below (since my algorithm has to know this value before it has to estimate it), send through the O-function, to find similar quotients for moving from 100 to 1000 to 10000 primes and so on:
(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
40.705882352941174
22.045279383429673
17.62109426211598
15.619414543051187
14.47513863274964
13.73425213148954
1.01を指数として使用する場合、これは商です。カウンターが経験的に見つけたものは次のとおりです。
ns: Array[Int] = Array(1628, 2929, 23583, 321898, 4291625, 54289190, 660847317)
(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
1.799140049140049
8.051553431205189
13.649578085909342
13.332251210010625
12.65003116535112
12.172723833234572
最初の2つの値は外れ値です。これは、小さな値(最大1000)の推定式を常に修正しているためです。
1.5のPeter Taylorsの提案では、次のようになります。
245.2396265560166
98.8566987153728
70.8831374743478
59.26104390040363
52.92941829568069
48.956394784317816
今私の価値で私は得る:
O(263)
res85: Long = 1576
しかし、O関数を使用して観測値にどれだけ近づけるかはわかりません。