Evaluate only a few boolean conditions, only one can be true (Delphi)
I have a function that evaluates several (7, in my case) boolean variables and conditions, and the result is correct if only one of them is true (and the rest is 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 a better solution than this?
PS : I think I misidentified what my problem is.
I am looking for a solution using only boolean operators, no casting involved.
PS2 : It looks like I can't explain correctly what I'm looking for. I want to see a solution without iteration, selection, function calls, etc. Only boolean operators are allowed. What for? I just want to know if this is possible or not. Finding a combination of logical operations that provide the same result as the function above.
source to share
I want to see a solution without iteration, selection, function calls, etc. Only boolean operators are allowed. What for? I just want to know if this is possible or not. Finding a combination of logical operations that provide the same result as the function above.
You want to implement this using only logical operators and
, or
, xor
and not
. It works 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 four booleans, but the concept is the same for any number.
source to share
Here's a function to compute only-1-true, regardless of the number of gates to be checked:
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 the result false
, then scan the resulting array. Set the return value to true on the first one found true
(if any) and clear the return value and exit if a second is found true
.
This is a special case of counting the amount of truth:
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 = howmanyretrue ([your Booleans]) = 1, but this allows you to ask other questions such as are none/all/all-but-1/majority/at-least-3/no-more-than-2/exactly-half true
(if you know the number of entities you are checking.)
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;
source to share
If you don't want to throw, then you can achieve the same:
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;
source to share