Minimal steps down to 1: Difference between revisions

Content added Content deleted
(→‎Python: Tabulated: Allied problem.)
Line 447: Line 447:
Up to 50,000 found 1 number that requires at least 26 steps.
Up to 50,000 found 1 number that requires at least 26 steps.
(45925) 26 steps: -2=>45923, -2=>45921, /3=>15307, -2=>15305, -2=>15303, /3=>5101, -2=>5099, -2=>5097, /3=>1699, -2=>1697, -2=>1695, /3=>565, -2=>563, -2=>561, /3=>187, -2=>185, -2=>183, /3=>61, -2=>59, -2=>57, /3=>19, -2=>17, -2=>15, /3=>5, -2=>3, /3=>1</pre>
(45925) 26 steps: -2=>45923, -2=>45921, /3=>15307, -2=>15305, -2=>15303, /3=>5101, -2=>5099, -2=>5097, /3=>1699, -2=>1697, -2=>1695, /3=>565, -2=>563, -2=>561, /3=>187, -2=>185, -2=>183, /3=>61, -2=>59, -2=>57, /3=>19, -2=>17, -2=>15, /3=>5, -2=>3, /3=>1</pre>

=={{header|Phix}}==
Using simple iterative (vs recursive) memoisation. To make things a bit more interesting it maintains separate caches for any&all {d,s} sets.
<lang Phix>sequence cache = {},
ckeys = {}

function ms21(integer n, sequence ds)
integer cdx = find(ds,ckeys)
if cdx=0 then
ckeys = append(ckeys,ds)
cache = append(cache,{{}})
cdx = length(cache)
end if
for i=length(cache[cdx])+1 to n do
integer ms = n+2
sequence steps = {}
for j=1 to length(ds) do -- (d then s)
for k=1 to length(ds[j]) do
integer dsk = ds[j][k],
ok = iff(j=1?remainder(i,dsk)=0:i>dsk)
if ok then
integer m = iff(j=1?i/dsk:i-dsk),
l = length(cache[cdx][m])+1
if ms>l then
ms = l
steps = prepend(cache[cdx][m],sprintf("%s%d -> %d",{"/-"[j],dsk,m}))
end if
end if
end for
end for
if steps = {} then ?9/0 end if
cache[cdx] = append(cache[cdx],steps)
end for
return cache[cdx][n]
end function

procedure show10(sequence ds)
printf(1,"\nWith divisors %v and subtractors %v:\n",ds)
for n=1 to 10 do
sequence steps = ms21(n,ds)
integer ns = length(steps)
string ps = iff(ns=1?"":"s"),
eg = iff(ns=0?"":", eg "&join(steps,","))
printf(1,"%d takes %d step%s%s\n",{n,ns,ps,eg})
end for
end procedure

procedure maxsteps(sequence ds, integer lim)
integer ms = -1, ls
sequence mc = {}, steps, args
for n=1 to lim do
steps = ms21(n,ds)
ls = length(steps)
if ls>ms then
ms = ls
mc = {n}
elsif ls=ms then
mc &= n
end if
end for
integer lm = length(mc)
string {are,ps,ns} = iff(lm=1?{"is","","s"}:{"are","s",""})
args = { are,lm, ps, lim, ns,ms, mc}
printf(1,"There %s %d number%s below %d that require%s %d steps: %v\n",args)
end procedure

show10({{2,3},{1}})
maxsteps({{2,3},{1}},2000)
maxsteps({{2,3},{1}},20000)
maxsteps({{2,3},{1}},50000)

show10({{2,3},{2}})
maxsteps({{2,3},{2}},2000)
maxsteps({{2,3},{2}},20000)
maxsteps({{2,3},{2}},50000)</lang>
{{out}}
<pre>
With divisors {2,3} and subtractors {1}:
1 takes 0 steps
2 takes 1 step, eg /2 -> 1
3 takes 1 step, eg /3 -> 1
4 takes 2 steps, eg /2 -> 2,/2 -> 1
5 takes 3 steps, eg -1 -> 4,/2 -> 2,/2 -> 1
6 takes 2 steps, eg /2 -> 3,/3 -> 1
7 takes 3 steps, eg -1 -> 6,/2 -> 3,/3 -> 1
8 takes 3 steps, eg /2 -> 4,/2 -> 2,/2 -> 1
9 takes 2 steps, eg /3 -> 3,/3 -> 1
10 takes 3 steps, eg -1 -> 9,/3 -> 3,/3 -> 1
There are 16 numbers below 2000 that require 14 steps: {863,1079,1295,1439,1511,1583,1607,1619,1691,1727,1823,1871,1895,1907,1919,1943}
There are 5 numbers below 20000 that require 20 steps: {12959,15551,17279,18143,19439}
There are 3 numbers below 50000 that require 22 steps: {25919,31103,38879}

With divisors {2,3} and subtractors {2}:
1 takes 0 steps
2 takes 1 step, eg /2 -> 1
3 takes 1 step, eg /3 -> 1
4 takes 2 steps, eg /2 -> 2,/2 -> 1
5 takes 2 steps, eg -2 -> 3,/3 -> 1
6 takes 2 steps, eg /2 -> 3,/3 -> 1
7 takes 3 steps, eg -2 -> 5,-2 -> 3,/3 -> 1
8 takes 3 steps, eg /2 -> 4,/2 -> 2,/2 -> 1
9 takes 2 steps, eg /3 -> 3,/3 -> 1
10 takes 3 steps, eg /2 -> 5,-2 -> 3,/3 -> 1
There is 1 number below 2000 that requires 17 steps: {1699}
There is 1 number below 20000 that requires 24 steps: {19681}
There is 1 number below 50000 that requires 26 steps: {45925}
</pre>


=={{header|Python}}==
=={{header|Python}}==