Law of cosines - triples: Difference between revisions

→‎{{header|REXX}}: optimized DO loops (using FOR), implemented the use of commas in large numbers, moved each set of computation to subroutines, added memoizations, changed whitespace and comments.
(Added 11l)
(→‎{{header|REXX}}: optimized DO loops (using FOR), implemented the use of commas in large numbers, moved each set of computation to subroutines, added memoizations, changed whitespace and comments.)
Line 1,844:
 
=={{header|REXX}}==
===using(Using some optimization=== and memoization.)
 
Instead of coding a general purpose subroutine (or function) to solve all of the
task's requirements,   it was decided to
Line 1,863 ⟶ 1,864:
<br>absolute value of the negative number).
<lang rexx>/*REXX pgm finds integer sided triangles that satisfy Law of cosines for 60º, 90º, 120º.*/
parse arg s1os1 s2os2 s3os3 os4 . /*obtain optional arguments from the CL*/
if s1os1=='' | s1os1=="," then s1os1= 13; s1=abs(os1) /*Not specified? Then use the default.*/
if s2os2=='' | s2os2=="," then s2os2= 13; s2=abs(os2) /* " " " " " " */
if s3os3=='' | s3os3=="," then s3os3= 13; s3=abs(os3) /* " " " " " " */
if os4=='' | os4=="," then os4= -0; s4=abs(os4) /* " " " " " " */
w= max( length(s1), length(s2), length(s3) ) /*W is used to align the side lengths.*/
@.= /*@: array holds squares, max of sides*/
 
if s1>0 then do; call head 120 do j=1 for max(s1, s2, s3, s4); @.j= j /*────120º: j + + ab ≡ c²/*use memoization.*/
end do a=1 for s1; aa = a/*j*a/
if s1>0 then call s1 /*handle the triangle docase for b=a+1 to s1; x= aa + b*b +120º. a*b/
if s2>0 then call s2 /*handle the triangle case for do c=b+1 to90º. s1 until c*c>x/
if s3>0 then call s3 if x==c/*chandle the thentriangle do;case for call show; iterate60º. b; end*/
if s4>0 then call s4 /*handle the case for unique sides. end /*c*/
end /*b*/
end /*a*/
call foot s1
end
 
if s2>0 then do; call head 90 /*────90º: a² + b² ≡ c² */
do a=1 for s2; aa = a*a
do b=a+1 to s2; x= aa + b*b
do c=b+1 to s2 until c*c>x
if x==c*c then do; call show; iterate b; end
end /*c*/
end /*b*/
end /*a*/
call foot s2
end
 
