(*
per @nektro's observation on perfect numbers in binary
* perfect numbers have an odd number of bits
* the first half (rounded up) are 1s
* the second half (rounded down) are 0s
*)// Creates a perfect number candidate of the given bit length.// Not all candidates are perfect numbers.// Example: createCandidate 3 returns 110b or 6// createCandidate 5 returns 11100b or 28letcreateCandidatebitLength=letzeroStart=bitLength/2+1letupdatenumi=letshifted=num*2Lifi<zeroStartthenshifted+1LelseshiftedList.initbitLengthid|>List.foldupdate0LletoddBitLengths=// 1, 3, 5, 7, 9, ... , 61Seq.init31(funi->i*2+1)// should be 32, but last one overflows on sum stepoddBitLengths|>Seq.mapcreateCandidate|>Seq.filterisPerfect|>Seq.iter(funi->printfn"%20i %s"i(Convert.ToString(i,2)))// 1 1// 6 110// 28 11100// 496 111110000// 8128 1111111000000// 33550336 1111111111111000000000000// 8589869056 111111111111111110000000000000000// 137438691328 1111111111111111111000000000000000000// 2305843008139952128 1111111111111111111111111111111000000000000000000000000000000
To filter the numbers down to just likely candidates, I am using @nektro
's observation. I first generate a limited list of possible candidates that fit in a 64 bit integer, then filter down to only perfect ones. It takes 40s or so to run, but all of that time is spent between the last and next-to-last result.
Runtime is about 40 seconds in Release mode. The largest cost is finding divisors. I used the least expensive algorithm I could find. But it is still expensive. So to get the runtime down that low, I optimize down the number of inputs using nektro’s observation.
I posted the prime-based solution here. The actual perfect number calculation time is now negligible, and the code can be a one-liner. But it requires being fed Mersenne Exponents. Fortunately, very few/small Mersenne Exponents quickly turn into perfect numbers which are too large for traditional memory structures.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
F#
Usage
To filter the numbers down to just likely candidates, I am using @nektro 's observation. I first generate a limited list of possible candidates that fit in a 64 bit integer, then filter down to only perfect ones. It takes 40s or so to run, but all of that time is spent between the last and next-to-last result.
How much time did this script took to run ? You approach is really nice, but I'm worried by
|> Seq.filter isPerfect
perf.Runtime is about 40 seconds in Release mode. The largest cost is finding divisors. I used the least expensive algorithm I could find. But it is still expensive. So to get the runtime down that low, I optimize down the number of inputs using nektro’s observation.
You could gain a little by only generating prime numbers for your candidates. Eratosthenes' sieve is not that hard to implement.
I will post another solution using primes. Thanks for the tip!
I posted the prime-based solution here. The actual perfect number calculation time is now negligible, and the code can be a one-liner. But it requires being fed Mersenne Exponents. Fortunately, very few/small Mersenne Exponents quickly turn into perfect numbers which are too large for traditional memory structures.