coin math
This commit is contained in:
parent
2d45058352
commit
7967c1df75
|
@ -19,6 +19,11 @@ func (coin Coin) String() string {
|
|||
return fmt.Sprintf("%v%v", coin.Amount, coin.Denom)
|
||||
}
|
||||
|
||||
// SameDenomAs returns true if the two coins are the same denom
|
||||
func (coin Coin) SameDenomAs(other Coin) bool {
|
||||
return (coin.Denom == other.Denom)
|
||||
}
|
||||
|
||||
// IsZero returns if this represents no money
|
||||
func (coin Coin) IsZero() bool {
|
||||
return coin.Amount == 0
|
||||
|
@ -27,8 +32,38 @@ func (coin Coin) IsZero() bool {
|
|||
// IsGTE returns true if they are the same type and the receiver is
|
||||
// an equal or greater value
|
||||
func (coin Coin) IsGTE(other Coin) bool {
|
||||
return (coin.Denom == other.Denom) &&
|
||||
(coin.Amount >= other.Amount)
|
||||
return coin.SameDenomAs(other) && (coin.Amount >= other.Amount)
|
||||
}
|
||||
|
||||
// IsEqual returns true if the two sets of Coins have the same value
|
||||
func (coin Coin) IsEqual(other Coin) bool {
|
||||
return coin.SameDenomAs(other) && (coin.Amount == other.Amount)
|
||||
}
|
||||
|
||||
// IsPositive returns true if coin amount is positive
|
||||
func (coin Coin) IsPositive() bool {
|
||||
return (coin.Amount > 0)
|
||||
}
|
||||
|
||||
// IsNotNegative returns true if coin amount is not negative
|
||||
func (coin Coin) IsNotNegative() bool {
|
||||
return (coin.Amount >= 0)
|
||||
}
|
||||
|
||||
// Adds amounts of two coins with same denom
|
||||
func (coin Coin) Plus(coinB Coin) Coin {
|
||||
if !coin.SameDenomAs(coinB) {
|
||||
return coin
|
||||
}
|
||||
return Coin{coin.Denom, coin.Amount + coinB.Amount}
|
||||
}
|
||||
|
||||
// Subtracts amounts of two coins with same denom
|
||||
func (coin Coin) Minus(coinB Coin) Coin {
|
||||
if !coin.SameDenomAs(coinB) {
|
||||
return coin
|
||||
}
|
||||
return Coin{coin.Denom, coin.Amount - coinB.Amount}
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
@ -55,14 +90,14 @@ func (coins Coins) IsValid() bool {
|
|||
case 0:
|
||||
return true
|
||||
case 1:
|
||||
return coins[0].Amount != 0
|
||||
return !coins[0].IsZero()
|
||||
default:
|
||||
lowDenom := coins[0].Denom
|
||||
for _, coin := range coins[1:] {
|
||||
if coin.Denom <= lowDenom {
|
||||
return false
|
||||
}
|
||||
if coin.Amount == 0 {
|
||||
if coin.IsZero() {
|
||||
return false
|
||||
}
|
||||
// we compare each coin against the last denom
|
||||
|
@ -96,10 +131,7 @@ func (coins Coins) Plus(coinsB Coins) Coins {
|
|||
if coinA.Amount+coinB.Amount == 0 {
|
||||
// ignore 0 sum coin type
|
||||
} else {
|
||||
sum = append(sum, Coin{
|
||||
Denom: coinA.Denom,
|
||||
Amount: coinA.Amount + coinB.Amount,
|
||||
})
|
||||
sum = append(sum, coinA.Plus(coinB))
|
||||
}
|
||||
indexA++
|
||||
indexB++
|
||||
|
@ -168,8 +200,8 @@ func (coins Coins) IsPositive() bool {
|
|||
if len(coins) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, coinAmount := range coins {
|
||||
if coinAmount.Amount <= 0 {
|
||||
for _, coin := range coins {
|
||||
if !coin.IsPositive() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -182,8 +214,8 @@ func (coins Coins) IsNotNegative() bool {
|
|||
if len(coins) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, coinAmount := range coins {
|
||||
if coinAmount.Amount < 0 {
|
||||
for _, coin := range coins {
|
||||
if !coin.IsNotNegative() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,144 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIsPositiveCoin(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cases := []struct {
|
||||
inputOne Coin
|
||||
expected bool
|
||||
}{
|
||||
{Coin{"A", 1}, true},
|
||||
{Coin{"A", 0}, false},
|
||||
{Coin{"a", -1}, false},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
res := tc.inputOne.IsPositive()
|
||||
assert.Equal(tc.expected, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsNotNegativeCoin(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cases := []struct {
|
||||
inputOne Coin
|
||||
expected bool
|
||||
}{
|
||||
{Coin{"A", 1}, true},
|
||||
{Coin{"A", 0}, true},
|
||||
{Coin{"a", -1}, false},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
res := tc.inputOne.IsNotNegative()
|
||||
assert.Equal(tc.expected, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSameDenomAsCoin(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cases := []struct {
|
||||
inputOne Coin
|
||||
inputTwo Coin
|
||||
expected bool
|
||||
}{
|
||||
{Coin{"A", 1}, Coin{"A", 1}, true},
|
||||
{Coin{"A", 1}, Coin{"a", 1}, false},
|
||||
{Coin{"a", 1}, Coin{"b", 1}, false},
|
||||
{Coin{"steak", 1}, Coin{"steak", 10}, true},
|
||||
{Coin{"steak", -11}, Coin{"steak", 10}, true},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
res := tc.inputOne.SameDenomAs(tc.inputTwo)
|
||||
assert.Equal(tc.expected, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsGTECoin(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cases := []struct {
|
||||
inputOne Coin
|
||||
inputTwo Coin
|
||||
expected bool
|
||||
}{
|
||||
{Coin{"A", 1}, Coin{"A", 1}, true},
|
||||
{Coin{"A", 2}, Coin{"A", 1}, true},
|
||||
{Coin{"A", -1}, Coin{"A", 5}, false},
|
||||
{Coin{"a", 1}, Coin{"b", 1}, false},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
res := tc.inputOne.IsGTE(tc.inputTwo)
|
||||
assert.Equal(tc.expected, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsEqualCoin(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cases := []struct {
|
||||
inputOne Coin
|
||||
inputTwo Coin
|
||||
expected bool
|
||||
}{
|
||||
{Coin{"A", 1}, Coin{"A", 1}, true},
|
||||
{Coin{"A", 1}, Coin{"a", 1}, false},
|
||||
{Coin{"a", 1}, Coin{"b", 1}, false},
|
||||
{Coin{"steak", 1}, Coin{"steak", 10}, false},
|
||||
{Coin{"steak", -11}, Coin{"steak", 10}, false},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
res := tc.inputOne.IsEqual(tc.inputTwo)
|
||||
assert.Equal(tc.expected, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlusCoin(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cases := []struct {
|
||||
inputOne Coin
|
||||
inputTwo Coin
|
||||
expected Coin
|
||||
}{
|
||||
{Coin{"A", 1}, Coin{"A", 1}, Coin{"A", 2}},
|
||||
{Coin{"A", 1}, Coin{"B", 1}, Coin{"A", 1}},
|
||||
{Coin{"asdf", -4}, Coin{"asdf", 5}, Coin{"asdf", 1}},
|
||||
{Coin{"asdf", -1}, Coin{"asdf", 1}, Coin{"asdf", 0}},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
res := tc.inputOne.Plus(tc.inputTwo)
|
||||
assert.Equal(tc.expected, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinusCoin(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
cases := []struct {
|
||||
inputOne Coin
|
||||
inputTwo Coin
|
||||
expected Coin
|
||||
}{
|
||||
{Coin{"A", 1}, Coin{"A", 1}, Coin{"A", 0}},
|
||||
{Coin{"A", 1}, Coin{"B", 1}, Coin{"A", 1}},
|
||||
{Coin{"asdf", -4}, Coin{"asdf", 5}, Coin{"asdf", -9}},
|
||||
{Coin{"asdf", 10}, Coin{"asdf", 1}, Coin{"asdf", 9}},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
res := tc.inputOne.Minus(tc.inputTwo)
|
||||
assert.Equal(tc.expected, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoins(t *testing.T) {
|
||||
|
||||
//Define the coins to be used in tests
|
||||
|
|
Loading…
Reference in New Issue