Reputation: 8131
What is the best way to construct a program in Ruby that solves for the different types of triangles: specifically AAS, ASA, SAS, SSA, and SSS triangles.
There are only three different solutions: using the law of sines, law of cosines and all angles add up to 180.
I've been playing around with different implementations of this, but I can't find a good clean way to make this nice and DRY.
I'm currently doing something like this:
def solve
#AA
!self.A && self.B && self.C ? self.A = 180 - (self.B + self.C) : false
!self.B && self.A && self.C ? self.B = 180 - (self.A + self.C) : false
!self.C && self.B && self.A ? self.C = 180 - (self.B + self.A) : false
#AAS
!self.a && self.A && self.C && self.c ? self.a = (self.c * Math.sin(self.A.degrees))/Math.sin(self.C.degrees) : false
!self.b && self.B && self.C && self.c ? self.b = (self.c * Math.sin(self.B.degrees))/Math.sin(self.C.degrees) : false
end
Essentially what I end up doing is having a list of all possible ways to solve it, loop through them and grab the first one that is solvable. Then loop through again and take a second stab at it until no solutions can be found. But it isn't DRY at all.
How would you attack this?
Upvotes: 2
Views: 678
Reputation: 6076
Okay, here is a more complete solution - no looping though:
class Triangle
def initialize( options )
@angles = [options[:alpha], options[:beta], options[:gamma]]
@sides = [options[:a], options[:b], options[:c]]
end
def solve
# AA
if @angles.one?( &:nil? )
@angles[@angles.index( nil )] = 180 - @angles.compact.inject( &:+ )
end
# AAS
(0..2).each do |i|
if !@sides[i] && @angles[i]
(0..2).each do |j|
if @angles[j] && @sides[j]
@sides[i] = ( @sides[j] * Math.sin( @angles[i] ).abs ) / Math.sin( @angles[j] ).abs
end
end
end
end
# ...
puts @angles.to_s
puts @sides.to_s
end
end
t = Triangle.new :alpha => 62, :beta => 35, :a => 7
t.solve
[62, 35, 83]
[7, 4.054866015928188, 9.170357476093628]
Upvotes: 1