Reputation: 726
I have a function which is evaluate multiple (7, in my case) boolean variables and conditions and the result is true if only one of them true (and the rest false of course). I have the following code:
function GetExclusiveTrue: boolean;
begin
Result:= (
Integer(BoolVar1) +
Integer(BoolVar2) +
Integer(BoolFunc3) +
Integer(BoolVar4) +
Integer(BoolFunc5) +
Integer(BoolVar6) +
Integer(BoolVar7)) = 1;
end;
I'm just wondering if there is any better solution than this?
PS: I think I haven't defined properly what is my problem.
I'm looking for a solution using logical operators only, without any casting involved.
PS2: Look like I can't explain properly what I'm looking for. I want to see a solution without iteration, selection, function calls, etc. ONLY boolean operators allowed. Why? I just want to know if that is possible or not. Looking for a combination of logical operations which provides the same result as the function above.
Upvotes: 3
Views: 2703
Reputation: 613612
I want to see a solution without iteration, selection, function calls, etc. ONLY boolean operators allowed. Why? I just want to know if that is possible or not. Looking for a combination of logical operations which provides the same result as the function above.
You want to implement this using only logical and
, or
, xor
and not
operators. That goes like this:
Result :=
(b1 and not (b2 or b3 or b4))
or (b2 and not (b1 or b3 or b4))
or (b3 and not (b1 or b2 or b4))
or (b4 and not (b1 or b2 or b3));
I gave an example with just four booleans but the concept is the same for any number.
Upvotes: 4
Reputation: 25
A better solution could be, you do a open array as
function GetExclusiveTrue(Values: array of Boolean ): Boolean;
and make a sum througth iteration.
Upvotes: 0
Reputation: 80211
Here's a function to calculate only-1-true, regardless of the number of booleans to check:
function GetExclusiveTrue(boolarray: array of Boolean) : Boolean;
var
arrayindex : integer;
begin
result := false;
for arrayindex := 0 to high(boolarray) do
if boolarray[arrayindex] then
begin
result := not result;
if not result then exit;
end;
end;
First, assume a false
result, then scan through the supplied array. Set the return value true on the first true
found (if any) and clear the return value and exit if a second is found true
.
This is a special case of counting how many are true:
function howmanytrue(boolarray: array of Boolean) : integer;
var
arrayindex : integer;
begin
result := 0;
for arrayindex := 0 to high(boolarray) do
if boolarray[arrayindex] then inc(result);
end;
Obviously, GetExclusiveTrue = howmanyaretrue([your Booleans]) = 1 but this allows other questions like are none/all/all-but-1/majority/at-least-3/no-more-than-2/exactly-half true
(assuming you know the number of Booleans you are examining.)
I tested this with a set of 11 checkboxes and 2 panels
procedure TForm1.CheckBoxClick(Sender: TObject);
begin
Panel1.Caption := BoolToStr(GetExclusiveTrue([checkbox1.Checked,checkbox2.Checked,checkbox3.Checked,checkbox4.Checked,checkbox5.Checked,checkbox6.Checked,checkbox7.Checked,checkbox8.Checked,checkbox9.Checked,checkbox10.Checked,checkbox11.Checked]),true);
Panel2.Caption := IntToStr(howmanytrue([checkbox1.Checked,checkbox2.Checked,checkbox3.Checked,checkbox4.Checked,checkbox5.Checked,checkbox6.Checked,checkbox7.Checked,checkbox8.Checked,checkbox9.Checked,checkbox10.Checked,checkbox11.Checked]));
end;
Upvotes: 4
Reputation: 1319
If you don't want to cast, then you can achieve the same thing this way:
function GetExclusiveTrue: boolean;
var
Count: Integer;
begin
Count := 0;
if BoolVar1 then
Inc(Count);
if BoolVar2 then
Inc(Count);
if BoolFunc3 then
Inc(Count);
if BoolVar4 then
Inc(Count);
if BoolFunc5 then
Inc(Count);
if BoolVar6 then
Inc(Count);
if BoolVar7 then
Inc(Count);
Result := (Count = 1);
end;
Upvotes: 1