From: Shell on
In VB6 I have an application where I have 7 characters (numbers and/or
letters). I need to generate a list (probably in a database) on all possible
combinations of 3, 4, 5, 6, and 7 characters.

I keep getting mixed up, trying recursive functions, which I hate. Does
anyone have a simpler way of doing this?

Thanks
--
Shell
From: dpb on
Shell wrote:
> In VB6 I have an application where I have 7 characters (numbers and/or
> letters). I need to generate a list (probably in a database) on all possible
> combinations of 3, 4, 5, 6, and 7 characters.
>
> I keep getting mixed up, trying recursive functions, which I hate. Does
> anyone have a simpler way of doing this?

I got the last one... ;)

How about...

>> nchoosek([1:7],7)
ans =
1 2 3 4 5 6 7
>> nchoosek([1:7],6)
ans =
1 2 3 4 5 6
1 2 3 4 5 7
1 2 3 4 6 7
1 2 3 5 6 7
1 2 4 5 6 7
1 3 4 5 6 7
2 3 4 5 6 7
>> nchoosek([1:7],5)
ans =
1 2 3 4 5
1 2 3 4 6
1 2 3 4 7
1 2 3 5 6
1 2 3 5 7
1 2 3 6 7
1 2 4 5 6
1 2 4 5 7
1 2 4 6 7
1 2 5 6 7
1 3 4 5 6
1 3 4 5 7
1 3 4 6 7
1 3 5 6 7
1 4 5 6 7
2 3 4 5 6
2 3 4 5 7
2 3 4 6 7
2 3 5 6 7
2 4 5 6 7
3 4 5 6 7
>> nchoosek([1:7],4)
ans =
1 2 3 4
1 2 3 5
1 2 3 6
1 2 3 7
1 2 4 5
1 2 4 6
1 2 4 7
1 2 5 6
1 2 5 7
1 2 6 7
1 3 4 5
1 3 4 6
1 3 4 7
1 3 5 6
1 3 5 7
1 3 6 7
1 4 5 6
1 4 5 7
1 4 6 7
1 5 6 7
2 3 4 5
2 3 4 6
2 3 4 7
2 3 5 6
2 3 5 7
2 3 6 7
2 4 5 6
2 4 5 7
2 4 6 7
2 5 6 7
3 4 5 6
3 4 5 7
3 4 6 7
3 5 6 7
4 5 6 7
>> nchoosek([1:7],3)
ans =
1 2 3
1 2 4
1 2 5
1 2 6
1 2 7
1 3 4
1 3 5
1 3 6
1 3 7
1 4 5
1 4 6
1 4 7
1 5 6
1 5 7
1 6 7
2 3 4
2 3 5
2 3 6
2 3 7
2 4 5
2 4 6
2 4 7
2 5 6
2 5 7
2 6 7
3 4 5
3 4 6
3 4 7
3 5 6
3 5 7
3 6 7
4 5 6
4 5 7
4 6 7
5 6 7
>>

Ain't Matlab useful sometimes???? :)

--
From: dpb on
dpb wrote:
> Shell wrote:
....
>> ...need a list of all possible combinations of 3, 4, 5, 6, and 7
>> characters from seven.
>>
>> I keep getting mixed up, trying recursive functions, which I hate.
>> Does anyone have a simpler way of doing this?
>
> I got the last one... ;)
>
> How about...
>
> >> nchoosek([1:7],7)
> ans =
> 1 2 3 4 5 6 7
> >> nchoosek([1:7],6)
> ans =
> 1 2 3 4 5 6
> 1 2 3 4 5 7
....
> 3 5 6 7
> 4 5 6 7
> >> nchoosek([1:7],3)
> ans =
> 1 2 3
....
> 4 6 7
> 5 6 7
> >>
>
> Ain't Matlab useful sometimes???? :)
>
> --
Here's a recursive solution, in Matlab.

I've added some comments to the Matlab code to aid in converting it if
you wish to do the generation on the fly rather than use the results
stored as lookup tables. Assuming you have a string, the above can be
used iteratively as the index vectors into the string to select the
various combinations as desired.

function P = combs(v,m)

In Matlab, the syntax for a function is that the return value is the
variable following the keyword function. "Vector" is synonymous w/ 1D
array and "row/column" have same orientation as does VB (column-major
storage order)

%COMBS All possible combinations.
% COMBS(V,M) where V is a row vector of length N,
% creates a matrix with N!/((N-M)! M!) rows and M columns containing
% all possible combinations of N elements taken M at a time.
%
% This function is only practical for situations where M is less
% than about 15.

if nargin~=2, error('Requires 2 input arguments.'); end

v = v(:).'; % Make sure v is a row vector.

n = length(v); % == UBound-LBound+1
if n == m % the select 'em all case
P = v;
elseif m == 1 % the other extreme of only one at a time
% return n rows w/ one element each
% your case won't ever use this as you said m>2
P = v.';
else % all the rest...
P = []; % starts w/ empty array...
if m < n & m > 1 % culls out the possible erroneous input
for k = 1:n-m+1
Q = combs(v(k+1:n),m-1);
The [ ] enclose an array expression in Matlab. This will have to be
expanded into a nested loop in VB. The semicolon concatenates the
following expression as the next row in the array P.

