using System.Collections.Generic;
private Dictionary<int, int> _amounts;
private int _totalAmount = 0;
public AtmMachine(Dictionary<int, int> amounts)
foreach (var i in _amounts)
this._totalAmount += i.Key * i.Value;
public List<Tuple<int, int>> Withdraw(int amount)
var amountsCopy = new Dictionary<int, int>(_amounts);
var solution = new List<Tuple<int, int>> { };
if (_totalAmount >= amount && amount > 0)
foreach (var item in _amounts.OrderByDescending(i => i.Key))
while (amount >= item.Key && _amounts[item.Key] > 0)
solution.Add(Tuple.Create(item.Key, noOfBills));
return new List<Tuple<int, int>> { };
public class VersionComparer
public int CmpDigits(int firstNr, int secondNr)
while (secondNr != 0 || firstNr != 0)
if (firstNr % 10 > secondNr % 10)
if (secondNr % 10 > firstNr % 10)
return (firstNr > secondNr) ? 1 : (firstNr < secondNr) ? -1 : 0;
public int Compare(string versionOne, string versionTwo)
int versionOneDotIndex = versionOne.IndexOf('.');
int versionTwoDotIndex = versionTwo.IndexOf('.');
int versionOneNumbmer = 0;
if (versionOneDotIndex == -1)
versionOneNumbmer = (versionOne.Length == 0) ? 0 : Int32.Parse(versionOne);
versionOneNumbmer = Int32.Parse(versionOne.Substring(0, versionOneDotIndex));
int versionTwoNumbmer = 0;
if (versionTwoDotIndex == -1)
versionTwoNumbmer = (versionTwo.Length == 0) ? 0 : Int32.Parse(versionTwo);
versionTwoNumbmer = Int32.Parse(versionTwo.Substring(0, versionTwoDotIndex));
if (versionOneDotIndex == -1 || versionTwoDotIndex == -1)
return CmpDigits(versionOneNumbmer, versionTwoNumbmer);
if (CmpDigits(versionOneNumbmer, versionTwoNumbmer) == 0)
return Compare(versionOne.Substring(versionOneDotIndex + 1),
versionTwo.Substring(versionTwoDotIndex + 1)
return CmpDigits(versionOneNumbmer, versionTwoNumbmer);
public static void Main()
private static void Run()
new AtmMachineTests().Start();
new VersionComparerTests().Start();
public class AtmMachineTests
Tests.Run($"{nameof(AtmMachine)} should", (it) =>
it.Should(() => NotProcessNegativeValues(), "Not process negative values");
it.Should(() => ReturnMultipleDenominationAmounts(), "Return multiple denomination amounts");
it.Should(() => NotProcessWithdrawalsWhenInventoryIsSmallerThanRequestedAmount(), "Not process witdrawals greater than inventory");
it.Should(() => ReturnAllAvailableMoney(), "Return all available money");
it.Should(() => KeepStateBetweenWithdrawals(), "Keep state between withdrawals");
it.Should(() => NotChangeStateIfWithdrawalIsntSuccessful(), "Not change state if withdrawal isn't successful");
private int CountMoney(List<Tuple<int, int>> amounts) => amounts.Aggregate(0, (a, i) => a + i.Item1 * i.Item2);
public void NotChangeStateIfWithdrawalIsntSuccessful()
var atm = new AtmMachine(new Dictionary<int, int> { { 1, 5 }, { 5, 5 }, { 10, 5 } });
var r1 = atm.Withdraw(50);
CountMoney(r1).ShouldBe(50);
var r2 = atm.Withdraw(50);
CountMoney(r2).ShouldBe(0);
var r3 = atm.Withdraw(20);
CountMoney(r3).ShouldBe(20);
public void NotProcessNegativeValues()
var atm = new AtmMachine(new Dictionary<int, int> { { 1, 5 } });
var result = atm.Withdraw(-5);
CountMoney(result).ShouldBe(0);
public void KeepStateBetweenWithdrawals()
var atm = new AtmMachine(new Dictionary<int, int> { { 1, 5 }, { 5, 5 } });
var r1 = atm.Withdraw(5);
CountMoney(r1).ShouldBe(5);
var r2 = atm.Withdraw(26);
CountMoney(r2).ShouldBe(0);
public void ReturnAllAvailableMoney()
var atm = new AtmMachine(new Dictionary<int, int> { { 1, 10 }, { 5, 10 }, { 10, 10 }, { 50, 10 }, { 100, 10 }, { 200, 10 }, { 500, 10 } });
var result = atm.Withdraw(8660);
var sum = CountMoney(result);
public void ReturnMultipleDenominationAmounts()
var atm = new AtmMachine(new Dictionary<int, int> { { 1, 10 }, { 5, 10 }, { 10, 10 } });
var result = atm.Withdraw(87);
CountMoney(result).ShouldBe(87);
public void NotProcessWithdrawalsWhenInventoryIsSmallerThanRequestedAmount()
var atm = new AtmMachine(new Dictionary<int, int> { { 1, 10 }, { 5, 10 }, { 10, 10 }, { 50, 10 }, { 100, 10 }, { 200, 10 }, { 500, 10 } });
var result = atm.Withdraw(8661);
CountMoney(result).ShouldBe(0);
public class VersionComparerTests
Tests.Run("VersionComparer should", (it) =>
it.Should(() => CompareEqualVersions(), "Compare equal versions");
it.Should(() => CompareDifferentVersions(), "Compare different versions");
public void CompareEqualVersions()
var comparer = new VersionComparer();
comparer.Compare("0", "0.0.0").ShouldBe(0);
comparer.Compare("0.01", "0.1").ShouldBe(0);
comparer.Compare("1.001", "1.1").ShouldBe(0);
comparer.Compare("7.015.84", "7.15.84").ShouldBe(0);
comparer.Compare("7.1", "7.1.0.0").ShouldBe(0);
public void CompareDifferentVersions()
var comparer = new VersionComparer();
comparer.Compare("01.0.1", "1.1.0").ShouldBe(-1);
comparer.Compare("33.1", "33.0.5").ShouldBe(1);
comparer.Compare("7.0105.84", "7.15.84").ShouldBe(-1);
public static void Run(string testGroup, Action<Tests> tests)
public static void StartTests(string testGroup)
Console.WriteLine("====================================================");
Console.WriteLine(testGroup);
Console.WriteLine("====================================================");
public void Should(Action test, string testName)
Console.WriteLine(testName);
Console.WriteLine(" Passed");
Console.WriteLine(" Failed");
Console.WriteLine(" " + e.Message);
public static void EndTests()