Link to home
Start Free TrialLog in
Avatar of muis2002
muis2002

asked on

Algorithm (Combination)

Anyone know any good algorithm to print all "N" combinations from 13?

What I meant of combination is like this :

numbers =  0,1,2,3,4,5,6,7,8,9,10,11,12

5 combination from numbers :

0,1,2,3,4
0,1,2,3,5
0,1,2,3,6
0,1,2,3,7
...
... etc.

The sequence is not important. So, because you have 0,1,2,3,4, you do not need to output 1,2,3,4,0

I am not good in math, so maybe the correct terms is not combination.
Avatar of Lesko987
Lesko987

Hi muis2002,

You must create 5 loops

Var I1, I2, I3, I4, I5, MinNum, MaxNum: Integer
Begin
  MinNum := 0;
  MaxNum := 12
  For I1 := MinNum To MaxNum - 4 Do
    For I2 := I1 To MaxNum - 3 Do
      For I3 := I2 To MaxNum - 2 Do
        For I4 := I3 To MaxNum - 1 Do
          For I5 := I4 To MaxNum Do Begin
            S := IntToStr (I1) + ',' + IntToStr (I2) + ',' + IntToStr (I3) + ',' + IntToStr (I4) + ',' + IntToStr (I5);
// depending on where you want to write
            WriteLn (S);
          End;

Regards Aleš
Lesko987,

Sorry, a few sintax errors. Here is corrected one.

Var I1, I2, I3, I4, I5, MinNum, MaxNum: Integer; S : String;
Begin
  MinNum := 0;
  MaxNum := 12;
  For I1 := MinNum To MaxNum - 4 Do
    For I2 := I1 To MaxNum - 3 Do
      For I3 := I2 To MaxNum - 2 Do
        For I4 := I3 To MaxNum - 1 Do
          For I5 := I4 To MaxNum Do Begin
            S := IntToStr (I1) + ',' + IntToStr (I2) + ',' + IntToStr (I3) + ',' + IntToStr (I4) + ',' + IntToStr (I5);
// depending on where you want to write
            WriteLn (S);
          End;
End;


Regards Aleš
Avatar of muis2002

ASKER

Not correct unfortunately.

I printed some of the first result :

0,0,0,0,0
0,0,0,0,1
0,0,0,0,2
0,0,0,0,3
0,0,0,0,4
0,0,0,0,5
0,0,0,0,6
0,0,0,0,7
0,0,0,0,8
0,0,0,0,9
0,0,0,0,10
0,0,0,0,11
0,0,0,0,12
ASKER CERTIFIED SOLUTION
Avatar of mokule
mokule
Flag of Poland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
+ 1 was missing.

Var I1, I2, I3, I4, I5, MinNum, MaxNum: Integer; S : String;
Begin
  MinNum := 0;
  MaxNum := 12;
  For I1 := MinNum To MaxNum - 4 Do
    For I2 := I1 + 1 To MaxNum - 3 Do
      For I3 := I2 + 1 To MaxNum - 2 Do
        For I4 := I3 + 1 To MaxNum - 1 Do
          For I5 := I4 + 1 To MaxNum Do Begin
            S := IntToStr (I1) + ',' + IntToStr (I2) + ',' + IntToStr (I3) + ',' + IntToStr (I4) + ',' + IntToStr (I5);
// depending on where you want to write
            WriteLn (S);
          End;
End;

// Here is a completely different approach!
// + you can change "TheSampleSize" (default 5 items), "TheNumber of elements" (default 13 items), and
// the "elements" could be almost anything; not just consecutive numbers from 0..12.
//
// Flexibility, I like it.
//

const
  maxelements:  integer=13;
  samplesize:   integer=5;
  elements:     array[1..13] of string=( ' 0',' 1',' 2',' 3',' 4',' 5',' 6',' 7',' 8',' 9','10','11','12');

procedure TForm1.Button1Click(Sender: TObject);
var
  i1,i2,i3:     Integer;
  s1:           String;
  sall:         String;
begin
  sall:='';

//  memo1.Lines.clear;

  for i2:=1 to maxelements do sall:=sall+elements[i2]+',';

  for i1:=1 to maxelements-(samplesize-2) do
    begin
      for i2:=1 to maxelements do
        begin
          s1:='';
          for i3:=1 to pred(samplesize) do
            s1:=s1+elements[i1+i3-1]+',';

          if ((i1=1) or ((i1>1) and (abs(i2-i1)>1))) then
            if pos(elements[i2]+',',s1)=0 then
              begin
                s1:=s1+elements[i2];
                // memo1.Lines.add(s1);
                writeln(s1);
              end;
        end;
    end;
end;
Avatar of aikimark
Although I don't have time to create a fully coded solution, I did something similar as part of an NP Complete problem (EE question Q_20908880 in the MSAccess forum).

If anyone is interested in doing a Delphi implementation of this is welcome to do so.  Here are the elements of this solution.
1. Create a bitCount[0..255] array of byte or short integer datatype;
2. Fill the bitCount array items with a loop from 1 to 255.  The zero position is already = 0.  For each of the first 8 bit positions in the iteration variable for this loop, check for the presence of a 1 at each position.
Example:
for J := 1 to 255 do begin
  count := 0;
  for I := 0 to 7 do begin
      //do an AND bitwise operation
      if ((J AND (2^I)) <> 0) then
        count := count +1;
  end;
  bitCount[J] := count;
end;

3. Allocate a four byte array. (Fourbytes[0..3])
4. Look for all numeric values whose binary representation contains the number of bits you are looking for.  (in this question, this is 5 items out of a 12 item list)
for J := (2^5-1) to (2^12-1) do begin
  Fourbytes[0] := ntohl(J);  // you might need to copy the bytes
  if (bitCount[Fourbytes[0]]+bitCount[Fourbytes[1]]+bitCount[Fourbytes[2]]+bitCount[Fourbytes[3]] ) = 5 do begin
// do your output here associating the 1 bit positions with the
// items in your list

end;

end;

========================
Notes:
* This works for all list sizes up to 30 items and all items between 1 and the list size.
* Once the bitCount table is initialized, this process is FAST
* The ntohl is required to reverse the bytes of a long iteger in the Windows little-endian environment.  ntohl is a Windows API.
* If you match the order of the long integer bytes with the order of the items in your list, you should be able to just (memory) copy the long integer bytes to the FourBytes array space.
* This is a flexible implementation.
* Counting bits efficiently was one of the keys to solving this problem in a reasonable amount of time.
<<...maybe the correct terms is not combination>>

It is the correct term for N things taken P at a time.

The formula for this is: N! / (P! * ((N-P)!) )

So you can expect to 1287 items (13 things taken 5 at a time)