Skip to content

Instantly share code, notes, and snippets.

@tippenein
Created January 24, 2017 00:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tippenein/428d15677b1403d1f94f793f63979a7a to your computer and use it in GitHub Desktop.
Save tippenein/428d15677b1403d1f94f793f63979a7a to your computer and use it in GitHub Desktop.
naive amortization
# naive amortization implementation using enumerators.
# used for a possible answer to compare against candidate solutions
# intended to determine how a candidate breaks up a problem
# similar haskell implementation - https://gist.github.com/tippenein/8dceb2d50272ec24ce13fe83f3a57bfa
module Amortizable
include Enumerable
def estimated_monthly
r = apr / 100 / 12 # percent per period
top = r * (1 + r) ** term
bottom = ((1 + r) ** term) - 1
principal * (top / bottom)
end
def amortization
principal_month_pairs.map do |pair|
Amortization.new(*pair, apr)
end
end
private
def principal_month_pairs
principals = principal_enumerator_from(principal).take(self.term)
months = month_enumerator_from(self.created_at).take(self.term)
principals.zip(months)
end
def principal_enumerator_from(initial_principal)
Enumerator.new do |g|
s = initial_principal
while s > 0 do
next_principal = s - estimated_monthly
g.yield next_principal
s = next_principal
end
end
end
def month_enumerator_from(start)
Enumerator.new do |g|
s = start
loop do
next_month = 1.month.since(s)
g.yield next_month
s = next_month
end
end
end
class Amortization
attr_accessor :date, :principal, :interest, :apr
def initialize(principal, date, apr)
@principal = principal > 0 ? principal : 0
@date = date
@apr = apr
@interest = interest_from(@principal)
end
def interest_from(principal)
apr_percent = apr / 100
(principal * (apr_percent / 365) * 30).round(2)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment