3
\$\begingroup\$

Here is a calculator for an unknown side in a right-angle. Is there a more efficient way of doing this?

import math
def trigonometry(angle, side_length, known, unknown):
    o, h, a = 'opposite', 'hypotenuse', 'adjacent'
    sohcahtoa = {o: {h: math.sin, a: math.tan},
                 h: {o: math.sin, a: math.cos},
                 a: {o: math.tan, h: math.cos}}
    function = sohcahtoa[known][unknown]
    return side_length / function(math.radians(angle)) if known == 'opposite' or (known == a and unknown == h)\
        else function(math.radians(angle) * side_length)

    print(trigonometry(30, 1, 'opposite', 'hypotenuse'))

I particularly dislike this line as it is basically brute force and very long.

return side_length / function(math.radians(angle)) if known == 'opposite' or (known == a and unknown == h)\
        else function(math.radians(angle) * side_length)

Test Calls

Here are two test calls to make sure the code works.

Call: trigonometry(30, 1, 'opposite', 'hypotenuse') Expected Output: 2

Call: trigonometry(30, 2, 'hypotenuse', 'opposite') Expected Output: 1

\$\endgroup\$
4
\$\begingroup\$
  • You know the equations, but fail to return them in your sohcahtoa dictionary. Take 'soh':

    \$\sin(\theta) = \frac{o}{a}\$
    \$o = a\sin(\theta)\$
    \$a = \frac{o}{\sin(\theta)}\$

    From this you know all the equations, and you know they follow the form op(side, trig_fn(angle)). And so you should expand your sohcahtoa dictionary to contain this too.

  • I'd recommend you make an Enum for opposite, adjacent and hypotenuse, so that you get an actual error, rather than hidden errors, if you mis-spell them. (Yes you should be careful of this.)

  • It doesn't make sense to create sohcahtoa every time you call the function.

And so I'd change to:

from enum import Enum
import math
import operator

class TrigSides(Enum):
    OPPOSITE = 'opposite'
    ADJACENT = 'adjacent'
    HYPOTENUSE = 'hypotenuse'

SOHCAHTOA = {
    TrigSides.OPPOSITE: {
        TrigSides.HYPOTENUSE: (math.sin, operator.truediv),
        TrigSides.ADJACENT: (math.tan, operator.truediv)
    },
    TrigSides.HYPOTENUSE: {
        TrigSides.OPPOSITE: (math.sin, operator.mul),
        TrigSides.ADJACENT: (math.cos, operator.mul)
    },
    TrigSides.ADJACENT: {
        TrigSides.HYPOTENUSE: (math.cos, operator.truediv),
        TrigSides.OPPOSITE: (math.tan, operator.mul)
    }
}

def trigonometry(angle, side, known, unknown):
    trig_fn, op = SOHCAHTOA[known][unknown]
    return op(side, trig_fn(math.radians(angle)))
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.