0
\$\begingroup\$

This challenge I am working on involves checking the sides of a triangle and returning the type of triangle as a symbol.

For example, :equilateral if all sides are equal, :scalene if the sides are all different, and :isoseles if two sides are the same.

Here is my thought process: I want to make something that doesn't involve a bunch of if/else or case statements. To achieve this, I thought that using math would help. Now, my math isn't that great, so I had to research cosine and make an algorithm to return angles A,B, and C.

First, I know this isn't required. I don't need the angles, but I thought it would help me avoid too many statements. However, I couldn't figure out what to do after this step.

Below is my code. It works, but I feel like it's kind of tacky. I know I could do better, but I'm facing a wall here. Any input?

def triangle(one, two, three)
  is_valid_triangle?(one,two,three)
end

def is_valid_triangle?(one,two,three)
  sides = [one,two,three].sort
  if (sides[0] + sides[1] <= sides[2]) || (sides[0] == 0)
    return "invalid!"
  else
    which_triangle?(one,two,three)
  end
end

def which_triangle?(one,two,three)
  triangles = {equilateral: [60,60,60], isosceles: [0], scalene: [0]}
  angle_a = (Math.acos((two**2+three**2-one**2)/(2*two*three).to_f)*180/Math::PI).round(2)
  angle_b = (Math.acos((three**2+one**2-two**2)/(2*three*one).to_f)*180/Math::PI).round(2)
  angle_c = (Math.acos((one**2+two**2-three**2)/(2*one*two).to_f)*180/Math::PI).round(2)
  if angle_a && angle_b == 60
    return :equilateral, triangles[:equilateral]
  elsif angle_a != angle_b && angle_b != angle_c
    triangles[:scalene] = [angle_a, angle_b, angle_c]
    return :scalene, triangles[:scalene]
  else
    triangles[:isosceles] = [angle_a, angle_b, angle_c]
    return :isosceles, triangles[:isosceles]
  end
end

p triangle(30,23,10)
p triangle(3,3,3)
p triangle(1.5,3,3)
p triangle(3,4,5)
p triangle(0,3,3)
p triangle(3,1,1)
\$\endgroup\$
  • 2
    \$\begingroup\$ You seriously think this looks simpler than checking lengths of three sides? It probably takes two lines of code to do it. \$\endgroup\$ – Stack crashed Oct 28 '17 at 5:09
  • 2
    \$\begingroup\$ If a==b and b==c: return type1 elif a==b or b==c or a==c: return type2 return type3 \$\endgroup\$ – Stack crashed Oct 28 '17 at 5:13
  • \$\begingroup\$ @Stackcrashed I understand that my way isn't simpler, I'm just trying to figure out a better way to do it without using if, elif statements. Unless there isn't any better way to do it. \$\endgroup\$ – Nathan Oct 29 '17 at 1:20
  • \$\begingroup\$ Please see What to do when someone answers. I have rolled back Rev 3 → 2. \$\endgroup\$ – 200_success Oct 29 '17 at 2:55
  • 2
    \$\begingroup\$ Note that @Stackcrashed's method works without elif since you are doing an early return. \$\endgroup\$ – Barry Carter Oct 29 '17 at 16:56
2
\$\begingroup\$

For triangle(3, 2, 3), the resulting classification is wrong:

[:scalene, [70.53, 38.94, 70.53]]

When you take into consideration all of the different pairs of angles you have to test, you are no better off comparing angles than comparing side lengths. In fact, this approach is worse, with extra computation and loss of precision due to rounding.

\$\endgroup\$
  • \$\begingroup\$ Thank you, I didn't catch this earlier. \$\endgroup\$ – Nathan Oct 29 '17 at 1:18

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.