Ruby: Running time = 0.93s
+-#PrimeList
class PrimeList
@@primes=[2,3,5,7,11,13,17,19]
def initialize
@next=-1
end
def last
return 0 if @next==-1
PrimeList.get(@next)
end
def getNext
PrimeList.get(@next+=1)
end
def [](i)
PrimeList.get(i)
end
def PrimeList.isPrime?(n)
if(@@primes[-1] >= n)
return true if @@primes.index n
return false
end
p=PrimeList.new
sq=Math.sqrt(n)
while(p.last<=sq)
return false if n % (p.getNext)==0
end
true
end
def PrimeList.get(i)
PrimeList.gen while @@primes.length<=i
@@primes[i]
end
def PrimeList.getPrimeNear(n)
PrimeList.gen until n<@@primes[-1]
@@primes[PrimeList.primeIndexNear(n)]
end
private
def PrimeList.primeIndexNear(n)
return 0 if n<@@primes[0]
return [-1] if n>@@primes[-1]
PrimeList.getIndexNear(@@primes,n)
end
def PrimeList.getIndexNear(list,n)
return 0 if list.length==1
if(list.length==2)
avg=(list[0]+list[1])/2.0
return 1 if n>avg
return 0
end
splitAfter=list.size/2
return PrimeList.getIndexNear(list[0..splitAfter],n) if n<list[splitAfter]
return splitAfter+1+PrimeList.getIndexNear(list[(splitAfter+1)..-1],n) if n>list[splitAfter+1]
avg=(list[splitAfter]+list[splitAfter+1])/2
return splitAfter+1 if n>avg
splitAfter
end
def PrimeList.gen
add=@@primes[-1]
cands=Set.new(1..(5*add)){|i|2*i+add}
theBegin=add+2
theEnd=11*add
highest=Math.sqrt(theEnd).to_i
upTo=PrimeList.primeIndexNear(highest)
upTo-=1 if @@primes[upTo]>highest
@@primes[1..upTo].each do |mult|
((theBegin-theBegin%mult)..(theEnd-theEnd%mult + mult)).step(mult){|i|cands.delete i}
end
@@primes=@@primes+cands.to_a.sort
end
end
def isSquare?(n)
return false if n<1
a=Math.sqrt(n).to_i
n==a*a
end
def p46
i=7
while true
i+=2
i+=2 while PrimeList.isPrime? i
pl=PrimeList.new
pl.getNext
fits=false
while (p=pl.getNext) < i
if(isSquare?((i-p)/2))
fits=true
break
end
end
unless fits
puts i
return
end
end
end