【问题标题】:Generate all possible combinations of choices from mutually exclusive options从互斥选项生成所有可能的选项组合
【发布时间】:2013-10-07 06:16:07
【问题描述】:

我有一个优化问题,需要我测试潜在投资组合的所有潜在选择组合,我还需要能够快速适应以排除某些选择。

这必须在 Excel 中完成。

下面我的净化示例的规则:

  • 我可以选择从 3 家杂货店中的任何一家购买水果
  • 杂货店可能有不同数量的过道,以及可供选择的不同水果组合
  • 我只能从所有杂货店中挑选一种水果(或根本没有选择)

组合

  1. 我的第一个组合不是来自任何杂货店的水果
  2. 接下来我从 Grocer3 的 Aisle 3 中挑选 apples
  3. 然后 apples 来自 Aisle 2 来自 Grocer3
  4. 然后 apples 来自 Aisle 1 来自 Grocer3
  5. 然后我从 Grocer2 中的 Aisle 2 中挑选 apples 而从 Grocer 3 中什么都没有(即从 Grocer 3 中选择相同的选择 em> 作为组合 1 等)
  6. 然后我从 Grocer2 的 Aisle 2 中挑选 apples,从 Aisle 3 中挑选 apples em> 来自 Grocer3(即来自 Grocer 3 的选择与组合 2 相同) 以此类推

所有这些将给我7*4*4 = 112 可能的组合,包括

  • Grocer 1 的 7 个选项(6 个选项 + 1 个什么都不做)
  • Grocer 2 的 4 个选项(3 个选项 + 1 个什么都不做)
  • Grocer 3 的 4 个选项(3 个选项 + 1 个什么都不做)

1.无约束问题

我的实际问题要复杂得多,但基本结构是正确的。

我想做的是使用 或 方法来填充以下所有可用选项:

  1. 无约束问题。
  2. 一个受限制的问题(例如,我关闭了 Aisle 2 给我 45 个有效组合)

2。受限问题

我的尝试

我确实解决了一个初始问题,即使用 MOD\INT 方法的杂货店选项数量相同。这很简单,只需一个公式即可,因为模式是可重复的。

如果有一个智能公式解决方案,那将是首选,但我对代码持开放态度(这是我现在正在尝试的路线)

【问题讨论】:

  • + 1 对于一个很好的 + 清晰 + 精确的问题 :)
  • 如果我错了,请纠正我...您想根据 D3:D5 + 第 12 行填充单元格 G3:G5?
  • 我想将 C15 填充到 Nx 其中 (x-15) 是有效组合的数量
  • 哦好的..If there is a smart formula solution then that would be preferred, but I'm open to code (and this is the route I am now trying)我可以想到一个VBA解决方案:p你能上传一个我可以玩的演示文件吗?
  • @SiddharthRout 上传到here

标签: excel-formula vba excel excel-formula vba


【解决方案1】:

在此 Experts-Exchange PAQ http://rdsrc.us/qdl6tl 中,我处理了一个非常相似的问题,以列举五种不同类别事物的每种组合。每个类别中的事物数量各不相同。枚举必须考虑在一个类别中没有选择的可能性以及从该类别中抽取的任何一个选择。

我把这个问题写成一个五位数的数字,其中数字中每个位置的可能位数是一个变量。

Sub CombinatrixPlus()
'Forms all the combinations of at least two subattributes taken from a selection. _
    No more than one subattribute may be taken from any row.
'Uses variable base counting method

Dim i As Long, ii As Long, j As Long, k As Long, lenSep As Long, _
    m As Long, mCol As Long, mSheet As Long, mRow As Long, _
    N As Long, nBlock As Long, nMax As Long, nWide As Long
Dim v As Variant, vInputs As Variant, vResults As Variant
Dim rg As Range, rgDest As Range
Dim ws As Worksheet
Dim s As String, sep As String

Application.ScreenUpdating = False
sep = ", "      'Separator substring between each subattribute in results
Set ws = Worksheets("Sheet2")   'Put first batch of results in this worksheet
Set rgDest = ws.[A2]      'Put results starting in this cell
mSheet = rgDest.Worksheet.Index
mCol = rgDest.Column
lenSep = Len(sep)
Set rg = Selection      'Cells containing the subattributes
nBlock = 16384          'Maximum number of values in results array

'Clear the previous results
Application.DisplayAlerts = False
For i = Worksheets.Count To ws.Index Step -1
    Worksheets(i).Cells.Clear                   'Clear the cells
    If i > ws.Index Then Worksheets(i).Delete   'Delete the sheet
