m个人抢一个手气红包
算法思路:
Q(n) = rand(0.01,2*R(n-1)/(m-n)-0.01)
Q(n): 第n个红包的金额
R(n-1): 第n-1个红包分配后的余额
实现思路,将金额最小额度定为1分,输入金额*100为以分为单位的整数
package main
import (
"fmt"
"math/rand"
"time"
)
const (
MaxAmount int = 200 * 100
MinAmount = 1
)
type redPack struct {
Amount int
Number int
}
func NewRedPack(amount int, number int) (*redPack, error) {
if number < 1 {
return nil, fmt.Errorf("number error")
}
if amount < MinAmount*number || amount > MaxAmount*number {
return nil, fmt.Errorf("amount error")
}
return &redPack{
Amount: amount,
Number: number,
}, nil
}
func (rp *redPack) calcArr() []int {
remain := rp.Amount
arr := make([]int, 0, rp.Number)
for i := 0; i < rp.Number; i++ {
if i == rp.Number-1 {
arr = append(arr, remain)
break
}
n := rp.getOne(remain, i)
arr = append(arr, n)
remain -= n
}
return arr
}
func (rp *redPack) getOne(remain int, i int) int {
return 1 + rand.Intn(2*remain/(rp.Number-i)-1)
}
func main() {
rand.Seed(time.Now().UnixNano())
arr := [][2]int{
{1, 1},
{10, 5},
{100, 7},
{10000, 9},
}
for i, v := range arr {
rp, _ := NewRedPack(v[0], v[1])
if rp != nil {
vs := rp.calcArr()
fmt.Println(i, ": ", vs)
if len(vs) != rp.Number {
fmt.Println(i, ": arr len not eq number")
}
s := 0
for j := range vs {
s += vs[j]
}
if s != rp.Amount {
fmt.Println(i, ": total not eq amount")
}
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。