# 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, :+). – Alex Popov Nov 21 '13 at 10:38
• @AlexPopov: Well, it's just to consider the case f(x) = 0. – tokland Nov 21 '13 at 10:46
• Good point, didn't think about that. – Alex Popov Nov 21 '13 at 10:50
• Btw, if you have zero = Polynomial.new 0, the code throws undefined method reverse' for 0:Fixnum (NoMethodError). – Alex Popov Nov 21 '13 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. – tokland Nov 21 '13 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` – Alex Popov Nov 21 '13 at 9:32
• Yep, it tends to happen. I'd any day prefer my second variation since it makes for an easy reading. – Chandranshu Nov 21 '13 at 9:36