if s3>0 then do; call head 60 /*────60º: a² + b² ─ ab ≡ c² */
do a=1 for s3; aa = a*a
do b=a to s3; x= aa + b*b - a*b
do c=a to s3 until c*c>x
if x==c*c then do; call show; iterate b; end
end /*c*/
end /*b*/
end /*a*/
call foot s3
end
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
footcommas: sayparse right(#arg ?; ' solutionsdo foundjc=length(?)-3 for' angleto "(sides1 up to"by arg-3; ?=insert(1)'),', 65?, jc); sayend; return ?
headdAng: #w= 0length(s); ang= parse' arg'd"º deg;" uq' '; angless= 's 'deg"º* "s; @sol= say" center(angle,solutions 65,found '═')for"; return return
showfoot: #=say right(commas(#) + 1;@sol say 'ang "(sides up to" commas('rightarg(a, w1)"," right(b, w)"')'," right(c, w65)')'; say; return</lang>
head: #= 0; parse arg d,uq,s; @= ','; call dAng; say center(ang, 65, '═'); return
show: #=#+1; arg p; if p>0 then say ' ('right(a,w)@ right(b,w)@ right(c,w)")"; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
s1: call head 120,,s1 /*────────── 120º: a² + b² + ab ≡ c² */
do a=1 for s1; ap1= a + 1
do b=ap1 for s1-ap1+1; x= @.a + @.b + a*b; if x>ss then iterate a
do c=b+1 for s1-b+1 until @.c>x
if x==@.c then do; call show os1; iterate b; end
end /*c*/
end /*b*/
end /*a*/
call foot s1; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
s2: call head 90,,s2 /*────────── 90º: a² + b² ≡ c² */
do a=1 for s2; ap1= a + 1
do b=ap1 for s2-ap1+1; x= @.a + @.b; if x>ss then iterate a
do c=b+1 for s2-b+2 until @.c>x
if x==@.c then do; call show os2; iterate b; end
end /*c*/
end /*b*/
end /*a*/
call foot s2; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
s3: call head 60,,s3 /*────────── 60º: a² + b² ─ ab ≡ c² */
do a=1 for s3; s3ma= s3 - a + 1
do b=a for s3ma; x= @.a + @.b - a*b; if x>ss then iterate a
do c=a for s3ma until @.c>x
if x==@.c then do; call show os3; iterate b; end
end /*c*/
end /*b*/
end /*a*/
call foot s2; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
s4: call head 60, 'unique', os4 /*────────── 60º: a² + b² ─ ab ≡ c² */
do a=1 for s4; ap1= a + 1; s4map1= s4 - ap1 + 1
do b=ap1 for s4map1; x= @.a + @.b - a*b; if x>ss then iterate a
do c=ap1 for s4map1 until @.c>x
if x==@.c then do; call show os4; iterate b; end
end /*c*/
end /*b*/
end /*a*/
call foot s4; return</lang>
{{out|output|text=&nbsp; when using the default number of sides for the input: &nbsp; &nbsp; <tt> 13 </tt>}}
<pre>
Line 1,937 ⟶ 1,954:
15 solutions found for 60º (sides up to 13)
</pre>
 
===using memoization===
<lang rexx>/*REXX pgm finds integer sided triangles that satisfy Law of cosines for 60º, 90º, 120º.*/
parse arg s1 s2 s3 s4 . /*obtain optional arguments from the CL*/
if s1=='' | s1=="," then s1= 13 /*Not specified? Then use the default.*/
if s2=='' | s2=="," then s2= 13 /* " " " " " " */
if s3=='' | s3=="," then s3= 13 /* " " " " " " */
if s4=='' | s4=="," then s4= -10000 /* " " " " " " */
parse value s1 s2 s3 s4 with os1 os2 os3 os4 . /*obtain the original values for sides.*/
s1=abs(s1); s2=abs(s2); s3=abs(s3); s4=abs(s4) /*use absolute values for the # sides. */
@.=
do j=1 for max(s1, s2, s3, s4); @.j = j*j
end /*j*/ /*build memoization array for squaring.*/
 
if s1>0 then do; call head 120,,os1 /*────120º: a² + b² + ab ≡ c² */
do a=1 for s1
do b=a+1 to s1; x= @.a + @.b + a*b
if x>z then iterate a
do c=b+1 to s1 until @.c>x
if x==@.c then do; call show; iterate b; end
end /*c*/
end /*b*/
end /*a*/
call foot s1
end
 
if s2>0 then do; call head 90,, os2 /*────90º: a² + b² ≡ c² */
do a=1 for s2
do b=a+1 to s2; x= @.a + @.b
if x>z then iterate a
do c=b+1 to s2 until @.c>x
if x==@.c then do; call show; iterate b; end
end /*c*/
end /*b*/
end /*a*/
call foot s2
end
 
if s3>0 then do; call head 60,, os3 /*────60º: a² + b² ─ ab ≡ c² */
do a=1 for s3
do b=a to s3; x= @.a + @.b - a*b
if x>z then iterate a
do c=a to s3 until @.c>x
if x==@.c then do; call show; iterate b; end
end /*c*/
end /*b*/
end /*a*/
call foot s3
end
 
if s4>0 then do; call head 60, 'unique', os4 /*────60º: a² + b² ─ ab ≡ c² */
do a=1 for s4
do b=a to s4; x= @.a + @.b - a*b
if x>z then iterate a
do c=a to s4 until @.c>x
if x==@.c then do; if a==b&a==c then iterate b
call show; iterate b
end
end /*c*/
end /*b*/
end /*a*/
call foot s4
end
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
foot: say right(# ' solutions found for' ang "(sides up to" arg(1)')', 65); say; return
head: #=0; arg d,,s;z=s*s;w=length(s); ang=' 'd"º " arg(2); say center(ang,65,'═'); return
show: #= # + 1; if s>0 then say ' ('right(a,w)"," right(b,w)"," right(c,w)')'; return</lang>
{{out|output|text= &nbsp; when using the inputs of: &nbsp; &nbsp; <tt> 0 &nbsp; 0 &nbsp; 0 &nbsp; -10000 </tt>}}
 
Note that the first three computations are bypassed because of the three zero ('''0''') numbers, &nbsp; the negative ten thousand indicates to find all the triangles with sides up to 10,000, &nbsp; but not list the triangles, it just reports the &nbsp; ''number'' &nbsp; of trianglessolutions found.
<pre>
══════════════════════════ 60º unique═══════════════════════════
1839418,394 solutions found for 60º unique (sides up to 1000010,000)
</pre>