ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[原创] 史上最酷的Excel VBA 组合算法 代码

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2014-9-15 10:23 | 显示全部楼层
本帖已被收录到知识树中,索引项:其他结构和算法
ak47ok 发表于 2014-8-3 21:40
这个明白,没能力瞎想是没用的,
足彩的没有玩过、
我可是怀着崇高理想来学习这正交的,呵呵!

你不是已有31因素5水平的

去掉7个因素就是了。摆渡 正交表的构造详述  完整的正交试验设计介绍

TA的精华主题

TA的得分主题

发表于 2014-9-15 15:18 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2014-9-16 17:02 | 显示全部楼层
yjh_27 发表于 2014-9-15 10:23
你不是已有31因素5水平的

去掉7个因素就是了。摆渡 正交表的构造详述  完整的正交试验设计介绍

感谢关注!能有31因素的更好,广范围撒网,再用14因素13水平来精选。

TA的精华主题

TA的得分主题

发表于 2014-10-22 19:41 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
香川群子 发表于 2013-7-4 22:43
这个是我的组合算法的核心部分代码

想要研究的话,看懂这部分就OK了。

  下面是关于香川Do循环组合的理解与分析:
  核心代码:
  1. Do
  2.     i = i + 1
  3.     a(j) = i
  4.     Mid(s, (j - 1) * l + 1, l) = sj(i)
  5.     If j = n Then
  6.         k = k + 1
  7.         jg(k, 1) = s
  8.         If i = m Then If j = 1 Then Exit Do Else j = j - 1: i = a(j) '循环出口1:仅在m选1时从此退出
  9.     ElseIf i = m - n + j Then
  10.         k = k + 1
  11.         jg(k, 1) = s
  12.         If j = 1 Then Exit Do Else j = j - 1: i = a(j) '循环出口2:m选2~n均从此退出
  13.     Else
  14.         j = j + 1
  15.     End If
  16. Loop
复制代码
  研究截图:
   369.jpg

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-10-22 20:06 | 显示全部楼层
下面是关于两处输出结果的分析:
  1. Do
  2.     i = i + 1
  3.     a(j) = i
  4.     Mid(s, (j - 1) * l + 1, l) = sj(i)
  5.     If j = n Then
  6.         k = k + 1
  7.         jg(k, 1) = s '此处输出第n位向前跳位时的组合结果
  8.         If i = m Then If j = 1 Then Exit Do Else j = j - 1: i = a(j)
  9.     ElseIf i = m - n + j Then
  10.         k = k + 1
  11.         jg(k, 1) = s '此处输出第n-1至1位向前跳位时的组合结果
  12.         If j = 1 Then Exit Do Else j = j - 1: i = a(j) '当然第1位是没法向前跳位的,因此跳出循环
  13.     Else
  14.         j = j + 1
  15.     End If
  16. Loop
复制代码

TA的精华主题

TA的得分主题

发表于 2014-10-22 20:22 | 显示全部楼层
这是我总结的跳位方法,来个文字的,备注下:
因此,可以粗略地想见,我们的跳位原则是:
1.从组合结果最后一个元素位置起,增加至本位置终止值,不能增加时,向前跳一位;
2.前位数值未达到其位终止值时,加1后继续后位循环;若前位值亦增加至其位终止值时,则继续前跳一位,重复本步。

顺便再说一句:
香川Do循环组合确实技术高超,思维巧妙,最重要的是想人们所不敢想,一个Do循环居然可以替代任意n层for循环……啧啧,奇之、服之!!!

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-10-22 23:37 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
aoe1981 发表于 2014-10-22 20:22
这是我总结的跳位方法,来个文字的,备注下:
因此,可以粗略地想见,我们的跳位原则是:
1.从组合结果最 ...

嗯。你的理解是正确的。

我在生成组合循环过程中,主要使用了两个参数 i 和 j 。