Reading the expression [v(ones(size(Q,1),1),k) Q] from inside out,
size(Q,1) is the number of rows in Q this iteration (size of first
dimension of Q), we'll temporarily call it nRows.

Then ones(nRows,1) returns a 1D column array of ones and so
v(ones(nRows,1),k) is v(1,k) for each pass thru the loop. This value is
then concatenated onto the row.

P = [P; [v(ones(size(Q,1),1),k) Q]];
end
end
end


Enjoy!!! :)

I've gotta' run at the moment; if have some time later on maybe I'll see
about translating it (but no promises, have some other commitments)...

--
From: Mike S on
On 6/2/2010 8:28 AM, Shell wrote:
> In VB6 I have an application where I have 7 characters (numbers and/or
> letters). I need to generate a list (probably in a database) on all possible
> combinations of 3, 4, 5, 6, and 7 characters.
>
> I keep getting mixed up, trying recursive functions, which I hate. Does
> anyone have a simpler way of doing this?
>
> Thanks

Avoiding recursion I think you can do it this way, to keep it simple you
can use a separate sub for each different length string, how does this
look? Using this approach, to make a string 4 chars long you could use a
new variable n, etc. for longer strings. Is this what you were looking for?

Option Explicit

Private chars() As String, results() As String

Private Sub btnMakeString3_Click()
On Error GoTo btnMakeString3Err
Dim j As Long, k As Long, m As Long, ctr As Long
ctr = 1
ReDim results(1 To 7 ^ 3)
Text1.Visible = False
Text1.Text = ""
For j = 1 To 7
For k = 1 To 7
For m = 1 To 7
results(ctr) = chars(j) & chars(k) & chars(m)
Text1.Text = Text1.Text & results(ctr) & vbCrLf
ctr = ctr + 1
Next
Next
Next
Text1.Visible = True
DoEvents
Exit Sub
'
btnMakeString3Err:
MsgBox "Error " & Err.Number & " " & Err.Description
End Sub

Private Sub Form_Load()
ReDim chars(1 To 7)
chars(1) = "0"
chars(2) = "1"
chars(3) = "2"
chars(4) = "3"
chars(5) = "4"
chars(6) = "5"
chars(7) = "6"
End Sub
From: dpb on
dpb wrote:
....

I haven't had (or more correctly, taken the time :) ) to work on an
actual translation -- I'll have to think about how to even cast it as VB
for a little I think, but...

Look at what's left out each step and maybe that'll give you a head
start in working out a procedural way...

Ovbiously n-of-n has only one solution and n-1 of n is leaving out one
element from 1:n so those are trivial. So, let's look at the next, n-2
out of n--
> >> nchoosek([1:7],5)
> ans = % Omitted values
> 1 2 3 4 5 % 6 7
> 1 2 3 4 6 % 5 7
> 1 2 3 4 7 % 5 6
> 1 2 3 5 6 % 4 7
> 1 2 3 5 7 % 4 6
> 1 2 3 6 7 % 4 5
> 1 2 4 5 6 % 3 7
> 1 2 4 5 7 % 3 6
> 1 2 4 6 7 % 3 5
> 1 2 5 6 7 % 3 4
> 1 3 4 5 6 % 2 7
> 1 3 4 5 7 % 2 6
> 1 3 4 6 7 % 2 5
> 1 3 5 6 7 % 2 4
> 1 4 5 6 7 % 2 3
> 2 3 4 5 6 % 1 7
> 2 3 4 5 7 % 1 6
> 2 3 4 6 7 % 1 5
> 2 3 5 6 7 % 1 4
> 2 4 5 6 7 % 1 3
> 3 4 5 6 7 % 1 2

> >> nchoosek([1:7],4)
> ans =
> 1 2 3 4 % 5 6 7
> 1 2 3 5 % 4 6 7
> 1 2 3 6 % 4 5 7
> 1 2 3 7 % 4 5 6
> 1 2 4 5 % 3 6 7
> 1 2 4 6 % 3 5 7
> 1 2 4 7 % 3 5 6
> 1 2 5 6 % 3 4 7
> 1 2 5 7 % 3 4 6
> 1 2 6 7 % 3 4 5
....

Begin to see the pattern emerging?

BTW, the number for each is, as the code comments say, N!/[(N-K)! K!]
which for an example if you don't recall factorials

C(7,3) = 7!/[(7-3)! 3!] = 7!/[4! 3!] = [7x6x5x4!]/[4! 3!] = 7x6x5/3!
= (7x6x5)/(3x2x1) = 7x5 = 35

A VB routine to calculate the number based on the Pascal's triangle
method is

Function BinomCoef(n As Long, k As Long) As Long

' Binomial coefficient.
' BINOMCOEF(N,K) where N and K are non-negative integers returns
' N!/K!(N-K)!.
' This is the number of combinations of N things taken K at a time.

Dim c As Double
Dim i As Long, j As Long

If k > n / 2 Then
k = n - k
End If

If k <= 1 Then
BinomCoef = n ^ k
Return
End If

c = 1#
j = 1
For i = n - k + 1 To n
c = c * i / j
j = j + 1
Next i
BinomCoef = c
End Function

That'll at least tell you if you got 'em all... :)

--
 |  Next  |  Last
Pages: 1 2 3
Prev: Tom Shelton ...
Next: Instr problem in VB5