Proper divisors: Difference between revisions

Content added Content deleted
m (→‎version 2: changed whitespace and comments, added better support for zero.)
Line 1,212: Line 1,212:


With the (subroutine) optimization, it's over twenty times faster.
With the (subroutine) optimization, it's over twenty times faster.
<lang rexx>/*REXX pgm finds proper divisors & count of some integer ranges, maximum*/
<lang rexx>/*REXX program finds proper divisors (& count) of integer ranges; max of #s. */
parse arg low high inc range xtra /*get optional args. */
parse arg bot top inc range xtra /*get optional args from C.L. */
high=word(high low 10,1); low=word(low 1,1); inc=word(inc 1,1) /*opts*/
top=word(top bot 10,1); bot=word(bot 1,1); inc=word(inc 1,1) /*1st range*/
if range=='' then range=high /*use HIGH for range.*/
if range=='' then range=top /*use TOP for the 2nd range.*/
w=length(high)+1; numeric digits max(9,w) /*'nuff digs for // */
w=length(top)+1; numeric digits max(9,w) /*'nuff digs for // operation*/
m=0
m=0
do n=low to high by inc; q=Pdivs(n); #=words(q)
do n=bot to top by inc; q=Pdivs(n); #=words(q); if q=='∞' then #=q
say right(n,digits()) 'has' center(#,4) "proper divisors: " q
say right(n,digits()) 'has' center(#,4) "proper divisors: " q
end /*n*/ /* [↑] process a range of ints.*/
end /*n*/ /* [↑] process a range of integers. */
say; @.='and'
say
do r=1 for range; q=Pdivs(r); #=words(q); if #<m then iterate
@.='and'
do r=1 for range; q=Pdivs(r); #=words(q); if #<m then iterate
@.#=@.# @. r; m=#
end /*r*/ /* [↑] process a range of integers. */
@.#=@.# @. r; m=#
end /*r*/ /* [↑] process a range of ints.*/


say m 'is the highest number of proper divisors in range 1──►'range", and it's for: " subword(@.m,3)
say m 'is the highest number of proper divisors in range 1──►'range", and it's for: " subword(@.m,3)
say /* [↓] handle any extra numbers.*/
say /* [↓] handle any given extra numbers. */
do i=1 for words(xtra); n=word(xtra,i); w=length(n)+1
do i=1 for words(xtra); n=word(xtra,i)
numeric digits max(9,w); q=Pdivs(n); #=words(q)
numeric digits max(9,length(n)+1); q=Pdivs(n); #=words(q)
say right(n,digits()) 'has' center(#,4) "proper divisors."
say right(n,digits()) 'has' center(#,4) "proper divisors."
end /*i*/ /* [↑] support extra given nums.*/
end /*i*/ /* [↑] support extra given integers. */
exit /*stick a fork in it, we're done.*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────PDIVS subroutine────────────────────*/
/*──────────────────────────────────PDIVS subroutine──────────────────────────*/
Pdivs: procedure; parse arg x,b; x=abs(x); if x==1 then return ''
Pdivs: procedure; parse arg x,b; x=abs(x); if x==1 then return ''
if x==0 then return 'infinite'; odd=x//2
odd=x//2; if x==0 then return ''
a=1 /* [↓] use only EVEN|ODD integers*/
a=1 /* [↓] process only EVEN│ODD integers.*/
do j=2+odd by 1+odd while j*j<x /*divide by all integers up to √x*/
do j=2+odd by 1+odd while j*j<x /*divide by all integers up to √x. */
if x//j==0 then do; a=a j; b=x%j b; end /*add divs to α&ß lists if ÷*/
if x//j==0 then do; a=a j; b=x%j b; end /*add divisors to α&ß lists if ÷*/
end /*j*/ /* [↑] % is REXX integer divide*/
end /*j*/ /* [↑] % is the REXX integer division*/
/* [↓] adjust for square. _ */
/* [↓] adjust for square. _ */
if j*j==x then return a j b /*Was X a square? If so, add √x.*/
if j*j==x then return a j b /*Was X a square? If so, add √x. */
return a b /*return divisors (both lists). */</lang>
return a b /*return the divisors (both lists). */</lang>
'''output''' when using the following input: &nbsp; <tt> 1 &nbsp; 10 &nbsp; 1 &nbsp; &nbsp; &nbsp; 20000 &nbsp; &nbsp; &nbsp; 166320 1441440 11796480000 </tt>
'''output''' when using the following input: &nbsp; <tt> 0 &nbsp; 10 &nbsp; 1 &nbsp; &nbsp; &nbsp; 20000 &nbsp; &nbsp; &nbsp; 166320 &nbsp; 1441440 &nbsp; 11796480000 </tt>
<pre>
<pre>
0 has ∞ proper divisors: ∞
1 has 0 proper divisors:
1 has 0 proper divisors:
2 has 1 proper divisors: 1
2 has 1 proper divisors: 1