scala 191
Not the shortest one...
object P extends App{
def c(M:Int)={
val p=(false::false::true::List.range(3,M+1).map(_%2!=0)).toArray
for(i<-List.range(3,M)
if(p(i))){
var j=2*i;
while(j<M){
if(p(j))p(j)=false
j+=i}
}
(1 to M).filter(x=>p(x))
}
println(c(args(0).toInt))
}
Just measuring the method c, like the others do.
But how to prove, that it fulfills the Big-O requierement?
Well, I feed it with numbers, each twice as big as the number before. If it was of O(x²) complexity, it should need about 4 times as long, shouldn't it?
So I just measure it:
for p in {10..22}
do
/usr/bin/time scala P $((2**p))> /dev/null
echo "N="$((2**p))
done 2>&1 | tee primes.log
and then it's just a grep:
egrep -o "(^.*user|N=.*|#)" primes.log | tr "\n" "\t" | tr "#" "\n"
0.57user N=1024
0.54user N=2048
0.56user N=4096
0.59user N=8192
0.62user N=16384
0.66user N=32768
0.70user N=65536
0.77user N=131072
0.99user N=262144
1.48user N=524288
2.59user N=1048576
5.68user N=2097152
10.79user N=4194304
So in the beginning there is only a startup overhead of about .55s - later it is a linear growth. For N'=2*N, t(N') ≈ 2*t(N).
O(n*ln(sqrt(n)))
.O(n*sqrt(n))
maybe, but there's nothing hints to why it would have anln
in there. Please correct me if I'm wrong. \$\endgroup\$O(ln(sqrt(x)) == O(ln(x))
\$\endgroup\$π(i) ~ i/ln(i)
. So,sqrt(X)/ln(sqrt(X)) ~ sqrt(X)/ln(X)
and overall complexity of producingN ~= X/ln(X)
primes isO(X^1.5 / (ln(X))^2 )
, not counting the testing of composites, most of which are multiples of2
or3
, so will be weeded out with very few tests. \$\endgroup\$N: X ~= N*log(N)
, it isO(N^1.5/sqrt(ln(N)))
. Or in practical termsN^1.4 .. 1.45
. So you might want to amend your spec to "below N^1.5" (or at least "below X^1.5") or all kinds of solutions will have to be admitted. \$\endgroup\$