Noah Clark
Noah Clark

Reputation: 8131

Handling triangle solving in Ruby

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

Answers (1)

seph
seph

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

Related Questions