ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 8289|回复: 13

[求助] 如何将1-49个数随机分组

[复制链接]

TA的精华主题

TA的得分主题

发表于 2014-7-12 16:56 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
1至49个数,按8组分,前7组每组6个数,最后一组7个数,每组数是随机的均是从1-49个数随机组合的不重复数。
谢谢!

TA的精华主题

TA的得分主题

发表于 2014-7-12 19:14 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
什么叫“从1-49个数随机组合的不重复数。”

楼主的意思是不是从49个不重复数中随机抽取并分成8组。有点绕,换种说法。有1到49个不重复数,先乱序排列,再分成8组,1到6个数为第一组,7到12个数为第二组……

TA的精华主题

TA的得分主题

发表于 2014-7-12 19:25 | 显示全部楼层
随机生成选择数据

随机.rar

13.57 KB, 下载次数: 238

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-7-14 09:22 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
maditate 发表于 2014-7-12 19:14
什么叫“从1-49个数随机组合的不重复数。”

楼主的意思是不是从49个不重复数中随机抽取并分成8组。有点绕 ...

这样说也地,反正就是1到49个数,随机分成8组。

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-7-14 09:24 | 显示全部楼层
ghostjiao 发表于 2014-7-12 19:25
随机生成选择数据

你好,这个符合我的要求,能否加下注释,学习一下,谢谢!
  1. Sub 分组()  
  2.     Dim arr, i%, j%, k%, brr(1 To 100, 1 To 8), temp, RndNum%, n%
  3.     arr = Sheet1.Range("A1").CurrentRegion
  4.     If UBound(arr) Mod 8 = 0 Then n = UBound(arr) \ 8 Else n = UBound(arr) \ 8 + 1
  5.     VBA.Randomize
  6.     For i = 1 To n
  7.         For j = 8 To 1 Step -1
  8.             k = k + 1
  9.             If k <= UBound(arr) Then
  10.                 RndNum = Int(Rnd * (UBound(arr) - k + 1)) + 1
  11.                 brr(i, j) = arr(RndNum, 1)
  12.                 temp = arr(RndNum, 1)
  13.                 arr(RndNum, 1) = arr(UBound(arr) - k + 1, 1)
  14.                 arr(UBound(arr) - k + 1, 1) = temp
  15.             End If
  16.         Next
  17.     Next
  18.     Range("C1").Resize(n, 8) = brr
  19. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2014-7-14 12:24 | 显示全部楼层
  1. Sub t1()
  2. '须安装ACTIVERUBY.才能运行,下载地址  http://www.artonx.org/data/asr/Ruby-2.1.msi
  3. Set ojs = CreateObject("scriptcontrol"): ojs.Language = "rubyscript"
  4. arr = ojs.eval("a=[*1..49].shuffle;b=[6,6,6,6,6,6,6,7];b.map(&a.method(:shift)).map{|x|x<<nil}")
  5. [e2].Resize(UBound(arr) + 1, UBound(arr, 2) + 1) = arr
  6. Set ojs = Nothing
  7. 'Stop
  8. End Sub
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-7-14 13:05 | 显示全部楼层
本帖最后由 香川群子 于 2014-7-14 13:27 编辑

总计有组合数:
k=1203225027094065555165204440308898611200
Combin(49,7)=85900584
Combin(42,6)=5245786
Combin(36,6)=1947792
Combin(30,6)=593775
Combin(24,6)=134596
Combin(18,6)=18564
Combin(12,6)=924


如果组间不分顺序,则组合数要少一点:
k=238735124423425705389921515934305280
Combin(49,7)=85900584
Combin(41,5)=749398
Combin(35,5)=324632
Combin(29,5)=118755
Combin(23,5)=33649
Combin(17,5)=6188
Combin(11,5)=462

呵呵。

TA的精华主题

TA的得分主题

