Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enumerate possible set values in Delphi

Tags:

set

delphi

I have a calculation algorithm in Delphi with a number of different options, and I need to try every combination of options to find an optimal solution.

TMyOption = (option1, option2, option3, option4);
TMyOptions = set of TMyOption;

I wondered about using an Integer loop to enumerate them:

for EnumerationInteger := 0 to 15 do begin
    Options := TMyOptions(EnumerationInteger);
end;

This does not compile. What I was wondering was if there was any fairly simple method to convert from Integer to Set (most questions on the Web try to go the other way, from Set to Integer), and if so what is it?

Another possibility is to just use the Integer as a bit-field:

C_Option1 = 1;
C_Option2 = 2;
C_Option3 = 4;
C_Option4 = 8;

and then test membership with a bitwise and:

if (Options and C_Option2) > 0 then begin
    ...
end;

I've tried this, and it works, but it feels like working with sets would be more natural and use the type system better (even though I'm going outside the said type system to enumerate the sets).

Is there a better/safer way to enumerate all possible set combinations than enumerating the underlying integer representation?

Notes:

  1. I know that the integer values of a set are not guaranteed in theory (though I suspect they are in practice if you don't play with the enumeration numbering).
  2. There could be more than four options (yes, I know that it grows exponentially and if there are too many options the algorithm could take forever).
like image 202
Jonathan Morgan Avatar asked Nov 04 '10 00:11

Jonathan Morgan


3 Answers

I know this question is quite old, but this is my preference since it's simple and natural to me :

function NumericToMyOptions(n: integer): TMyOptions;
var
  Op: TMyOption;
begin
  Result:= [];
  for Op:= Low(TMyOption) to High(TMyOption) do
    if n and (1 shl ord(Op)) > 0 then Include(Result, Op);
end;
like image 98
Hasan S Avatar answered Oct 31 '22 03:10

Hasan S


Try

var EnumerationByte: Byte;
...
for EnumerationByte := 0 to 15 do begin
    Options := TMyOptions(EnumerationByte);
end;
like image 41
500 - Internal Server Error Avatar answered Oct 31 '22 03:10

500 - Internal Server Error


Your code does not compile because your enumeration (TMyOption) have less than 8 values, and Delphi utilize the minimum possible size (in bytes) for sets. Thus, a byte variable will work for you.

If you have a set with more than 8 but less than 16 possible elements, a Word will work (and not an integer).

For more than 16 but less than 32 a DWord variable and typecast.

For more than 32 possible elements, I think a better approach is to use an array of bytes or something like that.

like image 2
jachguate Avatar answered Oct 31 '22 04:10

jachguate