123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- package otherutils
- import (
- "errors"
- "math/rand"
- )
- func init() {
- // rand.Seed(time.Now().UnixNano())
- }
- // RandInterval 随机1个数
- func RandInterval(b1, b2 int64) int64 {
- min, max := normalizeRange(b1, b2)
- return min + rand.Int63n(max-min+1)
- }
- // RandInterval64 随机1个数
- func RandInterval64(b1, b2 int64) int64 {
- min, max := normalizeRange64(b1, b2)
- return min + rand.Int63n(max-min+1)
- }
- func normalizeRange64(b1, b2 int64) (min, max int64) {
- if b1 < b2 {
- return b1, b2
- }
- return b2, b1
- }
- // RandIntervalN 随机生成n个范围在[b1, b2]之间的唯一整数
- // 使用Fisher-Yates洗牌算法
- func RandIntervalN(b1, b2 int64, n int64) []int64 {
- min, max := normalizeRange(b1, b2)
- rangeSize := max - min + 1
- n = limitCount(n, int64(rangeSize))
- if n == 1 {
- return []int64{min + rand.Int63n(max-min+1)}
- }
- return generateUniqueRandomNumbers(min, max, n)
- }
- func normalizeRange(b1, b2 int64) (min, max int64) {
- if b1 < b2 {
- return b1, b2
- }
- return b2, b1
- }
- func limitCount(n int64, rangeSize int64) int64 {
- if n > rangeSize {
- return rangeSize
- }
- return n
- }
- func generateUniqueRandomNumbers(min, max int64, n int64) []int64 {
- result := make([]int64, n)
- usedNumbers := make(map[int64]int64)
- rangeSize := max - min + 1
- for i := int64(0); i < n; i++ {
- randomValue := min + rand.Int63n(rangeSize)
- if replacementValue, exists := usedNumbers[randomValue]; exists {
- result[i] = replacementValue
- } else {
- result[i] = randomValue
- }
- lastValue := max - i
- if randomValue != lastValue {
- if replacementValue, exists := usedNumbers[lastValue]; exists {
- usedNumbers[randomValue] = replacementValue
- } else {
- usedNumbers[randomValue] = lastValue
- }
- }
- rangeSize--
- }
- return result
- }
- type Number interface {
- int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64
- }
- // RandOneNum 随机一个数字
- func RandOneNum[T Number](min, max T) T {
- if min == max {
- return min
- }
- if min > max {
- min, max = max, min
- }
- var result T
- switch any(min).(type) {
- case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
- result = T(rand.Int63n(int64(max-min)) + int64(min))
- case float32, float64:
- result = T(rand.Float64()*(float64(max)-float64(min)) + float64(min))
- default:
- panic("invalid type")
- }
- return result
- }
- // RandChoiceByWeighted 根据权重选取一个元素 [[id,weight]]
- func RandChoiceByWeighted(items [][]int64) int64 {
- var totalWeight int64
- for _, item := range items {
- totalWeight += item[1]
- }
- if totalWeight <= 0 {
- return -1
- }
- // 生成一个0到总权重之间的随机数
- randomNumber := rand.Int63n(totalWeight) + 1
- // 累积权重,直到累积权重超过随机数
- var cumulativeWeight int64
- for _, item := range items {
- cumulativeWeight += item[1]
- if randomNumber <= cumulativeWeight {
- return item[0]
- }
- }
- // 如果没有找到(理论上不会发生),返回0
- return -1
- }
- // type WeightedItem interface {
- // GetWeight() int64
- // }
- type WeightedTable[T any] struct {
- items []T
- totalWeight int64
- getWeight func(T) int64
- }
- func SetWeightedTable[T any](items []T, getWeight func(T) int64) *WeightedTable[T] {
- var totalWeight int64
- for _, item := range items {
- totalWeight += getWeight(item) //item.GetWeight()
- }
- return &WeightedTable[T]{
- items: items,
- totalWeight: totalWeight,
- getWeight: getWeight,
- }
- }
- func (rt *WeightedTable[T]) RandOneItem(reCalcWeight bool) (val T, err error) {
- var item T
- if reCalcWeight {
- var totalWeight int64
- for _, item := range rt.items {
- totalWeight += rt.getWeight(item)
- }
- rt.totalWeight = totalWeight
- }
- if rt.totalWeight <= 0 {
- return item, errors.New("total weight is zero")
- }
- // 生成一个0到总权重之间的随机数
- randomNumber := rand.Int63n(rt.totalWeight) + 1
- // 累积权重,直到累积权重超过随机数
- var cumulativeWeight int64
- for _, item := range rt.items {
- cumulativeWeight += rt.getWeight(item)
- if randomNumber <= cumulativeWeight {
- return item, nil
- }
- }
- // 如果没有找到(理论上不会发生),返回0
- return item, errors.New("not found")
- }
|