发表于 2014-7-14 15:10 | 显示全部楼层
  1.     Sub 分组()
  2.         Dim arr, i As Long, brr(7) As String
  3.         arr = [a1:a49]
  4.         [b1].Resize(49) = "=rand()"
  5.         [a:b].Sort [b1]
  6.         For i = 0 To 7
  7.         brr(i) = Chr(i - 23847) & Join(WorksheetFunction.Transpose(Cells(i * 6 + 1, 1).Resize(6 + i \ 7)), ",")
  8.         Next
  9.         [a1:a49] = arr
  10.         [b:b] = ""
  11.         MsgBox Join(brr, vbCrLf)
  12.     End Sub
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-7-14 15:12 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 香川群子 于 2014-7-14 15:27 编辑
qwasd3 发表于 2014-7-14 09:24
你好,这个符合我的要求,能否加下注释,学习一下,谢谢!

3楼代码的算法,本质上就是【数组洗牌法】了。代码挺不错的。


考虑到通用性,参数可以输入,代码修改为:
  1. Sub test()
  2.     m = InputBox("请输入分组排序最大数 m=", "Rand Group", 49) 'm为任意正整数
  3.     ReDim a(1 To m) '定义数组a存放1-m各个数值
  4.     For i = 1 To m
  5.         a(i) = i
  6.     Next
  7.    
  8.     k = InputBox("请输入分组的组数 k=", "Rand Group", 8) 'k为<m的正整数
  9.     n = m \ k '计算平均分组以后每组基准个数n。 例如 49/8=6.125取整后=6
  10.     ReDim b(1 To n + 1, 1 To k) '定义输出结果的数组b 行比n大1,列=分组数k

  11.     Randomize '随机种子初始化   
  12.     For j = 1 To k '遍历各列 计算各个分组
  13.         For i = 1 To n '在每一组中计算1-n个数的随机不重复序号
  14.             p = p + 1 '数据数组a中当前位置p+1
  15.             r = Int(Rnd * m) + p '从剩余数m中任选一个位置 加上当前位置即为实际不重复的随机位置
  16.             m = m - 1 '剩余数-1  【每次只从剩余数m中随机抽取第r个、保证已被抽取的p个不会被重复抽取】
  17.            't = a(r): a(r) = a(p): a(p) = t: b(i, j) = t '如数组a需要反复使用,则需三次交换
  18.            '本题只需如下两句即可 (不用返回数组a)
  19.             b(i, j) = a(r)  '本组j列的第i行 写入本次抽取得到的不重复随机数a(r)
  20.             a(r) = a(p)    '已被抽取掉数据的a(r)位置 交换写入未被抽取的当前p位置值a(p)
  21.             'a(p) = b(i, j)  '如只需抽取一次则抽过的数a(r)不用返回数组a的p位置
  22.         Next
  23.     Next
  24.     '到这里 1-k组的平均n个数都已随机抽取完毕,接下来处理多余的零数

  25.     If m > 0 Then '如果不是恰好整数,有多余零数时:
  26.         For j = k To 1 Step -1 '在第n+1行,从第k列倒序计算抽取不重复随机数
  27.             p = p + 1 '数组a中当前位置仍然+1
  28.             r = Int(Rnd * m) + p '仍然从剩余数m中任选一个位置
  29.             m = m - 1 '剩余数-1
  30.             b(n + 1, j) = a(r) '第n+1行 写入本次抽取得到的不重复随机数a(r)
  31.             a(r) = a(p)          '已被抽取掉数据的a(r)位置 交换写入未被抽取的当前p位置值a(p)
  32.             If m = 0 Then Exit For  '当剩余数m=0时退出循环
  33.         Next
  34. &#160; &#160;&#160;End If

  35.     [d1].CurrentRegion = "" '清空输出区域
  36.     [d1].Resize(n + 1, k) = b '输出随机分组结果到D1单元格开始的区域
  37. End Sub
复制代码
呵呵,这样的解释应该能看懂了吧。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-7-14 15:22 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
ghostjiao 发表于 2014-7-12 19:25
随机生成选择数据

If UBound(arr) Mod 8 = 0 Then n = UBound(arr) \ 8 Else n = UBound(arr) \ 8 + 1

这句代码可以简化计算为:

n = (UBound(arr) - 1) \ 8 + 1


即,计算m个元素分成k组时,每组最大n值是:
n = Int((m - 1) / k ) + 1

或在VBA中可简化为:
n = (m - 1) \ k + 1

呵呵。


您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-18 06:39 , Processed in 0.039015 second(s), 16 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表