Data update
This commit is contained in:
parent
4d5544505c
commit
4924dd0264
3073 changed files with 55820 additions and 4408 deletions
83
Task/Self-numbers/Pluto/self-numbers.pluto
Normal file
83
Task/Self-numbers/Pluto/self-numbers.pluto
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
local start_index, end_index, counter
|
||||
local current_self
|
||||
local output
|
||||
|
||||
local function done_after_adding(interval, n)
|
||||
-- Advance to the next self number in the sequence, append it to the output if required, indicate if finished.
|
||||
for _ = 1, n do
|
||||
current_self += interval
|
||||
++counter
|
||||
if counter >= start_index then
|
||||
output:insert(current_self)
|
||||
end
|
||||
if counter == end_index then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function self_numbers(index_range)
|
||||
start_index = index_range[1]
|
||||
end_index = index_range:back()
|
||||
counter = 0
|
||||
current_self = -1
|
||||
output = {}
|
||||
|
||||
-- Main process. Start with the single-digit odd numbers and first run.
|
||||
if done_after_adding(2, 5) then return output end
|
||||
if done_after_adding(11, 9) then return output end
|
||||
|
||||
-- If necessary, fast forward to last self number before the lowest-order block containing first number required.
|
||||
if counter < start_index then
|
||||
-- The highest-order blocks whose ends this 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!
|
||||
local index_diff = 9777777778
|
||||
local numeric_diff = 100000000001
|
||||
while index_diff >= 98 and counter != start_index do
|
||||
if counter + index_diff < start_index then
|
||||
counter += index_diff
|
||||
current_self += numeric_diff
|
||||
else
|
||||
index_diff = (index_diff + 2) / 10 -- (..78->80->8)
|
||||
numeric_diff = (numeric_diff + 9) /10 -- (..01->10->1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Sequencing loop, per lowest-order block.
|
||||
while true do
|
||||
-- Eight ten-number runs, each at a numeric interval of 2 from the end of the previous one.
|
||||
for _ = 1, 8 do
|
||||
if done_after_adding(2, 1) then return output end
|
||||
if done_after_adding(11, 9) then return output end
|
||||
end
|
||||
-- Two shorter runs, the second at an interval inversely related to their length.
|
||||
local shorter_run_length = 8
|
||||
local temp = current_self // 1000
|
||||
-- Work out a shorter run length based on the most significant digit change about to happen.
|
||||
while temp % 10 == 9 do
|
||||
shorter_run_length -= 1
|
||||
temp //= 10
|
||||
end
|
||||
|
||||
local interval = 2
|
||||
for _ = 1, 2 do
|
||||
if done_after_adding(interval, 1) then return output end
|
||||
if done_after_adding(11, shorter_run_length) then return output end
|
||||
interval += (9 - shorter_run_length) * 13
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print("The first 50 self numbers are:\n")
|
||||
for i, sn in self_numbers({1, 50}) do
|
||||
io.write(string.format("%3d ", sn))
|
||||
if i % 10 == 0 then print() end
|
||||
end
|
||||
print()
|
||||
for p = 8, 9 do
|
||||
local n = math.round(10 ^ p)
|
||||
local ord = string.formatint(n)
|
||||
local sn = string.formatint(math.round(self_numbers({n})[1]))
|
||||
print($"The {ord}th self number is {sn}")
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue