Recently I challenged my co-worker to write an algorithm to solve this problem:
Find the least number of coins required that can make any change from
A vb version
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
For saleAMT As Decimal = 0.01D To 0.99D Step 0.01D
Dim foo As New CashDrawer(0, 0, 0)
Dim chg As List(Of Money) = foo.MakeChange(saleAMT, 1D)
Dim t As Decimal = 1 - saleAMT
Debug.WriteLine(t.ToString("C2"))
For Each c As Money In chg
Debug.WriteLine(String.Format("{0} of {1}", c.Count.ToString("N0"), c.moneyValue.ToString("C2")))
Next
Next
End Sub
Class CashDrawer
Private _drawer As List(Of Money)
Public Sub New(Optional ByVal QTYtwoD As Integer = -1, _
Optional ByVal QTYoneD As Integer = -1, _
Optional ByVal QTYfifty As Integer = -1, _
Optional ByVal QTYquarters As Integer = -1, _
Optional ByVal QTYdimes As Integer = -1, _
Optional ByVal QTYnickels As Integer = -1, _
Optional ByVal QTYpennies As Integer = -1)
_drawer = New List(Of Money)
_drawer.Add(New Money(2D, QTYtwoD))
_drawer.Add(New Money(1D, QTYoneD))
_drawer.Add(New Money(0.5D, QTYfifty))
_drawer.Add(New Money(0.25D, QTYquarters))
_drawer.Add(New Money(0.1D, QTYdimes))
_drawer.Add(New Money(0.05D, QTYnickels))
_drawer.Add(New Money(0.01D, QTYpennies))
End Sub
Public Function MakeChange(ByVal SaleAmt As Decimal, _
ByVal amountTendered As Decimal) As List(Of Money)
Dim change As Decimal = amountTendered - SaleAmt
Dim rv As New List(Of Money)
For Each c As Money In Me._drawer
change -= (c.NumberOf(change) * c.moneyValue)
If c.Count > 0 Then
rv.Add(c)
End If
Next
If change <> 0D Then Throw New ArithmeticException
Return rv
End Function
End Class
Class Money
'-1 equals unlimited qty
Private _qty As Decimal 'quantity in drawer
Private _value As Decimal 'value money
Private _count As Decimal = 0D
Public Sub New(ByVal theValue As Decimal, _
ByVal theQTY As Decimal)
Me._value = theValue
Me._qty = theQTY
End Sub
ReadOnly Property moneyValue As Decimal
Get
Return Me._value
End Get
End Property
Public Function NumberOf(ByVal theAmount As Decimal) As Decimal
If (Me._qty > 0 OrElse Me._qty = -1) AndAlso Me._value <= theAmount Then
Dim ct As Decimal = Math.Floor(theAmount / Me._value)
If Me._qty <> -1D Then 'qty?
'limited qty
If ct > Me._qty Then 'enough
'no
Me._count = Me._qty
Me._qty = 0D
Else
'yes
Me._count = ct
Me._qty -= ct
End If
Else
'unlimited qty
Me._count = ct
End If
End If
Return Me._count
End Function
ReadOnly Property Count As Decimal
Get
Return Me._count
End Get
End Property
End Class
End Class