Self numbers: Difference between revisions

Content added Content deleted
m (→‎{{header|Phix}}: added syntax colouring the hard way)
Line 1,230: Line 1,230:
Certainly puts my previous rubbish attempts ([[Self_numbers\Phix|archived here]]) to shame.<br>
Certainly puts my previous rubbish attempts ([[Self_numbers\Phix|archived here]]) to shame.<br>
The precise nature of the difference-pattern eludes me, I will admit.
The precise nature of the difference-pattern eludes me, I will admit.
<lang Phix>--
<!--<lang Phix>-->
<span style="color: #000080;font-style:italic;">--
-- Base-10 self numbers by index (single or range).
-- 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
-- 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
-- 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,
-- 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.
-- 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.
-- 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
-- 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
-- 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.
-- pattern apparently starts again with a single run of 10, like the one at the beginning.
--
--</span>
integer startIndex, endIndex, counter
<span style="color: #004080;">integer</span> <span style="color: #000000;">startIndex</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">endIndex</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">counter</span>
atom currentSelf
<span style="color: #004080;">atom</span> <span style="color: #000000;">currentSelf</span>
sequence output
<span style="color: #004080;">sequence</span> <span style="color: #000000;">output</span>

function doneAfterAdding(integer interval, n)
<span style="color: #008080;">function</span> <span style="color: #000000;">doneAfterAdding</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">interval</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
-- Advance to the next self number in the sequence, append it to the output if required, indicate if finished.
<span style="color: #000080;font-style:italic;">-- Advance to the next self number in the sequence, append it to the output if required, indicate if finished.</span>
for i=1 to n do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
currentSelf += interval
<span style="color: #000000;">currentSelf</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">interval</span>
counter += 1
<span style="color: #000000;">counter</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
if counter >= startIndex then
<span style="color: #008080;">if</span> <span style="color: #000000;">counter</span> <span style="color: #0000FF;">>=</span> <span style="color: #000000;">startIndex</span> <span style="color: #008080;">then</span>
output &= currentSelf
<span style="color: #000000;">output</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">currentSelf</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if counter = endIndex then return true end if
<span style="color: #008080;">if</span> <span style="color: #000000;">counter</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">endIndex</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">true</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return false
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function selfNumbers(sequence indexRange)
<span style="color: #008080;">function</span> <span style="color: #000000;">selfNumbers</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">indexRange</span><span style="color: #0000FF;">)</span>
startIndex = indexRange[1]
<span style="color: #000000;">startIndex</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">indexRange</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
endIndex = indexRange[$]
<span style="color: #000000;">endIndex</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">indexRange</span><span style="color: #0000FF;">[$]</span>
counter = 0
<span style="color: #000000;">counter</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
currentSelf = -1
<span style="color: #000000;">currentSelf</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
output = {}
<span style="color: #000000;">output</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
-- Main process. Start with the single-digit odd numbers and first run.
<span style="color: #000080;font-style:italic;">-- Main process. Start with the single-digit odd numbers and first run.</span>
if doneAfterAdding(2,5) then return output end if
<span style="color: #008080;">if</span> <span style="color: #000000;">doneAfterAdding</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">output</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if doneAfterAdding(11,9) then return output end if
<span style="color: #008080;">if</span> <span style="color: #000000;">doneAfterAdding</span><span style="color: #0000FF;">(</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">output</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
-- If necessary, fast forward to last self number before the lowest-order block containing first number rqd.
<span style="color: #000080;font-style:italic;">-- If necessary, fast forward to last self number before the lowest-order block containing first number rqd.</span>
if counter<startIndex then
<span style="color: #008080;">if</span> <span style="color: #000000;">counter</span><span style="color: #0000FF;"><</span><span style="color: #000000;">startIndex</span> <span style="color: #008080;">then</span>
-- The highest-order blocks whose ends this handles correctly contain 9,777,777,778 self numbers.
<span style="color: #000080;font-style:italic;">-- 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!
-- 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!</span>
atom indexDiff = 9777777778,
<span style="color: #004080;">atom</span> <span style="color: #000000;">indexDiff</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">9777777778</span><span style="color: #0000FF;">,</span>
numericDiff = 100000000001
<span style="color: #000000;">numericDiff</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">100000000001</span>
while indexDiff>=98 and counter!=startIndex do
<span style="color: #008080;">while</span> <span style="color: #000000;">indexDiff</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">98</span> <span style="color: #008080;">and</span> <span style="color: #000000;">counter</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">startIndex</span> <span style="color: #008080;">do</span>
if counter+indexDiff < startIndex then
<span style="color: #008080;">if</span> <span style="color: #000000;">counter</span><span style="color: #0000FF;">+</span><span style="color: #000000;">indexDiff</span> <span style="color: #0000FF;"><</span> <span style="color: #000000;">startIndex</span> <span style="color: #008080;">then</span>
counter += indexDiff
<span style="color: #000000;">counter</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">indexDiff</span>
currentSelf += numericDiff
<span style="color: #000000;">currentSelf</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">numericDiff</span>
else
indexDiff = (indexDiff+2)/10 -- (..78->80->8)
<span style="color: #008080;">else</span>
<span style="color: #000000;">indexDiff</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">indexDiff</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">-- (..78-&gt;80-&gt;8)</span>
numericDiff = (numericDiff+9)/10 -- (..01->10->1)
<span style="color: #000000;">numericDiff</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">numericDiff</span><span style="color: #0000FF;">+</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">10</span> <span style="color: #000080;font-style:italic;">-- (..01-&gt;10-&gt;1)</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>

-- Sequencing loop, per lowest-order block.
<span style="color: #000080;font-style:italic;">-- Sequencing loop, per lowest-order block.</span>
while true do
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
-- Eight ten-number runs, each at a numeric interval of 2 from the end of the previous one.
<span style="color: #000080;font-style:italic;">-- Eight ten-number runs, each at a numeric interval of 2 from the end of the previous one.</span>
for i=1 to 8 do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
if doneAfterAdding(2,1) then return output end if
<span style="color: #008080;">if</span> <span style="color: #000000;">doneAfterAdding</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">output</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if doneAfterAdding(11,9) then return output end if
<span style="color: #008080;">if</span> <span style="color: #000000;">doneAfterAdding</span><span style="color: #0000FF;">(</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">output</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
-- Two shorter runs, the second at an interval inversely related to their length.
<span style="color: #000080;font-style:italic;">-- Two shorter runs, the second at an interval inversely related to their length.</span>
integer shorterRunLength = 8,
<span style="color: #004080;">integer</span> <span style="color: #000000;">shorterRunLength</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span>
temp = floor(currentSelf/1000)
<span style="color: #000000;">temp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">currentSelf</span><span style="color: #0000FF;">/</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">)</span>
-- Work out a shorter run length based on the most significant digit change about to happen.
<span style="color: #000080;font-style:italic;">-- Work out a shorter run length based on the most significant digit change about to happen.</span>
while remainder(temp,10)=9 do
<span style="color: #008080;">while</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">temp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
shorterRunLength -= 1
<span style="color: #000000;">shorterRunLength</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
temp = floor(temp/10)
<span style="color: #000000;">temp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">temp</span><span style="color: #0000FF;">/</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
integer interval = 2
<span style="color: #004080;">integer</span> <span style="color: #000000;">interval</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
for i=1 to 2 do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
if doneAfterAdding(interval,1) then return output end if
<span style="color: #008080;">if</span> <span style="color: #000000;">doneAfterAdding</span><span style="color: #0000FF;">(</span><span style="color: #000000;">interval</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">output</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if doneAfterAdding(11,shorterRunLength) then return output end if
<span style="color: #008080;">if</span> <span style="color: #000000;">doneAfterAdding</span><span style="color: #0000FF;">(</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shorterRunLength</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">output</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
interval += (9-shorterRunLength)*13
<span style="color: #000000;">interval</span> <span style="color: #0000FF;">+=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">9</span><span style="color: #0000FF;">-</span><span style="color: #000000;">shorterRunLength</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">13</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
atom t0 = time()
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
printf(1,"The first 50 self numbers are:\n")
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"The first 50 self numbers are:\n"</span><span style="color: #0000FF;">)</span>
pp(selfNumbers({1, 50}),{pp_IntFmt,"%3d",pp_IntCh,false})
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">selfNumbers</span><span style="color: #0000FF;">({</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">50</span><span style="color: #0000FF;">}),{</span><span style="color: #004600;">pp_IntFmt</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3d"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">pp_IntCh</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">})</span>
for p=8 to 9 do
<span style="color: #008080;">for</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">8</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
integer n = power(10,p)
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
printf(1,"The %,dth safe number is %,d\n",{n,selfNumbers({n})[1]})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"The %,dth safe number is %,d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">selfNumbers</span><span style="color: #0000FF;">({</span><span style="color: #000000;">n</span><span style="color: #0000FF;">})[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]})</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
printf(1,"completed in %s\n",elapsed(time()-t0))</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"completed in %s\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">))</span>
<!--</lang>-->
{{out}}
{{out}}
<pre>
<pre>