A number n is a self number if there is no number g such that g + the sum of g's digits = n. So 18 is not a self number because 9+9=18, 43 is not a self number because 35+5+3=43.


The task is:

 Display the first 50 self numbers;
 I believe that the 100000000th self number is 1022727208. You should either confirm or dispute my conjecture.

224036583-1 is a Mersenne prime, claimed to also be a self number. Extra credit to anyone proving it.


See also
 
OEIS: A003052 - Self numbers or Colombian numbers
Wikipedia: Self numbers
(*
    Base-10 self numbers by index (single or range).
    Follows an observed sequence pattern whereby, after the initial single-digit odd numbers, self numbers are
    grouped in runs whose members occur at numeric intervals of 11. Runs after the first one come in blocks of
    ten: eight runs of ten numbers followed by two shorter runs. The numeric interval between runs is usually 2,
    but that between shorter runs, and their length, depend on the highest-order digit change occurring in them.
    This connection with significant digit change means every ten blocks form a higher-order block, every ten
    of these a higher-order-still block, and so on.
 
    The code below appears to be good up to the last self number before 10^12 — ie. 999,999,999,997, which is
    returned as the 97,777,777,792nd such number. After this, instead of zero-length shorter runs, the actual
    pattern apparently starts again with a single run of 10, like the one at the beginning.
*)
on selfNumbers(indexRange)
    set indexRange to indexRange as list
    -- Script object with subhandlers and associated properties.
    script |subscript|
        property startIndex : beginning of indexRange
        property endIndex : end of indexRange
        property counter : 0
        property currentSelf : -1
        property output : {}
 
        -- Advance to the next self number in the sequence, append it to the output if required, indicate if finished.
        on doneAfterAdding(interval)
            set currentSelf to currentSelf + interval
            set counter to counter + 1
            if (counter < startIndex) then return false
            set end of my output to currentSelf
            return (counter = endIndex)
        end doneAfterAdding
 
        -- If necessary, fast forward to the last self number before the lowest-order block containing the first number required.
        on fastForward()
            if (counter ≥ startIndex) then return
            -- The highest-order blocks whose ends this script handles correctly contain 9,777,777,778 self numbers.
            -- The difference between equivalently positioned numbers in these blocks is 100,000,000,001.
            -- The figures for successively lower-order blocks have successively fewer 7s and 0s!
            set indexDiff to 9.777777778E+9
            set numericDiff to 1.00000000001E+11
            repeat until ((indexDiff < 98) or (counter = startIndex))
                set test to counter + indexDiff
                if (test < startIndex) then
                    set counter to test
                    set currentSelf to (currentSelf + numericDiff)
                else
                    set indexDiff to (indexDiff + 2) div 10
                    set numericDiff to numericDiff div 10 + 1
                end if
            end repeat
        end fastForward
 
        -- Work out a shorter run length based on the most significant digit change about to happen.
        on getShorterRunLength()
            set shorterRunLength to 9
            set temp to (|subscript|'s currentSelf) div 1000
            repeat while (temp mod 10 is 9)
                set shorterRunLength to shorterRunLength - 1
                set temp to temp div 10
            end repeat
            return shorterRunLength
        end getShorterRunLength
    end script
 
    -- Main process. Start with the single-digit odd numbers and first run.
    repeat 5 times
        if (|subscript|'s doneAfterAdding(2)) then return |subscript|'s output
    end repeat
    repeat 9 times
        if (|subscript|'s doneAfterAdding(11)) then return |subscript|'s output
    end repeat
    -- Fast forward if the start index hasn't yet been reached.
    tell |subscript| to fastForward()
 
    -- Sequencing loop, per lowest-order block.
    repeat
        -- Eight ten-number runs, each at a numeric interval of 2 from the end of the previous one.
        repeat 8 times
            if (|subscript|'s doneAfterAdding(2)) then return |subscript|'s output
            repeat 9 times
                if (|subscript|'s doneAfterAdding(11)) then return |subscript|'s output
            end repeat
        end repeat
        -- Two shorter runs, the second at an interval inversely related to their length.
        set shorterRunLength to |subscript|'s getShorterRunLength()
        repeat with interval in {2, 2 + (10 - shorterRunLength) * 13}
            if (|subscript|'s doneAfterAdding(interval)) then return |subscript|'s output
            repeat (shorterRunLength - 1) times
                if (|subscript|'s doneAfterAdding(11)) then return |subscript|'s output
            end repeat
        end repeat
    end repeat
end selfNumbers
 
-- Demo calls:
-- First to fiftieth self numbers.
selfNumbers({1, 50})
--> {1, 3, 5, 7, 9, 20, 31, 42, 53, 64, 75, 86, 97, 108, 110, 121, 132, 143, 154, 165, 176, 187, 198, 209, 211, 222, 233, 244, 255, 266, 277, 288, 299, 310, 312, 323, 334, 345, 356, 367, 378, 389, 400, 411, 413, 424, 435, 446, 457, 468}
 
-- One hundred millionth:
selfNumbers(100000000)
--> {1.022727208E+9}
 
-- 97,777,777,792nd:
selfNumbers(9.7777777792E+10)
--> {9.99999999997E+11}