Skip to content

Instantly share code, notes, and snippets.

@tomphp
Created April 5, 2018 19:04
Show Gist options
  • Save tomphp/1ed6bbd7c6195dbca4d4ddc12d152fd5 to your computer and use it in GitHub Desktop.
Save tomphp/1ed6bbd7c6195dbca4d4ddc12d152fd5 to your computer and use it in GitHub Desktop.
package go_coin_change
func ExampleChange(amount uint) []uint {
result := []uint{}
coins := []uint{10, 5, 2, 1}
for _, coin := range coins {
for amount >= coin {
result = append(result, coin)
amount -= coin
}
}
return result
}
package go_coin_change
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Coin ExampleChange Kata", func() {
Describe("ExampleChange()", func() {
It("returns no coins for 0 amount", func() {
Expect(ExampleChange(0)).To(Equal([]uint{}))
})
It("returns 1 x 1p for amount of 1p", func() {
Expect(ExampleChange(1)).To(Equal([]uint{1}))
})
It("returns 1 x 2p for amount of 2p", func() {
Expect(ExampleChange(2)).To(Equal([]uint{2}))
})
It("returns 1 x 2p an 1 x 1p for amount of 3p", func() {
Expect(ExampleChange(3)).To(Equal([]uint{2, 1}))
})
It("returns 2 x 2p for amount of 4p", func() {
Expect(ExampleChange(4)).To(Equal([]uint{2, 2}))
})
It("returns 1 x 5p for amount of 5p", func() {
Expect(ExampleChange(5)).To(Equal([]uint{5}))
})
It("returns 1 x 10p for amount of 10p", func() {
Expect(ExampleChange(10)).To(Equal([]uint{10}))
})
})
})
package go_coin_change
func PropertyChange(amount uint) []uint {
result := []uint{}
coins := []uint{10, 5, 2, 1}
for _, coin := range coins {
for amount >= coin {
result = append(result, coin)
amount -= coin
}
}
return result
}
package go_coin_change
import (
. "github.com/onsi/ginkgo"
. "github.com/tomphp/go-coin-change/quick"
"reflect"
"math/rand"
)
func sum(xs []uint) uint {
total := uint(0)
for _, x := range xs{
total += x
}
return total
}
func numUniq(xs []uint, search uint) int {
count := 0
for _, x := range xs {
if x == search {
count++
}
}
return count
}
func validCoin(coin uint) bool {
validCoins := []uint{10, 5, 2, 1}
for _, c := range validCoins {
if c == coin {
return true
}
}
return false
}
func validCoins(coins []uint) bool {
for _, coin := range coins {
if ! validCoin(coin) {
return false;
}
}
return true
}
type Amount uint
const MAX_AMOUNT = 1000000
func (_ Amount) Generate(rand *rand.Rand, size int) reflect.Value {
return reflect.ValueOf(Amount(rand.Intn(MAX_AMOUNT)))
}
var _ = Describe("Coin Change Kata", func() {
Describe("PropertyChange()", func() {
It("returns coins which have a total value == amount", Check(func(amount Amount) bool {
return sum(PropertyChange(uint(amount))) == uint(amount)
}))
It("only returns valid coins", Check(func(amount Amount) bool { // Can be checked at the type level
return validCoins(PropertyChange(uint(amount)))
}))
It("never returns more than 1 coin with the value of 1p", Check(func(amount Amount) bool {
return numUniq(PropertyChange(uint(amount)), 1) <= 1
}))
It("never returns more than 2 coins with the value of 2p", Check(func(amount Amount) bool {
return numUniq(PropertyChange(uint(amount)),2) <= 2
}))
It("never returns more than 1 coin with the value of 5p", Check(func(amount Amount) bool {
return numUniq(PropertyChange(uint(amount)),5) <= 1
}))
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment