# Polynomial equation solver in Ruby

I've written a small function for solving simple quadratic equations:

class EquationSolver
def solve(x, *args)
args.reverse.map.with_index { |coefficient, index| coefficient * x ** index }.reduce { |result, element| result + element }
end
end


To calculate f(3) for f(x)=3x3−2x2−x+5, one would write:

puts EquationSolver.new.solve(3, 3, -2, -1, 5)


However, is there a more elegant version of my function, more like reduce.with_index or something similar?

Some notes:

• If you use a OOP approach, it seems more logical to use methods.
• Use arrays to group values that go together.
• I don't think solve is the correct term, that's when you are finding the roots of a function, here you're just evaluating it at a given point.

I'd write:

class Polynomial
attr_accessor :coefficients

def initialize(coefficients)
self.coefficients = coefficients.reverse
end

def evaluate(x)
coefficients.map.with_index { |k, power| k * (x**power) }.reduce(0, :+)
end
end

polynomial = Polynomial.new([3, -2, -1, 5])
puts polynomial.evaluate(3) #=> 65

• Pretty good. Btw, I think you don't need the 0 in reduce(0, :+). Commented Nov 21, 2013 at 10:38
• @AlexPopov: Well, it's just to consider the case f(x) = 0. Commented Nov 21, 2013 at 10:46
• Good point, didn't think about that. Commented Nov 21, 2013 at 10:50
• Btw, if you have zero = Polynomial.new 0, the code throws undefined method reverse' for 0:Fixnum (NoMethodError). Commented Nov 21, 2013 at 10:59
• @Alex: Yes. Personally I don't like this because it makes difficult to add extra arguments. IMHO the coefficients should be grouped, and an array is the most obvious way to do it. Commented Nov 21, 2013 at 14:40

Yes, there is a more elegant version. Here it is:

class EquationSolver
def solve(x, *args)
args.reverse.each_with_index.reduce(0) { |result, (coefficient, index)| result + coefficient * x ** index }
end
end


It's possible to do this because iterator methods like each_with_index, when called without a block, return an Enumerator object on which you can call all the methods of the Enumerable.

In fact, an even shorter solution is obtained by using a variation of reduce to use a symbolic operator:

class EquationSolver
def solve(x, *args)
args.reverse.map.with_index { |coefficient, index| coefficient * x ** index }.inject(:+)
end
end

• 10x, I had figured out the first version you proposed, but I didn't pass a 0 to reduce as a starting parameter, so it was giving me no implicit conversion of Fixnum into Array` Commented Nov 21, 2013 at 9:32
• Yep, it tends to happen. I'd any day prefer my second variation since it makes for an easy reading. Commented Nov 21, 2013 at 9:36