“Develop something useful in under 100 lines of code” contest.

One of my friends was recently asked to write the coolest/cleverest/most creative application in 100 lines of code or less. Any language could be used. It just needs to be creative, legible and easy enough to understand.

Here is my attempt. The program is a loan payment schedule calculator.
The formula to calculate loan payments is M = P * ( J / (1 – (1 + J) ^ -N)).
where
M = payment amount
P = principal, meaning the amount of money borrowed
J = effective interest rate. This is not the annual interest rate.
N = total number of payments
For more details see here .
I have also written several unit tests since I just do not like writing any code without unit tests. The actual code is just 30 lines and the remaining is all unit tests.
I have used the MidpointRounding.AwayFromZero enumeration to round a double to a number to two decimal points.


using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject
{
    public class AmortizationSchedule : IAmortizationSchedule
    {
        public List<AmortizationScheduleRow> Get(double annualPercentageRate,
             double loanAmount, int loanPeriodInYears, DateTime loanStartDate)
        {
            if (annualPercentageRate <= 0 || loanAmount <= 0 || loanPeriodInYears <= 0 ||
                loanStartDate <= DateTime.MinValue)
            {
                throw new ArgumentException("Invalid arguments");
            }

            #region Calculate monthly payment
            const int NoOfMonthsInYear = 12;
            var loanPeriodInMonths = loanPeriodInYears * NoOfMonthsInYear;
            var effectiveInterestRate = annualPercentageRate / (NoOfMonthsInYear * 100);
            var toThePowerOfVariable = Math.Pow(1 + effectiveInterestRate, -loanPeriodInMonths);
            var monthlyPayment = (loanAmount * (effectiveInterestRate / (1 - toThePowerOfVariable)));
            #endregion

            #region Calculate payment schedule based on monthly payment and loan start date
            var amortizationSchedule = new List<AmortizationScheduleRow>();
            var currentMonthCounter = loanStartDate.AddMonths(1);
            var currentBalance = loanAmount;
            double totalInterestAmount = 0;
            for (var counter = 0; counter < loanPeriodInMonths; counter++)
            {
                var interestAmount = effectiveInterestRate * currentBalance;
                totalInterestAmount = totalInterestAmount + interestAmount;
                var amortizationScheduleRow = new AmortizationScheduleRow
                {
                    Date = currentMonthCounter,
                    MonthlyPaymentAmount = monthlyPayment,
                    InterestAmount = interestAmount,
                    TotalInterestAmount = totalInterestAmount
                };
                amortizationSchedule.Add(amortizationScheduleRow);
                currentBalance = currentBalance - amortizationScheduleRow.GetPrincipalAmount();
                currentMonthCounter = currentMonthCounter.AddMonths(1);
            }
            #endregion
            return amortizationSchedule;
        }
    }
    public interface IAmortizationSchedule
    {
        List<AmortizationScheduleRow> Get(double annualPercentageRate, double loanAmount, int loanPeriodInYears, DateTime loanStartDate);
    }
    public class AmortizationScheduleRow
    {
        public double GetMonthlyPaymentAmount()
        {
            return Math.Round(MonthlyPaymentAmount, 2, MidpointRounding.AwayFromZero);
        }
        public double MonthlyPaymentAmount { private get; set; }
        public double GetInterestAmount()
        {
            return Math.Round(InterestAmount, 2, MidpointRounding.AwayFromZero);
        }
        public double InterestAmount { private get; set; }
        public double GetTotalInterestAmount()
        {
            return Math.Round(TotalInterestAmount, 2, MidpointRounding.AwayFromZero);
        }
        public double TotalInterestAmount { private get; set; }
        public double GetPrincipalAmount()
        {
            var principalAmount = MonthlyPaymentAmount - InterestAmount;
            return Math.Round(principalAmount, 2, MidpointRounding.AwayFromZero);
        }
        public string GetDate()
        {
            return Date.ToString("MMM yyyy");
        }
        public DateTime Date { private get; set; }
    }
    [TestClass]
    public class AmortizationScheduleTester
    {
        const double annualPercentageRate = 3.5;
        const double loanAmount = 300000;
        const int loanPeriodInYears = 15;
        readonly DateTime loanStartDate = new DateTime(2016, 7, 1);
        [TestMethod]
        public void GetAmortizationScheduleExceptionTest()
        {
            const int NoOfMonthsInYear = 12;
            var monthlyPaymentSchedule = new AmortizationSchedule().Get(annualPercentageRate, loanAmount,
                loanPeriodInYears, loanStartDate);
            var secondMonthPaymentSchedule = monthlyPaymentSchedule[1];
            Assert.AreEqual(monthlyPaymentSchedule.Count, 15 * NoOfMonthsInYear);
            Assert.AreEqual(secondMonthPaymentSchedule.GetMonthlyPaymentAmount(), 2144.65);
            Assert.AreEqual(secondMonthPaymentSchedule.GetDate(), "Sep 2016");
            Assert.AreEqual(secondMonthPaymentSchedule.GetInterestAmount(), 871.30);
            Assert.AreEqual(secondMonthPaymentSchedule.GetTotalInterestAmount(), 1746.30);
            Assert.AreEqual(secondMonthPaymentSchedule.GetPrincipalAmount(), 1273.35);
        }
        [ExpectedException(typeof(ArgumentException))]
        [TestMethod]
        public void GetAmortizationScheduleExceptionTest1()
        {
            new AmortizationSchedule().Get(0, loanAmount,
                loanPeriodInYears, loanStartDate);
        }

        [ExpectedException(typeof(ArgumentException))]
        [TestMethod]
        public void GetAmortizationScheduleExceptionTest2()
        {
            new AmortizationSchedule().Get(annualPercentageRate, 0,
                loanPeriodInYears, loanStartDate);
        }
        [ExpectedException(typeof(ArgumentException))]
        [TestMethod]
        public void GetAmortizationScheduleExceptionTest3()
        {
            new AmortizationSchedule().Get(annualPercentageRate, loanAmount, 0, loanStartDate);
        }
        [ExpectedException(typeof(ArgumentException))]
        [TestMethod]
        public void GetAmortizationScheduleExceptionTest4()
        {
            new AmortizationSchedule().Get(annualPercentageRate, loanAmount,
                loanPeriodInYears, DateTime.MinValue);
        }
    }
}

Download Solution

You may also like

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.