Here's my binary search solution. It can return negative values
(extra credit) and returns nil for undefined behavior.
require "enumerator"
require "rubygems"
require "facets/numeric/round"
def npv(irr, cash_flows)
cash_flows.enum_with_index.inject(0) do |sum, (c_t, t)|
sum + c_t / (1+irr)**t
end
end
def irr(cash_flows, precision=3D10 ** -4)
# establish an upper bound, return nil if none
max =3D 1.0
max *=3D 2 until npv(max, cash_flows) < 0 or max.infinite?
return nil if max.infinite?
# initialize search variables
last_irr, irr, radius =3D max, 0.0, max
# binary search until precision is met
until irr.approx?(last_irr, precision/10)
last_irr =3D irr
# improve approximation of irr
if npv(irr, cash_flows) < 0
irr -=3D radius
else
irr +=3D radius
end
# reduce the search space by half
radius /=3D 2
end
irr.round_to(precision)
end
if __FILE__ =3D=3D $PROGRAM_NAME
puts irr(ARGV.map { |e| Float(e) }) || "Undefined"
end
On Feb 8, 6:01 am, Ruby Quiz <ja... / grayproductions.net> wrote:
> The three rules of RubyQuiz:
>
> 1. Please do not post any solutions or spoiler discussion for thisquizunt=
il
> 48 hours have passed from the time on this message.
>
> 2. Support RubyQuizby submitting ideas as often as you can:
>
> http://www.rubyquiz.com/
>
> 3. Enjoy!
>
> Suggestion: A [QUIZ] in the subject of emails about the problem helps eve=
ryone
> on Ruby Talk follow the discussion. Please reply to the originalquizmessa=
ge,
> if you can.
>
> -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=
=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=
=3D-=3D-=3D
>
> by Harrison Reiser
>
> Internal Rate of Return (IRR -http://en.wikipedia.org/wiki/Internal_rate_o=
f_return) is a common financial
> metric, used by investment firms to predict the profitability of a company=
or
> project. Finding the IRR of a company amounts to solving for it in the equ=
ation
> for Net Present Value (NPV -http://en.wikipedia.org/wiki/Net_present_value=
),
> another valuable decision-making metric:
>
> N C_t
> NPV =3D =D3 ------------
> t=3D0 (1 + IRR)**t
>
> This week'squizis to calculate the IRR for any given variable-length list =
of
> numbers, which represent yearly cash flows, the C_t's in the formula above=
: C_0,
> C_1, etc. (C_0 is typically a negative value, corresponding to the initial=
> investment into the project.) From the example in the Wikipedia article
> (http://en.wikipedia.org/wiki/Internal_rate_of_return), for instance, you =
should
> be able to produce a rate of 17.09% (to four decimal places, let's say) fr=
om
> this or a similar command:
>
> irr([-100,+30,+35,+40,+45])
> =3D> 0.1709...
>
> Keep in mind that an IRR greater than 100% is possible. Extra credit if yo=
u can
> also correctly handle input that produces negative rates, disregarding the=
fact
> that they make no sense.