diff --git a/readme.md b/readme.md index dc9a792..c0aab4b 100644 --- a/readme.md +++ b/readme.md @@ -83,6 +83,8 @@ 2021/03/26: 新增全排列的递归实现、字典序实现、递增进制位实现、递减进制位实现 +2021/06/16 新增一个数拆分成N个数且N个数相加和等于这个数工具、测试方法 + # 修复日志 2020/11/23:修改项目案例(按照一定规则对一组数据进行排序分组) diff --git a/util/splitNumToN/README.md b/util/splitNumToN/README.md new file mode 100644 index 0000000..2d9c3e0 --- /dev/null +++ b/util/splitNumToN/README.md @@ -0,0 +1,9 @@ +## 需求 +这里的实际需求是策划案中的掷骰子,先随机得到骰子的总和,再将骰子拆分成三个随机的骰子数,策划案中说明有对出现豹子进行控制,这边不把这个实现做进来 +如果需要进行控制,则在获取结果之后进行控制即可,重新掷骰子的概率不会特别高,因为豹子本身就是一个低概率的事件。 + + +## 实现 +总共两个实现,一个是实际需求中的三个数的拆分 + +另一个是N个数的拆分,这边用Splitter结构体实现,在创建的时候需要进行数字与数量的校验 \ No newline at end of file diff --git a/util/splitNumToN/SpliNumTo3.go b/util/splitNumToN/SpliNumTo3.go new file mode 100644 index 0000000..55942e2 --- /dev/null +++ b/util/splitNumToN/SpliNumTo3.go @@ -0,0 +1,44 @@ +/* + * @Author : huangZJ + * @Time : 2021/6/16 10:50 + * @Description: + */ + +package splitNumToN + +import ( + "Go-Tool/util/rand" + "fmt" +) + +//将一个数拆解成三个 +func SplitNumTo3(num int) { + randNumList := make([]int, 0) + var count int + for i := 0; i < 2; i++ { + randNum := getRandValue(num-count, 3-1-i) + randNumList = append(randNumList, randNum) + count = count + randNum + } + + randNumList = append(randNumList, num-count) + + for _, num := range randNumList { + fmt.Print(fmt.Sprintf("%d ", num)) + } +} + +//num 被随机的数 +//count count + 1 = 总随机数数量 +func getRandValue(num int, count int) int { + minValue := num - 6*count + if minValue <= 0 { + minValue = 1 + } + maxValue := num - count*1 + if maxValue > 6 { + maxValue = 6 + } + + return rand.GetRandInt(minValue, maxValue) +} diff --git a/util/splitNumToN/SplitNumTo3_test.go b/util/splitNumToN/SplitNumTo3_test.go new file mode 100644 index 0000000..920ec17 --- /dev/null +++ b/util/splitNumToN/SplitNumTo3_test.go @@ -0,0 +1,24 @@ +/* + * @Author : huangZJ + * @Time : 2021/6/16 10:52 + * @Description: + */ + +package splitNumToN + +import ( + "fmt" + "testing" +) + +func TestSplitNumTo3(t *testing.T) { + for i := 4; i <= 17; i++ { + fmt.Println() + fmt.Println(fmt.Sprintf("当前随机数为%d", i)) + for j := 0; j < 100; j++ { + fmt.Println() + SplitNumTo3(i) + } + fmt.Println() + } +} diff --git a/util/splitNumToN/SplitNumToN.go b/util/splitNumToN/SplitNumToN.go new file mode 100644 index 0000000..4cdc6fc --- /dev/null +++ b/util/splitNumToN/SplitNumToN.go @@ -0,0 +1,72 @@ +/* + * @Author : huangZJ + * @Time : 2021/6/15 11:20 + * @Description:将一个数拆分成其他N个数,这N个数相加的结果等于这个数 + */ + +package splitNumToN + +import "Go-Tool/util/rand" + +type Splitter struct { + NumCount int //拆分成随机数的数量 + Num int //被拆分的总数 + MinValue int //被拆分的最小值 + MaxValue int //被拆分的最大值 + + SplitNumList []int //存放拆解之后的结果 +} + +func NewSplitter(numCount, num int) *Splitter { + //给定默认的限制的最大最小值 + splitter := &Splitter{ + NumCount: numCount, + Num: num, + MinValue: 1, + MaxValue: 6, + SplitNumList: make([]int, 0), + } + //校验数值是否满足 + splitter.checkValue() + return splitter +} + +func (splitter *Splitter) checkValue() { + if splitter.MinValue*splitter.NumCount > splitter.Num { + panic("被拆分的数值过小") + } + if splitter.MaxValue*splitter.NumCount < splitter.Num { + panic("被拆分的数值过大") + } +} + +//将一个数拆成N个,并且保证N个数相加值等于被拆分的这个数 +func (splitter *Splitter) SplitNumToN() { + var count int + for i := 0; i < splitter.NumCount-1; i++ { + randNum := splitter.getRandValue(splitter.Num-count, splitter.NumCount-1-i) + splitter.SplitNumList = append(splitter.SplitNumList, randNum) + count = count + randNum + } + + splitter.SplitNumList = append(splitter.SplitNumList, splitter.Num-count) +} + +func (splitter *Splitter) GetRandNumList() []int { + return splitter.SplitNumList +} + +//num 被随机的数 +//count count + 1 = 总随机数数量 +func (splitter *Splitter) getRandValue(num int, count int) int { + minValue := num - splitter.MaxValue*count + if minValue <= 0 { + minValue = splitter.MinValue + } + maxValue := num - count*1 + if maxValue > splitter.MaxValue { + maxValue = splitter.MaxValue + } + + return rand.GetRandInt(minValue, maxValue) +} diff --git a/util/splitNumToN/SplitNumToN_test.go b/util/splitNumToN/SplitNumToN_test.go new file mode 100644 index 0000000..db2cd3d --- /dev/null +++ b/util/splitNumToN/SplitNumToN_test.go @@ -0,0 +1,103 @@ +/* + * @Author : huangZJ + * @Time : 2021/6/16 9:50 + * @Description: + */ + +package splitNumToN + +import ( + "fmt" + "testing" +) + +func TestSplitNumToNWith2(t *testing.T) { + + fmt.Println("测试两个数的情况") + for i := 3; i <= 11; i++ { + fmt.Println() + fmt.Println(fmt.Sprintf("当前随机数为%d", i)) + for j := 0; j < 20; j++ { + splitter := NewSplitter(2, i) + splitter.SplitNumToN() + for _, num := range splitter.GetRandNumList() { + fmt.Print(fmt.Sprintf("%d ", num)) + } + fmt.Println() + } + fmt.Println() + } +} + +func TestSplitNumToNWith3(t *testing.T) { + fmt.Println() + fmt.Println("测试三个数的情况") + for i := 4; i <= 17; i++ { + fmt.Println() + fmt.Println(fmt.Sprintf("当前随机数为%d", i)) + for j := 0; j < 20; j++ { + splitter := NewSplitter(3, i) + fmt.Println() + splitter.SplitNumToN() + for _, num := range splitter.GetRandNumList() { + fmt.Print(fmt.Sprintf("%d ", num)) + } + } + fmt.Println() + } +} + +func TestSplitNumToNWith4(t *testing.T) { + fmt.Println() + fmt.Println("测试四个数的情况") + for i := 5; i <= 23; i++ { + fmt.Println() + fmt.Println(fmt.Sprintf("当前随机数为%d", i)) + for j := 0; j < 100; j++ { + splitter := NewSplitter(4, i) + fmt.Println() + splitter.SplitNumToN() + for _, num := range splitter.GetRandNumList() { + fmt.Print(fmt.Sprintf("%d ", num)) + } + } + fmt.Println() + } +} + +func TestSplitNumToNWith5(t *testing.T) { + fmt.Println() + fmt.Println("测试五个数的情况") + for i := 6; i <= 29; i++ { + fmt.Println() + fmt.Println(fmt.Sprintf("当前随机数为%d", i)) + for j := 0; j < 100; j++ { + splitter := NewSplitter(5, i) + fmt.Println() + splitter.SplitNumToN() + for _, num := range splitter.GetRandNumList() { + fmt.Print(fmt.Sprintf("%d ", num)) + } + } + fmt.Println() + } + +} + +func TestSplitNumToNWith6(t *testing.T) { + fmt.Println() + fmt.Println("测试六个数的情况") + for i := 7; i <= 35; i++ { + fmt.Println() + fmt.Println(fmt.Sprintf("当前随机数为%d", i)) + for j := 0; j < 100; j++ { + splitter := NewSplitter(6, i) + fmt.Println() + splitter.SplitNumToN() + for _, num := range splitter.GetRandNumList() { + fmt.Print(fmt.Sprintf("%d ", num)) + } + } + fmt.Println() + } +}