tcxbalage
tcxbalage

Reputation: 726

Evaluate multiple boolean conditions exclusively, only one can be true (Delphi)

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

Answers (4)

David Heffernan
David Heffernan

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

Wellington Ribeiro
Wellington Ribeiro

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

Magoo
Magoo

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

Rob McDonell
Rob McDonell

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

Related Questions