其中, j 是组合位、变动取值范围 1 To n (需要抽取n个元素)
i 是组合抽取元素的序号、变动取值范围 1 To m (数据一共m个元素)

计算过程、规则如下:
1、初始化
j 从 1 To n到达末尾n位置,i 也从 1 To n (未到最大值m)

2、正式开始循环
a. 首先固定 j位置=n 即在末尾 n位置不变,而 i 进行 For循环从 i +1 To m;
b. j 从 n-1 To 1 倒序检查,读取该位置的 i 值,并+1 升位,
    然后检查升位以后的 i 值是否已达最高位置,即  i  = m-n+j 表明下一次已经不能升位了,
    且当前状态就是有效组合之一,所以直接记录。
c.  在b状态时,继续位置 j-1 向前移动、然后读取 i 值并检查,直到升位以后的 i +1 < m-n+j ,则表明可以向后升位了。
d.  在c状态时,则应位置 j+1 向后移动、然后把该位置的 i 值更新为 i +1……直到n-1位置。
f.   j 移动到末尾位置,可以回到a开始新的Do循环。

…………直至最后 j = 0时结束。

…………如果是 1、2、3、4、5、6 这m=6个数中任取n=4个进行组合,则过程如下:
① 初始化,
a = 1,2,3,?
此时,j=n=4、i =3

② 末尾位置递增到m=6
1,2,3,4
1,2,3,5
1,2,3,6

③ 检查j=n-1 To 1 并升位
1,2,4,?   由于4<最终组合 3,4,5,6中的5,可以j=j+1向后继续

④ j=n、末尾位置i+1递增直到m=6
1,2,4,5
1,2,4,6

⑤ 检查j=j-1=3 时,发现4+1=5已到最高位置(m-n+j)
1,2,5,6于是直接记录该有效组合


⑥ 继续向前检查
1,2,5,6 → 因为2+1<4 所以可以继续

1,3,4,5

⑦ 继续②开始的步骤
1,3,4,6

1,3,5,6

1,4,5,6

然后继续:
2,3,4,5

2,3,4,6

2,3,5,6

2,4,5,6


3,4,5,6


点评

多谢指点,相互印证,再加学习!  发表于 2014-10-23 09:26

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-10-24 11:53 | 显示全部楼层
好代码,收藏
顺便废话两句 ,COMBIN 组合       PERMUT排列   这两个函数是excel的内置函数
群子的代码要 移植到 Vb 或者VBS 等没有excel的环境中
需要 编写两句 代码来代替
    x = 1
    For i = 1 To n'''''组合
        x = x * (m - n + i) / i
    Next
等同于 x= Application.COMBIN(m,n)


    x = 1
    For i = 1 To n'''''排列
        x = x * (m - n + i)
    Next
等同于 x= Application.PERMUT(m,n)

貌似是高中数学教的
排列总数= 最大的n个数累乘            组合= 排列总数/ 最小n个数累乘

点评

又学习了一招,感谢科普,擦了一个盲点!  发表于 2014-10-24 17:19

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-10-24 13:55 | 显示全部楼层
本帖最后由 香川群子 于 2014-10-24 13:56 编辑
ldy 发表于 2014-10-24 11:53
好代码,收藏
顺便废话两句 ,COMBIN 组合       PERMUT排列   这两个函数是excel的内置函数
群子的代码要 ...


如果是For i = 1 To Combin / Permut 循环,当然需要事先知道排列组合的结果总数。

但我的Do循环代码不需要事先知道 Cobin和Permut的计算结果。
在循环完成后,自然就得到了排列组合的结果总数k。



评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-10-24 14:04 | 显示全部楼层
香川群子 发表于 2014-10-24 13:55
如果是For i = 1 To Combin / Permut 循环,当然需要事先知道排列组合的结果总数。

但我的Do循环代码 ...

确实是目前最优化的方法 ,Do 循环的次数,跟计算结果非常接近了
我现在加不了分了,送花
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-17 09:38 , Processed in 0.038285 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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