107 lines
5 KiB
AppleScript
107 lines
5 KiB
AppleScript
|
|
(*
|
|||
|
|
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}
|