Next
Application.DisplayAlerts = True

N = rg.Rows.Count
nWide = N       'If results lists subattributes in separate cells
'nWide = 1      'If results lists subattributes as a single string with separators
ReDim v(N, 1 To 2)
vInputs = rg.Value
v(0, 2) = 1
For i = 1 To N
    v(i, 1) = Application.CountA(rg.Rows(i))
    v(i, 2) = (v(i, 1) + 1) * v(i - 1, 2)
Next
nMax = v(N, 2) - 1


ReDim vResults(1 To nBlock, 1 To nWide)
For i = 1 To nMax
    s = ""
    m = 0
    ii = ii + 1
    For j = 1 To N
        k = (i Mod v(j, 2)) \ v(j - 1, 2)
        If k <> 0 Then
            m = m + 1
            If nWide > 1 Then vResults(ii, j) = vInputs(j, k)
            s = s & sep & vInputs(j, k)
        End If
    Next
    s = Mid$(s, lenSep + 1)
    If nWide = 1 Then vResults(ii, 1) = s  'Results in a concatentated string
    If m < 2 Then ii = ii - 1

    If ii = nBlock Then
        Application.StatusBar = "Now posting combination " & i & " of " & nMax
        mRow = rgDest.Worksheet.Cells(Rows.Count, mCol).End(xlUp).Row
        If rgDest.Worksheet.Cells(mRow, mCol) <> "" Then mRow = mRow + 1
        If mRow < rgDest.Row Then mRow = rgDest.Row
        If (Rows.Count - mRow) >= nBlock Then
            rgDest.Worksheet.Cells(mRow, mCol).Resize(nBlock, nWide).Value = vResults
        Else
            mSheet = mSheet + 1
            If Worksheets.Count < mSheet Then Worksheets.Add After:=Worksheets(mSheet - 1)
            With ActiveSheet
                Set rgDest = .Range(rgDest.Address)
                For j = 1 To N
                    .Columns(j).ColumnWidth = ws.Columns(j).ColumnWidth
                Next
                mRow = rgDest.Row
                .Cells(mRow, mCol).Resize(nBlock, nWide).Value = vResults
            End With
        End If
        ii = 0
        ReDim vResults(1 To nBlock, 1 To nWide)
    End If
Next

If ii > 0 Then
        Application.StatusBar = "Now posting combination " & i & " of " & nMax
        mRow = rgDest.Worksheet.Cells(Rows.Count, mCol).End(xlUp).Row
        If rgDest.Worksheet.Cells(mRow, mCol) <> "" Then mRow = mRow + 1
        If mRow < rgDest.Row Then mRow = rgDest.Row
        If (Rows.Count - mRow) >= nBlock Then
            rgDest.Worksheet.Cells(mRow, mCol).Resize(nBlock, nWide).Value = vResults
        Else
            mSheet = mSheet + 1
            If Worksheets.Count < mSheet Then Worksheets.Add After:=Worksheets(mSheet - 1)
            With ActiveSheet
                Set rgDest = .Range(rgDest.Address)
                For j = 1 To N
                    .Columns(i).ColumnWidth = ws.Columns(j).ColumnWidth
                Next
                mRow = rgDest.Row
                .Cells(mRow, mCol).Resize(nBlock, nWide).Value = vResults
            End With
        End If
    i = rgDest.Worksheet.UsedRange.Rows.Count   'Reset the scrollbar
End If
Application.StatusBar = False   'Clear the status bar
Application.ScreenUpdating = True
End Sub

【讨论】:

  • 感谢 Brad 的快速回复,我会期待明天完成这个 - 非常感谢。
  • +1 这是 99.9%。它给了我试验的 112 个组合中的 99 个,只缺少 a) 没有选择 (1) b) 单一选择 (11)。
  • 对于仅公式的解决方案,工作表布局不方便。排除某些可能值的愿望也是如此。
  • =IF(D11="",INDEX(D$3:D$8,1),IF(MATCH(D11,D$3:D$8,0)=COUNTA(D$3:D$8) ,"",INDEX(D$3:D$8,MATCH(D11,D$3:D$8,0)+1))) 最右边位置的公式
  • 测试列出的所有组合 =IF($A12>=(COUNTA($B$3:$B$8)+1)*(COUNTA($C$3:$C$8)+1)* (COUNTA($D$3:$D$8)+1),"",以前发布的公式)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-06
  • 2018-02-04
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
  • 2019-05-20
相关资源
最近更新 更多