Law of cosines - triples: Difference between revisions
(→{{header|Factor}}: fixed a logic error resulting in incorrect output) |
|||
Line 36: | Line 36: | ||
:: triples ( quot -- seq ) |
:: triples ( quot -- seq ) |
||
[ |
[ |
||
V{ } clone :> seen |
|||
13 [1,b] dup dup [ amb-lazy ] tri@ :> ( a b c ) |
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 = |
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 ; |
] bag-of ; |
||
: solutions ( quot -- seq ) |
|||
triples [ natural-sort ] map members { } like ; |
|||
: show-solutions ( quot angle -- ) |
: show-solutions ( quot angle -- ) |
||
[ |
[ triples { } like dup length ] dip rot |
||
"%d solutions for %d degrees:\n%u\n\n" printf ; |
"%d solutions for %d degrees:\n%u\n\n" printf ; |
||
Line 64: | Line 63: | ||
{ 2 2 2 } |
{ 2 2 2 } |
||
{ 3 3 3 } |
{ 3 3 3 } |
||
{ 3 |
{ 3 8 7 } |
||
{ 4 4 4 } |
{ 4 4 4 } |
||
{ 5 5 5 } |
{ 5 5 5 } |
||
{ 5 |
{ 5 8 7 } |
||
{ 6 6 6 } |
{ 6 6 6 } |
||
{ 7 7 7 } |
{ 7 7 7 } |
Revision as of 14:31, 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:
A² + B² - 2ABcos(γ) = C²
- Specific angles
For an angle of of 90° this becomes the more familiar "Pythagoras equation:
A² + B² = C²
For an angle of 60° this becomes the less familiar equation:
A² + B² - AB = C²
And finally for an angle of 120° this becomes the equation:
A² + B² + AB = C²
- 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