Law of cosines - triples: Difference between revisions
m (→{{header|REXX}}: corrected calculations for width of various side lengths.) |
m (→{{header|REXX}}: added checks to see if computations are needed when some angles are skipped.) |
||
Line 179: | Line 179: | ||
This REXX version used some optimization. |
This REXX version used some optimization. |
||
<lang rexx>/*REXX pgm finds integer sided triangles that satisfy Law of cosines for 60º, 90º, 120º.*/ |
<lang rexx>/*REXX pgm finds integer sided triangles that satisfy Law of cosines for 60º, 90º, 120º.*/ |
||
parse arg |
parse arg s1 s2 s3 . /*obtain optional arguments from the CL*/ |
||
if |
if s1=='' | s1=="," then s1= 13 /*Not specified? Then use the default.*/ |
||
if |
if s2=='' | s2=="," then s2= s1 /* " " " " " " */ |
||
if |
if s3=='' | s3=="," then s3= s2 /* " " " " " " */ |
||
w= max(length( |
w= max( length(s1), length(s2), length(s3) ) /*W is used to align the side lengths.*/ |
||
⚫ | |||
if s1>0 then do; call head 120 /*title for 120º: a² + b² + ab == c² */ |
|||
do |
do a=1 for s1; aa = a*a |
||
do |
do b=a+1 to s1; x= aa + b*b + a*b |
||
do c=b+1 to s1; if x==c*c then call show |
|||
end /*c*/ |
|||
end /*b*/ |
|||
⚫ | |||
call foot sides1 |
|||
call foot s1 |
|||
end |
|||
⚫ | |||
if s2>0 then do; call head 90 /*title for 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; if x==c*c then call show |
|||
end /*c*/ |
|||
call foot sides2 |
|||
end /*b*/ |
|||
end /*a*/ |
|||
call foot s2 |
|||
end |
|||
⚫ | |||
⚫ | |||
if s3>0 then do; call head 60 /*title for 60º: a² + b² - ab == c² */ |
|||
do a=1 for s3; aa = a*a |
|||
⚫ | |||
call foot sides3 |
|||
⚫ | |||
end /*c*/ |
|||
⚫ | |||
end /*a*/ |
|||
call foot s3 |
|||
end |
|||
exit /*stick a fork in it, we're all done. */ |
exit /*stick a fork in it, we're all done. */ |
||
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
/*──────────────────────────────────────────────────────────────────────────────────────*/ |
Revision as of 17:44, 23 September 2018
The Law of cosines states that for an angle γ, (gamma) of any triangle, if the sides adjacent to the angle are A and B and the side opposite is C; then the lengths of the sides are related by this formula:
A2 + B2 - 2ABcos(γ) = C2
- Specific angles
For an angle of of 90º this becomes the more familiar "Pythagoras equation":
A2 + B2 = C2
For an angle of 60º this becomes the less familiar equation:
A2 + B2 - AB = C2
And finally for an angle of 120º this becomes the equation:
A2 + B2 + AB = C2
- Task
- Find all integer solutions to the three specific cases, in order; distinguishing between each angle being considered.
- Restrain all sides to the integers 1..13 inclusive.
- Show how many results there are for each angle.
- Display results on this page.
- Optional Extra credit
- How many 60° integer triples are there for sides in the range 1..10_000 where the sides are not all of the same length.
- Related Task
- See also
- Visualising Pythagoras: ultimate proofs and crazy contortions Mathlogger Video
Factor
<lang factor>USING: backtrack formatting kernel locals math math.ranges sequences sets sorting ; IN: rosetta-code.law-of-cosines
- triples ( quot -- seq )
[ V{ } clone :> seen 13 [1,b] dup dup [ amb-lazy ] tri@ :> ( a b c ) a sq b sq + a b quot call( x x x -- x ) c sq = { b a c } seen member? not and must-be-true { a b c } dup seen push ] bag-of ;
- show-solutions ( quot angle -- )
[ triples { } like dup length ] dip rot "%d solutions for %d degrees:\n%u\n\n" printf ;
[ * + ] 120 [ 2drop 0 - ] 90 [ * - ] 60 [ show-solutions ] 2tri@</lang>
- Output:
2 solutions for 120 degrees: { { 3 5 7 } { 7 8 13 } } 3 solutions for 90 degrees: { { 3 4 5 } { 5 12 13 } { 6 8 10 } } 15 solutions for 60 degrees: { { 1 1 1 } { 2 2 2 } { 3 3 3 } { 3 8 7 } { 4 4 4 } { 5 5 5 } { 5 8 7 } { 6 6 6 } { 7 7 7 } { 8 8 8 } { 9 9 9 } { 10 10 10 } { 11 11 11 } { 12 12 12 } { 13 13 13 } }
Haskell
<lang haskell>import Data.List (groupBy, nub, sort, sortBy) import Data.Ord (comparing) import Data.Function (on) import Data.Monoid ((<>)) import Control.Arrow (second)
triplesFound :: Int -> [(Int, [(Int, Int)])] triplesFound n =
let xs = ((,) <*> (^ 2)) <$> [1 .. n] :: [(Int, Int)] in xs >>= \x -> xs >>= \y -> xs >>= \z -> let d = snd z - (snd x + snd y) in if 0 == d then [(90, [x, y, z])] else if (fst x * fst y) == abs d then if 0 < d then [(60, [x, y, z])] else [(120, [x, y, z])] else []
showTriples :: [(Int, [(Int, Int)])] -> String showTriples xs =
unlines $ zipWith (\n vs -> '\n' : show (length vs) <> " solutions for " <> show n <> " degrees:\n" <> show vs) [120, 90, 60] $ (nub . fmap (sort . snd)) <$> groupBy (on (==) fst) (second (fmap fst) <$> sortBy (comparing fst) xs)
main :: IO () main = putStrLn $ showTriples (triplesFound 13)</lang>
- Output:
2 solutions for 120 degrees: [[3,5,7],[7,8,13]] 3 solutions for 90 degrees: [[3,4,5],[5,12,13],[6,8,10]] 15 solutions for 60 degrees: [[1,1,1],[2,2,2],[3,3,3],[3,7,8],[4,4,4],[5,5,5],[5,7,8],[6,6,6],[7,7,7],[8,8,8],[9,9,9],[10,10,10],[11,11,11],[12,12,12],[13,13,13]]
Python
<lang>N = 13
def method1(N=N):
squares = [x**2 for x in range(0, N+1)] sqrset = set(squares) tri90, tri60, tri120 = (set() for _ in range(3)) for a in range(1, N+1): a2 = squares[a] for b in range(1, a + 1): b2 = squares[b] c2 = a2 + b2 if c2 in sqrset: tri90.add(tuple(sorted((a, b, int(c2**0.5))))) continue ab = a * b c2 -= ab if c2 in sqrset: tri60.add(tuple(sorted((a, b, int(c2**0.5))))) continue c2 += 2 * ab if c2 in sqrset: tri120.add(tuple(sorted((a, b, int(c2**0.5))))) return sorted(tri90), sorted(tri60), sorted(tri120)
- %%
if __name__ == '__main__':
print(f'Integer triangular triples for sides 1..{N}:') for angle, triples in zip([90, 60, 120], method1(N)): print(f' {angle:3}° has {len(triples)} solutions:\n {triples}') _, t60, _ = method1(10_000) notsame = sum(1 for a, b, c in t60 if a != b or b != c) print('Extra credit:', notsame)</lang>
- Output:
Integer triangular triples for sides 1..13: 90° has 3 solutions: [(3, 4, 5), (5, 12, 13), (6, 8, 10)] 60° has 15 solutions: [(1, 1, 1), (2, 2, 2), (3, 3, 3), (3, 7, 8), (4, 4, 4), (5, 5, 5), (5, 7, 8), (6, 6, 6), (7, 7, 7), (8, 8, 8), (9, 9, 9), (10, 10, 10), (11, 11, 11), (12, 12, 12), (13, 13, 13)] 120° has 2 solutions: [(3, 5, 7), (7, 8, 13)] Extra credit: 17806
REXX
This REXX version used some optimization. <lang rexx>/*REXX pgm finds integer sided triangles that satisfy Law of cosines for 60º, 90º, 120º.*/ parse arg s1 s2 s3 . /*obtain optional arguments from the CL*/ if s1== | s1=="," then s1= 13 /*Not specified? Then use the default.*/ if s2== | s2=="," then s2= s1 /* " " " " " " */ if s3== | s3=="," then s3= s2 /* " " " " " " */ w= max( length(s1), length(s2), length(s3) ) /*W is used to align the side lengths.*/
if s1>0 then do; call head 120 /*title for 120º: a² + b² + ab == c² */
do a=1 for s1; aa = a*a do b=a+1 to s1; x= aa + b*b + a*b do c=b+1 to s1; if x==c*c then call show end /*c*/ end /*b*/ end /*a*/ call foot s1 end
if s2>0 then do; call head 90 /*title for 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; if x==c*c then call show end /*c*/ end /*b*/ end /*a*/ call foot s2 end
if s3>0 then do; call head 60 /*title for 60º: a² + b² - ab == c² */
do a=1 for s3; aa = a*a do b=a for s3; x= aa + b*b - a*b do c=b for s3; if x==c*c then call show end /*c*/ end /*b*/ end /*a*/ call foot s3 end
exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ foot: say right(# ' solutions found for' angle "(sides up to" arg(1)')', 65); say; return head: #= 0; angle= ' 'arg(1)"º "; say center(angle, 65, '═'); return show: #= # + 1; say ' ('right(a, w)"," right(b, w)"," right(c, w)')'; return</lang>
- output when using the default number of sides for the input: 13
═════════════════════════════ 120º ══════════════════════════════ ( 3, 5, 7) ( 7, 8, 13) 2 solutions found for 120º (sides up to 13) ══════════════════════════════ 90º ══════════════════════════════ ( 3, 4, 5) ( 5, 12, 13) ( 6, 8, 10) 3 solutions found for 90º (sides up to 13) ══════════════════════════════ 60º ══════════════════════════════ ( 1, 1, 1) ( 2, 2, 2) ( 3, 3, 3) ( 4, 4, 4) ( 5, 5, 5) ( 6, 6, 6) ( 7, 7, 7) ( 8, 8, 8) ( 9, 9, 9) (10, 10, 10) (11, 11, 11) (12, 12, 12) (13, 13, 13) 13 solutions found for 60º (sides up to 13)