目錄
題目描述
請實現微信拼手氣紅包算法,輸入紅包總額,輸出紅包抽取後的數值序列,算法考慮公平性、隨機性。題目答案要求:總和爲金額數,個數爲紅包數,單個金額不小於0.01,取兩位小數。
解決方案
如果0.01 * 紅包個數大於總金額,這種情況下錢不夠分。
對每一個搶到的紅包預先分配0.01元,分配後剩下的金額爲:總金額 - 0.01 * 紅包個數。利用循環將每一個紅包隨機的從剩下的金額池中選取一個隨機數,將該隨機數作爲搶到的金額與預分配0.01相加即爲最終的結果。
爲了完全保證公平性,在返回最終序列之前,需要將序列打亂(因爲在上述的隨機從金額池抽取的過程中,會出現前幾個紅包將金額池瓜分完,導致後面的紅包全部是0.01,因此不能保證完全的公平)。
代碼
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("請輸入總金額:")
amountBytes, _, _ := reader.ReadLine()
amount, err := strconv.ParseFloat(string(amountBytes), 10)
if err != nil {
fmt.Println("請輸入合法的總金額格式。")
return
}
fmt.Print("請輸入紅包個數:")
numberBytes, _, _ := reader.ReadLine()
number, err := strconv.Atoi(string(numberBytes))
if err != nil {
fmt.Println("請輸入整數。")
return
}
pool := amount - float64(number)*0.01
if pool < 0 {
fmt.Println("紅包不夠分")
return
}
pool = pool * 100
result := make([]float64, 0)
for i := 0; i < number; i++ {
if i == number-1 {
packet := Decimal(pool*0.01 + 0.01)
result = append(result, packet)
continue
}
packet := rand.Intn(int(pool))
pool = pool - float64(packet)
result = append(result, Decimal(float64(packet)*0.01+0.01))
}
Suffix(&result)
fmt.Println(result)
}
func Decimal(value float64) float64 {
value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
return value
}
func Suffix(list *[]float64) {
length := len(*list)
if length <= 1 {
return
}
for i := 0; i < length; i++ {
randIndex := rand.Intn(length)
(*list)[i], (*list)[randIndex] = (*list)[randIndex], (*list)[i]
}
}
代碼走讀
package main import ( "bufio" "fmt" "math/rand" "os" "strconv" ) func main() { // 從控制檯讀取總金額、紅包個數 reader := bufio.NewReader(os.Stdin) fmt.Print("請輸入總金額:") amountBytes, _, _ := reader.ReadLine() amount, err := strconv.ParseFloat(string(amountBytes), 10) if err != nil { fmt.Println("請輸入合法的總金額格式。") return } fmt.Print("請輸入紅包個數:") numberBytes, _, _ := reader.ReadLine() number, err := strconv.Atoi(string(numberBytes)) if err != nil { fmt.Println("請輸入整數。") return } // 爲每一個紅包預分配0.01元,然後將剩餘的金額放入紅包池中 pool := amount - float64(number)*0.01 if pool < 0 { fmt.Println("紅包不夠分") return } // 將紅包池轉換成以分爲單位的數字 pool = pool * 100 // 爲每一個紅包分配隨機的金額,隨機數分佈在 0 ~ pool result := make([]float64, 0) for i := 0; i < number; i++ { // 如果是最後一個紅包,則將pool內的剩餘金額全部分配 if i == number-1 { packet := Decimal(pool*0.01 + 0.01) result = append(result, packet) continue } packet := rand.Intn(int(pool)) pool = pool - float64(packet) result = append(result, Decimal(float64(packet)*0.01+0.01)) } // 打亂分配結果 Suffix(&result) fmt.Println(result) } // 將一個浮點數保留兩位小數 func Decimal(value float64) float64 { value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64) return value } // 打亂序列 func Suffix(list *[]float64) { length := len(*list) if length <= 1 { return } for i := 0; i < length; i++ { randIndex := rand.Intn(length) (*list)[i], (*list)[randIndex] = (*list)[randIndex], (*list)[i] } }