Recursive code to generate a parametric sweep of input valuesCleaning up and reformatting imported data in an Excel sheetCode optimization of recursive functionFilling a row with valuesFunctional FrameworkMaking a report from payroll detailsVBA Macro to generate a report of mean values for each dateK-combination recursive algorithm implementationVBA - recursive combination listing based on Excel columnsCheck employee input from shift workGenerate parentheses solution
What should be done when the theory behind a PhD thesis turns out to be wrong?
Can any number of squares sum to a square?
Is there any difference between 旅行者 and 旅人?
Is it harder to enter an atmosphere perpendicular or at an angle
What is written in this excerpt from a Manifest of Alien Passengers for the US arriving at Providence?
What is the difference between Cisco's QoS models and strategies?
What is the typical CPU utilization of idle iMac?
Why is the processor instruction called "move", not "copy"?
What is the difference between scissors and shears?
How does a virus know what component of it to mutate?
Load extra fonts with lualatex
Is concept of entropy really indispensable? Especially when the concept of potential energy can serve the purpose?
Possibly unsurprising riddle
Is there a material or method to allow "swimmable" coins?
Why choose the name "Morpheus" when it is the name of the Greek god of dreams
Reconstructed PIE grammar? Could we be able to speak in Proto-European?
Round up my number
Has there been clarification of the Random Weight Table in the Player's Handbook?
If a picture of a screen is a screenshot, what is a video of a screen?
Why doesn't the road lose its thickness to the tyre?
Who's next to me in the queue?
Probability of pushing buttons in elevator
Is harmony based on intervals rather than chords?
Are generation ships inherently implausible?
Recursive code to generate a parametric sweep of input values
Cleaning up and reformatting imported data in an Excel sheetCode optimization of recursive functionFilling a row with valuesFunctional FrameworkMaking a report from payroll detailsVBA Macro to generate a report of mean values for each dateK-combination recursive algorithm implementationVBA - recursive combination listing based on Excel columnsCheck employee input from shift workGenerate parentheses solution
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
$begingroup$
I generate a set of data based off every combination of inputs. The source range that's inputs requires headers to identify the parameters. In its present state I'm not content as it's not as straightforward as I'd like it to be. Specifically the module variables can be cleaned up but I'm not seeing how.
A simple example with 2 columns
---------------------
| Column1 | Column2 |
|---------|---------|
| A | 1 |
| B | 2 |
| C | 3 |
---------------------
generates
---------------------
| Column1 | Column2 |
|---------|---------|
| A | 1 |
| A | 2 |
| A | 3 |
| B | 1 |
| B | 2 |
| B | 3 |
| C | 1 |
| C | 2 |
| C | 3 |
---------------------
Adding a 3 column input table
-------------------------------
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| A | 1 | F1 |
| B | 2 | F2 |
| C | 3 | F3 |
| | | F4 |
-------------------------------
generates
-------------------------------
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| A | 1 | F1 |
| A | 1 | F2 |
| A | 1 | F3 |
| A | 1 | F4 |
| A | 2 | F1 |
. . . . . . . . . . . . . . .
| C | 2 | F4 |
| C | 3 | F1 |
| C | 3 | F2 |
| C | 3 | F3 |
| C | 3 | F4 |
-------------------------------
and so on.
The class module InputColumn
is used to help compartmentalize the logic for each column and its corresponding max depth being equivalent to CountOfValues
.
'@PredeclaredId
'@Folder("ParametricSweep.Model")
Option Explicit
Private Type THelper
ColumnIndex As Long
Values As Variant
Identifier As String
End Type
Private this As THelper
Public Property Let Values(ByVal Value As Variant)
this.Values = Value
End Property
Public Property Get Values() As Variant
Values = this.Values
End Property
Public Property Get CountOfValues() As Long
CountOfValues = UBound(Values) - LBound(Values) + 1
End Property
Public Property Let Identifier(ByVal Value As String)
this.Identifier = Value
End Property
Public Property Get Identifier() As String
Identifier = this.Identifier
End Property
Public Function Self() As InputColumn
Set Self = Me
End Function
Public Function Create(ByVal ColumnIndex As Long, ByVal sourceArea As Range) As InputColumn
Dim populatedCells As Range
Set populatedCells = sourceArea.SpecialCells(XlCellType.xlCellTypeConstants)
With New InputColumn
.Identifier = populatedCells(1, 1).Value2
.Values = Application.WorksheetFunction.Transpose(populatedCells.Offset(1).Resize(populatedCells.Rows.Count - 1).Value2)
Set Create = .Self
End With
End Function
The sweep of values is generated by populating the inputColumns()
array then stepping into PopulateArray 1
for the first (topmost) level. After the call to PopulateArray
it recursively descends one level deeper until it's populating the last column. As each loop returns it increments the array recursionInputColumnPopulationIndex()
that identifies which element should populated for the corresponding recursion depth.
Option Explicit
Private parentArray() As Variant
Private inputColumns() As InputColumn
Private maxRecursionDepth As Long
Private recursionInputColumnPopulationIndex() As Long
Private populationRow As Long
Public Sub TestRecursive()
Dim foo As Variant
foo = RecursiveParametricSweep(Sheet1.Range("C5").CurrentRegion, True)
Dim bar As Variant
bar = RecursiveParametricSweep(Sheet1.Range("C16").CurrentRegion, False)
End Sub
Public Function RecursiveParametricSweep(ByVal inputSourceArea As Range, ByVal includeHeader As Boolean) As Variant
maxRecursionDepth = inputSourceArea.Columns.Count
ReDim inputColumns(1 To maxRecursionDepth)
ReDim recursionInputColumnPopulationIndex(1 To maxRecursionDepth)
PopulateInputColumns inputSourceArea
Dim rowCount As Long
rowCount = GetRowCount(inputColumns)
If includeHeader Then
ReDim parentArray(0 To rowCount, 1 To maxRecursionDepth)
Dim headerRow As Long
headerRow = LBound(parentArray)
Dim headerColumn As Long
For headerColumn = LBound(inputColumns) To UBound(inputColumns)
parentArray(headerRow, headerColumn) = inputColumns(headerColumn).Identifier
Next
populationRow = LBound(parentArray) + 1
Else
ReDim parentArray(1 To rowCount, 1 To maxRecursionDepth)
populationRow = LBound(parentArray)
End If
PopulateArray 1, includeHeader
RecursiveParametricSweep = parentArray
End Function
Private Sub PopulateArray(ByVal recursionDepth As Long, ByVal includeHeader As Boolean)
Dim populateElementCount As Long
For populateElementCount = 1 To inputColumns(recursionDepth).CountOfValues
If recursionDepth < maxRecursionDepth Then
PopulateArray recursionDepth + 1, includeHeader
recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
Else
Dim columnPopulationIndex As Long
For columnPopulationIndex = recursionDepth To 1 Step -1
parentArray(populationRow, columnPopulationIndex) = inputColumns(columnPopulationIndex).Values(recursionInputColumnPopulationIndex(columnPopulationIndex) + 1)
Next
recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
populationRow = populationRow + 1
End If
Next
recursionInputColumnPopulationIndex(recursionDepth) = 0
End Sub
Private Function GetRowCount(ByRef inputColumns() As InputColumn) As Long
GetRowCount = 1
Dim depthCounter As Long
For depthCounter = LBound(inputColumns) To UBound(inputColumns)
GetRowCount = GetRowCount * inputColumns(depthCounter).CountOfValues
Next
End Function
Private Sub PopulateInputColumns(ByVal inputSourceArea As Range)
Dim populateInputColumnsCounter As Long
For populateInputColumnsCounter = LBound(inputColumns) To UBound(inputColumns)
Set inputColumns(populateInputColumnsCounter) = InputColumn.Create(populateInputColumnsCounter, inputSourceArea.Columns(populateInputColumnsCounter))
Next
End Sub
```
vba excel recursion combinatorics
$endgroup$
add a comment
|
$begingroup$
I generate a set of data based off every combination of inputs. The source range that's inputs requires headers to identify the parameters. In its present state I'm not content as it's not as straightforward as I'd like it to be. Specifically the module variables can be cleaned up but I'm not seeing how.
A simple example with 2 columns
---------------------
| Column1 | Column2 |
|---------|---------|
| A | 1 |
| B | 2 |
| C | 3 |
---------------------
generates
---------------------
| Column1 | Column2 |
|---------|---------|
| A | 1 |
| A | 2 |
| A | 3 |
| B | 1 |
| B | 2 |
| B | 3 |
| C | 1 |
| C | 2 |
| C | 3 |
---------------------
Adding a 3 column input table
-------------------------------
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| A | 1 | F1 |
| B | 2 | F2 |
| C | 3 | F3 |
| | | F4 |
-------------------------------
generates
-------------------------------
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| A | 1 | F1 |
| A | 1 | F2 |
| A | 1 | F3 |
| A | 1 | F4 |
| A | 2 | F1 |
. . . . . . . . . . . . . . .
| C | 2 | F4 |
| C | 3 | F1 |
| C | 3 | F2 |
| C | 3 | F3 |
| C | 3 | F4 |
-------------------------------
and so on.
The class module InputColumn
is used to help compartmentalize the logic for each column and its corresponding max depth being equivalent to CountOfValues
.
'@PredeclaredId
'@Folder("ParametricSweep.Model")
Option Explicit
Private Type THelper
ColumnIndex As Long
Values As Variant
Identifier As String
End Type
Private this As THelper
Public Property Let Values(ByVal Value As Variant)
this.Values = Value
End Property
Public Property Get Values() As Variant
Values = this.Values
End Property
Public Property Get CountOfValues() As Long
CountOfValues = UBound(Values) - LBound(Values) + 1
End Property
Public Property Let Identifier(ByVal Value As String)
this.Identifier = Value
End Property
Public Property Get Identifier() As String
Identifier = this.Identifier
End Property
Public Function Self() As InputColumn
Set Self = Me
End Function
Public Function Create(ByVal ColumnIndex As Long, ByVal sourceArea As Range) As InputColumn
Dim populatedCells As Range
Set populatedCells = sourceArea.SpecialCells(XlCellType.xlCellTypeConstants)
With New InputColumn
.Identifier = populatedCells(1, 1).Value2
.Values = Application.WorksheetFunction.Transpose(populatedCells.Offset(1).Resize(populatedCells.Rows.Count - 1).Value2)
Set Create = .Self
End With
End Function
The sweep of values is generated by populating the inputColumns()
array then stepping into PopulateArray 1
for the first (topmost) level. After the call to PopulateArray
it recursively descends one level deeper until it's populating the last column. As each loop returns it increments the array recursionInputColumnPopulationIndex()
that identifies which element should populated for the corresponding recursion depth.
Option Explicit
Private parentArray() As Variant
Private inputColumns() As InputColumn
Private maxRecursionDepth As Long
Private recursionInputColumnPopulationIndex() As Long
Private populationRow As Long
Public Sub TestRecursive()
Dim foo As Variant
foo = RecursiveParametricSweep(Sheet1.Range("C5").CurrentRegion, True)
Dim bar As Variant
bar = RecursiveParametricSweep(Sheet1.Range("C16").CurrentRegion, False)
End Sub
Public Function RecursiveParametricSweep(ByVal inputSourceArea As Range, ByVal includeHeader As Boolean) As Variant
maxRecursionDepth = inputSourceArea.Columns.Count
ReDim inputColumns(1 To maxRecursionDepth)
ReDim recursionInputColumnPopulationIndex(1 To maxRecursionDepth)
PopulateInputColumns inputSourceArea
Dim rowCount As Long
rowCount = GetRowCount(inputColumns)
If includeHeader Then
ReDim parentArray(0 To rowCount, 1 To maxRecursionDepth)
Dim headerRow As Long
headerRow = LBound(parentArray)
Dim headerColumn As Long
For headerColumn = LBound(inputColumns) To UBound(inputColumns)
parentArray(headerRow, headerColumn) = inputColumns(headerColumn).Identifier
Next
populationRow = LBound(parentArray) + 1
Else
ReDim parentArray(1 To rowCount, 1 To maxRecursionDepth)
populationRow = LBound(parentArray)
End If
PopulateArray 1, includeHeader
RecursiveParametricSweep = parentArray
End Function
Private Sub PopulateArray(ByVal recursionDepth As Long, ByVal includeHeader As Boolean)
Dim populateElementCount As Long
For populateElementCount = 1 To inputColumns(recursionDepth).CountOfValues
If recursionDepth < maxRecursionDepth Then
PopulateArray recursionDepth + 1, includeHeader
recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
Else
Dim columnPopulationIndex As Long
For columnPopulationIndex = recursionDepth To 1 Step -1
parentArray(populationRow, columnPopulationIndex) = inputColumns(columnPopulationIndex).Values(recursionInputColumnPopulationIndex(columnPopulationIndex) + 1)
Next
recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
populationRow = populationRow + 1
End If
Next
recursionInputColumnPopulationIndex(recursionDepth) = 0
End Sub
Private Function GetRowCount(ByRef inputColumns() As InputColumn) As Long
GetRowCount = 1
Dim depthCounter As Long
For depthCounter = LBound(inputColumns) To UBound(inputColumns)
GetRowCount = GetRowCount * inputColumns(depthCounter).CountOfValues
Next
End Function
Private Sub PopulateInputColumns(ByVal inputSourceArea As Range)
Dim populateInputColumnsCounter As Long
For populateInputColumnsCounter = LBound(inputColumns) To UBound(inputColumns)
Set inputColumns(populateInputColumnsCounter) = InputColumn.Create(populateInputColumnsCounter, inputSourceArea.Columns(populateInputColumnsCounter))
Next
End Sub
```
vba excel recursion combinatorics
$endgroup$
add a comment
|
$begingroup$
I generate a set of data based off every combination of inputs. The source range that's inputs requires headers to identify the parameters. In its present state I'm not content as it's not as straightforward as I'd like it to be. Specifically the module variables can be cleaned up but I'm not seeing how.
A simple example with 2 columns
---------------------
| Column1 | Column2 |
|---------|---------|
| A | 1 |
| B | 2 |
| C | 3 |
---------------------
generates
---------------------
| Column1 | Column2 |
|---------|---------|
| A | 1 |
| A | 2 |
| A | 3 |
| B | 1 |
| B | 2 |
| B | 3 |
| C | 1 |
| C | 2 |
| C | 3 |
---------------------
Adding a 3 column input table
-------------------------------
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| A | 1 | F1 |
| B | 2 | F2 |
| C | 3 | F3 |
| | | F4 |
-------------------------------
generates
-------------------------------
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| A | 1 | F1 |
| A | 1 | F2 |
| A | 1 | F3 |
| A | 1 | F4 |
| A | 2 | F1 |
. . . . . . . . . . . . . . .
| C | 2 | F4 |
| C | 3 | F1 |
| C | 3 | F2 |
| C | 3 | F3 |
| C | 3 | F4 |
-------------------------------
and so on.
The class module InputColumn
is used to help compartmentalize the logic for each column and its corresponding max depth being equivalent to CountOfValues
.
'@PredeclaredId
'@Folder("ParametricSweep.Model")
Option Explicit
Private Type THelper
ColumnIndex As Long
Values As Variant
Identifier As String
End Type
Private this As THelper
Public Property Let Values(ByVal Value As Variant)
this.Values = Value
End Property
Public Property Get Values() As Variant
Values = this.Values
End Property
Public Property Get CountOfValues() As Long
CountOfValues = UBound(Values) - LBound(Values) + 1
End Property
Public Property Let Identifier(ByVal Value As String)
this.Identifier = Value
End Property
Public Property Get Identifier() As String
Identifier = this.Identifier
End Property
Public Function Self() As InputColumn
Set Self = Me
End Function
Public Function Create(ByVal ColumnIndex As Long, ByVal sourceArea As Range) As InputColumn
Dim populatedCells As Range
Set populatedCells = sourceArea.SpecialCells(XlCellType.xlCellTypeConstants)
With New InputColumn
.Identifier = populatedCells(1, 1).Value2
.Values = Application.WorksheetFunction.Transpose(populatedCells.Offset(1).Resize(populatedCells.Rows.Count - 1).Value2)
Set Create = .Self
End With
End Function
The sweep of values is generated by populating the inputColumns()
array then stepping into PopulateArray 1
for the first (topmost) level. After the call to PopulateArray
it recursively descends one level deeper until it's populating the last column. As each loop returns it increments the array recursionInputColumnPopulationIndex()
that identifies which element should populated for the corresponding recursion depth.
Option Explicit
Private parentArray() As Variant
Private inputColumns() As InputColumn
Private maxRecursionDepth As Long
Private recursionInputColumnPopulationIndex() As Long
Private populationRow As Long
Public Sub TestRecursive()
Dim foo As Variant
foo = RecursiveParametricSweep(Sheet1.Range("C5").CurrentRegion, True)
Dim bar As Variant
bar = RecursiveParametricSweep(Sheet1.Range("C16").CurrentRegion, False)
End Sub
Public Function RecursiveParametricSweep(ByVal inputSourceArea As Range, ByVal includeHeader As Boolean) As Variant
maxRecursionDepth = inputSourceArea.Columns.Count
ReDim inputColumns(1 To maxRecursionDepth)
ReDim recursionInputColumnPopulationIndex(1 To maxRecursionDepth)
PopulateInputColumns inputSourceArea
Dim rowCount As Long
rowCount = GetRowCount(inputColumns)
If includeHeader Then
ReDim parentArray(0 To rowCount, 1 To maxRecursionDepth)
Dim headerRow As Long
headerRow = LBound(parentArray)
Dim headerColumn As Long
For headerColumn = LBound(inputColumns) To UBound(inputColumns)
parentArray(headerRow, headerColumn) = inputColumns(headerColumn).Identifier
Next
populationRow = LBound(parentArray) + 1
Else
ReDim parentArray(1 To rowCount, 1 To maxRecursionDepth)
populationRow = LBound(parentArray)
End If
PopulateArray 1, includeHeader
RecursiveParametricSweep = parentArray
End Function
Private Sub PopulateArray(ByVal recursionDepth As Long, ByVal includeHeader As Boolean)
Dim populateElementCount As Long
For populateElementCount = 1 To inputColumns(recursionDepth).CountOfValues
If recursionDepth < maxRecursionDepth Then
PopulateArray recursionDepth + 1, includeHeader
recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
Else
Dim columnPopulationIndex As Long
For columnPopulationIndex = recursionDepth To 1 Step -1
parentArray(populationRow, columnPopulationIndex) = inputColumns(columnPopulationIndex).Values(recursionInputColumnPopulationIndex(columnPopulationIndex) + 1)
Next
recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
populationRow = populationRow + 1
End If
Next
recursionInputColumnPopulationIndex(recursionDepth) = 0
End Sub
Private Function GetRowCount(ByRef inputColumns() As InputColumn) As Long
GetRowCount = 1
Dim depthCounter As Long
For depthCounter = LBound(inputColumns) To UBound(inputColumns)
GetRowCount = GetRowCount * inputColumns(depthCounter).CountOfValues
Next
End Function
Private Sub PopulateInputColumns(ByVal inputSourceArea As Range)
Dim populateInputColumnsCounter As Long
For populateInputColumnsCounter = LBound(inputColumns) To UBound(inputColumns)
Set inputColumns(populateInputColumnsCounter) = InputColumn.Create(populateInputColumnsCounter, inputSourceArea.Columns(populateInputColumnsCounter))
Next
End Sub
```
vba excel recursion combinatorics
$endgroup$
I generate a set of data based off every combination of inputs. The source range that's inputs requires headers to identify the parameters. In its present state I'm not content as it's not as straightforward as I'd like it to be. Specifically the module variables can be cleaned up but I'm not seeing how.
A simple example with 2 columns
---------------------
| Column1 | Column2 |
|---------|---------|
| A | 1 |
| B | 2 |
| C | 3 |
---------------------
generates
---------------------
| Column1 | Column2 |
|---------|---------|
| A | 1 |
| A | 2 |
| A | 3 |
| B | 1 |
| B | 2 |
| B | 3 |
| C | 1 |
| C | 2 |
| C | 3 |
---------------------
Adding a 3 column input table
-------------------------------
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| A | 1 | F1 |
| B | 2 | F2 |
| C | 3 | F3 |
| | | F4 |
-------------------------------
generates
-------------------------------
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| A | 1 | F1 |
| A | 1 | F2 |
| A | 1 | F3 |
| A | 1 | F4 |
| A | 2 | F1 |
. . . . . . . . . . . . . . .
| C | 2 | F4 |
| C | 3 | F1 |
| C | 3 | F2 |
| C | 3 | F3 |
| C | 3 | F4 |
-------------------------------
and so on.
The class module InputColumn
is used to help compartmentalize the logic for each column and its corresponding max depth being equivalent to CountOfValues
.
'@PredeclaredId
'@Folder("ParametricSweep.Model")
Option Explicit
Private Type THelper
ColumnIndex As Long
Values As Variant
Identifier As String
End Type
Private this As THelper
Public Property Let Values(ByVal Value As Variant)
this.Values = Value
End Property
Public Property Get Values() As Variant
Values = this.Values
End Property
Public Property Get CountOfValues() As Long
CountOfValues = UBound(Values) - LBound(Values) + 1
End Property
Public Property Let Identifier(ByVal Value As String)
this.Identifier = Value
End Property
Public Property Get Identifier() As String
Identifier = this.Identifier
End Property
Public Function Self() As InputColumn
Set Self = Me
End Function
Public Function Create(ByVal ColumnIndex As Long, ByVal sourceArea As Range) As InputColumn
Dim populatedCells As Range
Set populatedCells = sourceArea.SpecialCells(XlCellType.xlCellTypeConstants)
With New InputColumn
.Identifier = populatedCells(1, 1).Value2
.Values = Application.WorksheetFunction.Transpose(populatedCells.Offset(1).Resize(populatedCells.Rows.Count - 1).Value2)
Set Create = .Self
End With
End Function
The sweep of values is generated by populating the inputColumns()
array then stepping into PopulateArray 1
for the first (topmost) level. After the call to PopulateArray
it recursively descends one level deeper until it's populating the last column. As each loop returns it increments the array recursionInputColumnPopulationIndex()
that identifies which element should populated for the corresponding recursion depth.
Option Explicit
Private parentArray() As Variant
Private inputColumns() As InputColumn
Private maxRecursionDepth As Long
Private recursionInputColumnPopulationIndex() As Long
Private populationRow As Long
Public Sub TestRecursive()
Dim foo As Variant
foo = RecursiveParametricSweep(Sheet1.Range("C5").CurrentRegion, True)
Dim bar As Variant
bar = RecursiveParametricSweep(Sheet1.Range("C16").CurrentRegion, False)
End Sub
Public Function RecursiveParametricSweep(ByVal inputSourceArea As Range, ByVal includeHeader As Boolean) As Variant
maxRecursionDepth = inputSourceArea.Columns.Count
ReDim inputColumns(1 To maxRecursionDepth)
ReDim recursionInputColumnPopulationIndex(1 To maxRecursionDepth)
PopulateInputColumns inputSourceArea
Dim rowCount As Long
rowCount = GetRowCount(inputColumns)
If includeHeader Then
ReDim parentArray(0 To rowCount, 1 To maxRecursionDepth)
Dim headerRow As Long
headerRow = LBound(parentArray)
Dim headerColumn As Long
For headerColumn = LBound(inputColumns) To UBound(inputColumns)
parentArray(headerRow, headerColumn) = inputColumns(headerColumn).Identifier
Next
populationRow = LBound(parentArray) + 1
Else
ReDim parentArray(1 To rowCount, 1 To maxRecursionDepth)
populationRow = LBound(parentArray)
End If
PopulateArray 1, includeHeader
RecursiveParametricSweep = parentArray
End Function
Private Sub PopulateArray(ByVal recursionDepth As Long, ByVal includeHeader As Boolean)
Dim populateElementCount As Long
For populateElementCount = 1 To inputColumns(recursionDepth).CountOfValues
If recursionDepth < maxRecursionDepth Then
PopulateArray recursionDepth + 1, includeHeader
recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
Else
Dim columnPopulationIndex As Long
For columnPopulationIndex = recursionDepth To 1 Step -1
parentArray(populationRow, columnPopulationIndex) = inputColumns(columnPopulationIndex).Values(recursionInputColumnPopulationIndex(columnPopulationIndex) + 1)
Next
recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
populationRow = populationRow + 1
End If
Next
recursionInputColumnPopulationIndex(recursionDepth) = 0
End Sub
Private Function GetRowCount(ByRef inputColumns() As InputColumn) As Long
GetRowCount = 1
Dim depthCounter As Long
For depthCounter = LBound(inputColumns) To UBound(inputColumns)
GetRowCount = GetRowCount * inputColumns(depthCounter).CountOfValues
Next
End Function
Private Sub PopulateInputColumns(ByVal inputSourceArea As Range)
Dim populateInputColumnsCounter As Long
For populateInputColumnsCounter = LBound(inputColumns) To UBound(inputColumns)
Set inputColumns(populateInputColumnsCounter) = InputColumn.Create(populateInputColumnsCounter, inputSourceArea.Columns(populateInputColumnsCounter))
Next
End Sub
```
vba excel recursion combinatorics
vba excel recursion combinatorics
edited Sep 28 at 14:39
Mathieu Guindon♦
71.8k16 gold badges166 silver badges431 bronze badges
71.8k16 gold badges166 silver badges431 bronze badges
asked Sep 28 at 5:48
IvenBachIvenBach
1,9447 silver badges17 bronze badges
1,9447 silver badges17 bronze badges
add a comment
|
add a comment
|
1 Answer
1
active
oldest
votes
$begingroup$
This looks like a decent recursive implementation. So, this is mainly about style and readability.
First, I would like to talk about two things which are really hard and could use some improvement here, naming and consistency of semantic levels. Then I have some more miscellaneous comments.
Naming
Generally, the naming is not too bad, but some of the names are a bit misleading, e.g. the function name GetRowCount
suggests that it returns the number of rows of whatever I give it. However, what it returns is the number of rows of the later output. So, one could simply call it OutputRowCount
, which also follows the general guideline to use nouns that describe the return value for functions.
Another things with the naming is that it sticks a bit much to the role of things in the implementation and not to what they are. Naming things after what they are can make understanding the code much faster. E.g. using inputColumnIndex
instead of recursionDepth
would immediately tell the reader that you are dealing with this specific input column right now. Then the technical maxRecursionDepth
could also be lastColumnIndex
or countOfColumns
. Similarly, the rather ominous recursionInputColumnPopulationIndex(recursionDepth)
could be currentInputIndex(inputColumnIndex)
. So generally, my advice would be to name things after what they are and not their implementation purpose.
Consistency of Semantic Levels
Programmers, me included, are notoriously bad a keeping semantic levels consistent in procedures. To explain what I mean take a look at RecursiveParametricSweep
. It does some high level orchestration like calling the procedure to populate the input columns, calling a function to get the number of output rows, calling the procedure to populate the output array and assigning the return value. However, in between it goes into the detail of how to handle headers. This is a break in semantic level of the procedure that throws one off a bit when first reading the procdure. This could be avoided by extracting either an InitializeOutputArray
or a WriteHeaders
procedure.
Miscellaneous
- The global variable
maxRecursionDepth
is a bit superfluous since it is justUBound(inputColumns)
, which is a bit clearer semantically, I think. - Instead of incrementing
recursionInputColumnPopulationIndex(recursionDepth)
, you could just always set it topopulateElementCount
at the start of the loop, which might be calledcurrentInputIndex
instead. - Istead of keeping track of the indeces for the columns in an array, you might just as well keep track of the values in an array instead. That would put the choice of value closer to the action for the specific column.
- It looks a bit strange to have the
populationRow
counter as a module level variable. You could avoid this by passing itByRef
into the recursive procedure. - It might make sense to extract a
PopulateRow
procedure to keep semantic levels consitsent.
$endgroup$
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229781%2frecursive-code-to-generate-a-parametric-sweep-of-input-values%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
This looks like a decent recursive implementation. So, this is mainly about style and readability.
First, I would like to talk about two things which are really hard and could use some improvement here, naming and consistency of semantic levels. Then I have some more miscellaneous comments.
Naming
Generally, the naming is not too bad, but some of the names are a bit misleading, e.g. the function name GetRowCount
suggests that it returns the number of rows of whatever I give it. However, what it returns is the number of rows of the later output. So, one could simply call it OutputRowCount
, which also follows the general guideline to use nouns that describe the return value for functions.
Another things with the naming is that it sticks a bit much to the role of things in the implementation and not to what they are. Naming things after what they are can make understanding the code much faster. E.g. using inputColumnIndex
instead of recursionDepth
would immediately tell the reader that you are dealing with this specific input column right now. Then the technical maxRecursionDepth
could also be lastColumnIndex
or countOfColumns
. Similarly, the rather ominous recursionInputColumnPopulationIndex(recursionDepth)
could be currentInputIndex(inputColumnIndex)
. So generally, my advice would be to name things after what they are and not their implementation purpose.
Consistency of Semantic Levels
Programmers, me included, are notoriously bad a keeping semantic levels consistent in procedures. To explain what I mean take a look at RecursiveParametricSweep
. It does some high level orchestration like calling the procedure to populate the input columns, calling a function to get the number of output rows, calling the procedure to populate the output array and assigning the return value. However, in between it goes into the detail of how to handle headers. This is a break in semantic level of the procedure that throws one off a bit when first reading the procdure. This could be avoided by extracting either an InitializeOutputArray
or a WriteHeaders
procedure.
Miscellaneous
- The global variable
maxRecursionDepth
is a bit superfluous since it is justUBound(inputColumns)
, which is a bit clearer semantically, I think. - Instead of incrementing
recursionInputColumnPopulationIndex(recursionDepth)
, you could just always set it topopulateElementCount
at the start of the loop, which might be calledcurrentInputIndex
instead. - Istead of keeping track of the indeces for the columns in an array, you might just as well keep track of the values in an array instead. That would put the choice of value closer to the action for the specific column.
- It looks a bit strange to have the
populationRow
counter as a module level variable. You could avoid this by passing itByRef
into the recursive procedure. - It might make sense to extract a
PopulateRow
procedure to keep semantic levels consitsent.
$endgroup$
add a comment
|
$begingroup$
This looks like a decent recursive implementation. So, this is mainly about style and readability.
First, I would like to talk about two things which are really hard and could use some improvement here, naming and consistency of semantic levels. Then I have some more miscellaneous comments.
Naming
Generally, the naming is not too bad, but some of the names are a bit misleading, e.g. the function name GetRowCount
suggests that it returns the number of rows of whatever I give it. However, what it returns is the number of rows of the later output. So, one could simply call it OutputRowCount
, which also follows the general guideline to use nouns that describe the return value for functions.
Another things with the naming is that it sticks a bit much to the role of things in the implementation and not to what they are. Naming things after what they are can make understanding the code much faster. E.g. using inputColumnIndex
instead of recursionDepth
would immediately tell the reader that you are dealing with this specific input column right now. Then the technical maxRecursionDepth
could also be lastColumnIndex
or countOfColumns
. Similarly, the rather ominous recursionInputColumnPopulationIndex(recursionDepth)
could be currentInputIndex(inputColumnIndex)
. So generally, my advice would be to name things after what they are and not their implementation purpose.
Consistency of Semantic Levels
Programmers, me included, are notoriously bad a keeping semantic levels consistent in procedures. To explain what I mean take a look at RecursiveParametricSweep
. It does some high level orchestration like calling the procedure to populate the input columns, calling a function to get the number of output rows, calling the procedure to populate the output array and assigning the return value. However, in between it goes into the detail of how to handle headers. This is a break in semantic level of the procedure that throws one off a bit when first reading the procdure. This could be avoided by extracting either an InitializeOutputArray
or a WriteHeaders
procedure.
Miscellaneous
- The global variable
maxRecursionDepth
is a bit superfluous since it is justUBound(inputColumns)
, which is a bit clearer semantically, I think. - Instead of incrementing
recursionInputColumnPopulationIndex(recursionDepth)
, you could just always set it topopulateElementCount
at the start of the loop, which might be calledcurrentInputIndex
instead. - Istead of keeping track of the indeces for the columns in an array, you might just as well keep track of the values in an array instead. That would put the choice of value closer to the action for the specific column.
- It looks a bit strange to have the
populationRow
counter as a module level variable. You could avoid this by passing itByRef
into the recursive procedure. - It might make sense to extract a
PopulateRow
procedure to keep semantic levels consitsent.
$endgroup$
add a comment
|
$begingroup$
This looks like a decent recursive implementation. So, this is mainly about style and readability.
First, I would like to talk about two things which are really hard and could use some improvement here, naming and consistency of semantic levels. Then I have some more miscellaneous comments.
Naming
Generally, the naming is not too bad, but some of the names are a bit misleading, e.g. the function name GetRowCount
suggests that it returns the number of rows of whatever I give it. However, what it returns is the number of rows of the later output. So, one could simply call it OutputRowCount
, which also follows the general guideline to use nouns that describe the return value for functions.
Another things with the naming is that it sticks a bit much to the role of things in the implementation and not to what they are. Naming things after what they are can make understanding the code much faster. E.g. using inputColumnIndex
instead of recursionDepth
would immediately tell the reader that you are dealing with this specific input column right now. Then the technical maxRecursionDepth
could also be lastColumnIndex
or countOfColumns
. Similarly, the rather ominous recursionInputColumnPopulationIndex(recursionDepth)
could be currentInputIndex(inputColumnIndex)
. So generally, my advice would be to name things after what they are and not their implementation purpose.
Consistency of Semantic Levels
Programmers, me included, are notoriously bad a keeping semantic levels consistent in procedures. To explain what I mean take a look at RecursiveParametricSweep
. It does some high level orchestration like calling the procedure to populate the input columns, calling a function to get the number of output rows, calling the procedure to populate the output array and assigning the return value. However, in between it goes into the detail of how to handle headers. This is a break in semantic level of the procedure that throws one off a bit when first reading the procdure. This could be avoided by extracting either an InitializeOutputArray
or a WriteHeaders
procedure.
Miscellaneous
- The global variable
maxRecursionDepth
is a bit superfluous since it is justUBound(inputColumns)
, which is a bit clearer semantically, I think. - Instead of incrementing
recursionInputColumnPopulationIndex(recursionDepth)
, you could just always set it topopulateElementCount
at the start of the loop, which might be calledcurrentInputIndex
instead. - Istead of keeping track of the indeces for the columns in an array, you might just as well keep track of the values in an array instead. That would put the choice of value closer to the action for the specific column.
- It looks a bit strange to have the
populationRow
counter as a module level variable. You could avoid this by passing itByRef
into the recursive procedure. - It might make sense to extract a
PopulateRow
procedure to keep semantic levels consitsent.
$endgroup$
This looks like a decent recursive implementation. So, this is mainly about style and readability.
First, I would like to talk about two things which are really hard and could use some improvement here, naming and consistency of semantic levels. Then I have some more miscellaneous comments.
Naming
Generally, the naming is not too bad, but some of the names are a bit misleading, e.g. the function name GetRowCount
suggests that it returns the number of rows of whatever I give it. However, what it returns is the number of rows of the later output. So, one could simply call it OutputRowCount
, which also follows the general guideline to use nouns that describe the return value for functions.
Another things with the naming is that it sticks a bit much to the role of things in the implementation and not to what they are. Naming things after what they are can make understanding the code much faster. E.g. using inputColumnIndex
instead of recursionDepth
would immediately tell the reader that you are dealing with this specific input column right now. Then the technical maxRecursionDepth
could also be lastColumnIndex
or countOfColumns
. Similarly, the rather ominous recursionInputColumnPopulationIndex(recursionDepth)
could be currentInputIndex(inputColumnIndex)
. So generally, my advice would be to name things after what they are and not their implementation purpose.
Consistency of Semantic Levels
Programmers, me included, are notoriously bad a keeping semantic levels consistent in procedures. To explain what I mean take a look at RecursiveParametricSweep
. It does some high level orchestration like calling the procedure to populate the input columns, calling a function to get the number of output rows, calling the procedure to populate the output array and assigning the return value. However, in between it goes into the detail of how to handle headers. This is a break in semantic level of the procedure that throws one off a bit when first reading the procdure. This could be avoided by extracting either an InitializeOutputArray
or a WriteHeaders
procedure.
Miscellaneous
- The global variable
maxRecursionDepth
is a bit superfluous since it is justUBound(inputColumns)
, which is a bit clearer semantically, I think. - Instead of incrementing
recursionInputColumnPopulationIndex(recursionDepth)
, you could just always set it topopulateElementCount
at the start of the loop, which might be calledcurrentInputIndex
instead. - Istead of keeping track of the indeces for the columns in an array, you might just as well keep track of the values in an array instead. That would put the choice of value closer to the action for the specific column.
- It looks a bit strange to have the
populationRow
counter as a module level variable. You could avoid this by passing itByRef
into the recursive procedure. - It might make sense to extract a
PopulateRow
procedure to keep semantic levels consitsent.
answered Sep 28 at 8:55
M.DoernerM.Doerner
1,1614 silver badges9 bronze badges
1,1614 silver badges9 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229781%2frecursive-code-to-generate-a-parametric-sweep-of-input-values%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown