Question

J'ai trois valeurs booléennes A, B et C. Je dois écrire une instruction IF qui exécutera si et seulement si plus d'une de ces valeurs est vrai. En d'autres termes, voici la table de vérité:

 A | B | C | Result
---+---+---+--------
 0 | 0 | 0 |   1
 0 | 0 | 1 |   1
 0 | 1 | 0 |   1
 0 | 1 | 1 |   0
 1 | 0 | 0 |   1
 1 | 0 | 1 |   0
 1 | 1 | 0 |   0
 1 | 1 | 1 |   0

Quelle est la meilleure façon d'écrire cela? Je sais que je peux énumérer toutes les possibilités, mais cela semble ... trop bavard. : P

Ajouté: Je viens juste d'une idée:

! (A && B) &&! (B && C) &&! (A && C)

vérifie que deux valeurs sont définies. La suggestion au sujet des sommes est bien aussi. Encore plus lisible peut-être ...

(A 1: 0) + (B 1: 0) + (C 1: 0) <= 1

P.S. Ceci est pour le code de production, donc je vais plus pour la lisibilité du code que la performance.

Ajouté 2: déjà accepté réponse, mais pour les curieux - c'est C #. :) La question est à peu près la langue agnostique bien.

Était-ce utile?

La solution

Que diriez-vous de les traiter comme entier 1 et 0, et vérifier que leur somme est égale à 1?

EDIT :

maintenant que nous savons que c'est c # .net, je pense que ressemblerait un peu comme la solution la plus lisible

public static class Extensions
{
    public static int ToInt(this bool b)
    {
        return b ? 1 : 0;
    }
}

niché au-dessus de loin dans une bibliothèque de classes (? AppCode) où on n'a pas le voir, mais peut facilement y accéder (Ctrl + clic dans r #, par exemple) et la mise en œuvre seront simplement:

public bool noMoreThanOne(params bool[] bools) 
{ 
    return bools.ToList().Sum(b => b.ToInt()) <= 1; 
}

...

bool check = noMoreThanOne(true, true, false, any, amount, of, bools);

Autres conseils

Vous shold vous familiariser avec Karnaugh Cartes . Concept est le plus souvent appliquée à l'électronique, mais est très utile ici aussi. Il est très facile (pensée explication Wikipédia ne semble à long - il est complet).

(A XOR B XOR C) ou non (A, B ou C)

Modifier. Comme l'a souligné Vilx, ce n'est pas juste

Si A et B sont tous deux 1 et C est 0, A XOR B sera 0, le résultat global sera 0.

Que diriez-vous: PAS (A et B) ET NON (A et C) ET NON (B et C)

Si vous tournez la logique autour, vous voulez la condition d'être fausse si vous avez une paire de booléens qui sont à la fois vrai:

if (! ((a && b) || (a && c) || (b && c))) { ... }

Pour quelque chose de complètement différent, vous pouvez mettre les booléens dans un tableau et compte combien de vraies valeurs, il y a:

if ((new bool[] { a, b, c }).Where(x => x).Count() <= 1) { ... }

Je vais pour la maintenabilité et la lisibilité maximale.

static bool ZeroOrOneAreTrue(params bool[] bools)
{
    return NumThatAreTrue(bools) <= 1;
}

static int NumThatAreTrue(params bool[] bools)
{
    return bools.Where(b => b).Count();
}

Il y a beaucoup de réponses, mais j'avoir un autre!

a ^ b ^ c ^ (a == b && b == c)

D'une manière générale de trouver une expression booléenne minimale pour une table de vérité donnée est d'utiliser une carte Karnaugh:

http://babbage.cs.qc.edu/courses/Minimize/

Il y a plusieurs minimiseurs en ligne sur le web. Celui ici (lié à de l'article, il est en allemand, bien que) trouve l'expression suivante:

(! A &&! B) || (! A &&! C) || (! B &&! C)

Si vous allez pour la lisibilité du code, cependant, je ne serais probablement aller avec l'idée de « somme <= 1 ». Veillez à ce que toutes les langues ne garantissent pas que de faux == 0 et vrai == 1 - mais vous êtes probablement au courant de cela depuis que vous avez pris en charge dans votre propre solution.

Bon ol » logique:

+ = OR
. = AND

R = Abar.Bbar.Cbar + Abar.Bbar.C + Abar.B.Cbar + A.Bbar.Cbar
  = Abar.Bbar.(Cbar + C) + Abar.B.Cbar + A.Bbar.Cbar
  = Abar.Bbar + Abar.B.Cbar + A.Bbar.Cbar
  = Abar.Bbar + CBar(A XOR B)
  = NOT(A OR B) OR (NOT C AND (A XOR B))

Prenez l'indice et simplifier davantage si vous voulez.

Et oui, obtenir votre auto familier avec Karnaugh carte

dépend si vous voulez quelque chose où il est facile de comprendre ce que vous essayez de faire, ou quelque chose qui est aussi logiquement simple que possible. D'autres personnes affichent logiquement des réponses simples, alors voici une où il est plus clair ce qui se passe (et ce sera le résultat pour les entrées différentes):

  def only1st(a, b, c):
    return a and not b and not c

  if only1st(a, b, c) or only1st(b, a, c) or only1st(c, a, b):
    print "Yes"
  else:
    print "No"

J'aime la solution d'addition, mais voici un hack pour le faire avec des champs de bits ainsi.

inline bool OnlyOneBitSet(int x)
{
    // removes the leftmost bit, if zero, there was only one set.
    return x & (x-1) == 0;
}

// macro for int conversion
#define BOOLASINT(x) ((x)?1:0)

// turn bools a, b, c into the bit field cba
int i = (BOOLASINT(a) << 0) | BOOLASINT(b) << 1 | BOOLASINT(c) << 2;

if (OnlyOneBitSet(i)) { /* tada */ }

démonstration du code de la solution d':

int total=0;
if (A) total++;
if (B) total++;
if (C) total++;

if (total<=1) // iff no more than one is true.
{
    // execute

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top