Triperfect Numbers

April 23, 2019

We have another exercise today based on a Numberphile video:

A perfect number is a number n that is equal to the sum of its divisors, excluding itself; in other words, a perfect number n satisfies the equation σn = 2n, where σ is the divisor-sum function. A triperfect number is a number n such that σn = 3n. It is believed that there are six, and only six, triperfect numbers.

Your task is to compute the six triperfect numbers. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

4 Responses to “Triperfect Numbers”

  1. Pascal Bourguignon said
    
    (ql:quickload :bordeaux-threads)
    
    (defun triperfectp (n)
      (= (reduce (function +) (divisors n))
         (+ n n n)))
    
    (defstruct triperfect
      (current 0)
      (numbers '())
      (start-time 0)
      (error nil))
    
    (defparameter *triperfects* (make-triperfect))
    
    (defun search-triperfect-numbers ()
      (bt:make-thread
       (lambda ()
         (handler-case
             (loop
               :for n :from (triperfect-current *triperfects*)
                 :initially (setf (triperfect-start-time *triperfects*) (get-universal-time))
               :do (setf (triperfect-current *triperfects*) n)
               :when (triperfectp n)
                 :do (push n (triperfect-numbers *triperfects*)))
           (error (err)
             (setf (triperfect-error *triperfects*) err))))
       :name "Triperfect Search"))
    
    (defun triperfect-numbers-found-so-far ()
      (let ((duration     (if (zerop (triperfect-start-time *triperfects*))
                              nil
                              (- (get-universal-time) (triperfect-start-time *triperfects*))))
            (n            (triperfect-current *triperfects*))
            (triperfects  (triperfect-numbers *triperfects*))
            (error        (triperfect-error *triperfects*)))
        (format t "~&~:[~;;; After ~:*~A second~:*~P, ~]scanning up to ~D, we have found ~A triperfect number~:*~P~:[~;: ~:*~{~A~^, ~}~].~%"
                duration n (length triperfects) triperfects)
        (if error
            (format t ";; The search aborted with the error ~A~%" error)
            (format t ";; The search continues.~%"))
        (finish-output)
        triperfects))
    
    (progn
      (search-triperfect-numbers)
      (sleep 60)
      (triperfect-numbers-found-so-far)
      (sleep 60)
      (triperfect-numbers-found-so-far))
    ;; After 60 seconds, scanning up to 855906, we have found 3 triperfect numbers: 523776, 672, 120.
    ;; The search continues.
    ;; After 120 seconds, scanning up to 1410357, we have found 3 triperfect numbers: 523776, 672, 120.
    ;; The search continues.
    ;; (523776 672 120)
    (triperfect-numbers-found-so-far)
    ;; After 258 seconds, scanning up to 2425768, we have found 3 triperfect numbers: 523776, 672, 120.
    ;; The search continues.
    (523776 672 120)
    
    
  2. Pascal Bourguignon said

    Oh, com.informatimago.common-lisp.arithmetic.primes:divisors is found in https://github.com/informatimago/lisp/blob/master/common-lisp/arithmetic/primes.lisp

  3. Daniel said

    Here’s a solution in C that uses trial division to find factors. It would seemingly take a long time using this implementation to find the six triperfect numbers.

    @programmingpraxis, can you elaborate on your “pre-qualify” filter? Your solution says “all of the multiperfect numbers are highly composite”, but the second triperfect number, 672, is not a highly composite number (according the the Wikipedia definition of highly composite, aka “anti-prime”, numbers).

    #include <stdint.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    typedef uint64_t u64;
    
    int main(void) {
      for (u64 x = 1; ; ++x) {
        u64 sum = 0;
        for (u64 y = 1; y * y <= x; ++y) {
          if (x % y == 0) {
            sum += y;
            u64 z = x / y;
            if (z != y)
              sum += z;
          }
        }
        if (sum == 3 * x)
          printf("%lu\n", x);
      }
      return EXIT_SUCCESS;
    }
    

    Output:

    $ ./a.out
    120
    672
    523776
    ...
    
  4. Paul said

    @Daniel: I will answer for @programmingpraxis. All the triperfect numbers are similar to highly composite numbers. They all look like 2^nprime1prime2….. with all primes below 160. The triperfect numbers are no hcn though. Knowing this you can factorise the numbers with low prime numbers only (prequalify). Another trick is to search the sequence a, 2a, 3a, 4a, .. with a=2^n. In this way you can find even the highest triperfect numbers very quickly. I feel it is kind cheating though, as long as you cannot proof mathematically that triperfect numbers should behave like that.

Leave a comment