Pergunta

Eu tenho três valores booleanos A, B e C. Eu preciso escrever uma instrução IF que irá executar se e somente se não mais do que um desses valores é True. Em outras palavras, aqui está a tabela verdade:

 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

Qual é a melhor maneira de escrever isso? Eu sei que posso enumerar todas as possibilidades, mas que parece ... muito detalhado. : P

Adicionado: Apenas teve uma idéia:

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

Isto verifica que não há dois valores são definidos. A sugestão sobre somas é OK também. Ainda mais legível talvez ...

(a 1:? 0) + (B 1:? 0) + (C 1?: 0) <= 1

P.S. Isto é para o código de produção, então eu vou mais para facilitar a leitura de código de desempenho.

Adicionado 2: resposta já aceito, mas para os curiosos - é C #. :) A questão é muito bonito embora a linguagem-agnóstico.

Foi útil?

Solução

Como cerca de tratá-los como número inteiro 1 e 0, e verificando que a sua soma é igual a 1?

Editar :

Agora que sabemos que é c # .net, eu acho que a solução mais legível ficaria um pouco como

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

acima escondido em uma biblioteca de classe (? Appcode), onde não temos para vê-lo, mas facilmente pode acessá-lo (ctrl + clique no r #, por exemplo) e, em seguida, a implementação será simplesmente:

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

...

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

Outras dicas

Você shold familiarizar com Karnaugh mapeia . Concept é mais frequentemente aplicada a eletrônica, mas é muito útil aqui também. É muito fácil (pensou Wikipedia explicação faz olhar longo - é completa).

(A XOR B XOR C) ou não (A ou B ou C)

Edit:. Como apontado por Vilx, isso não está certo

Se A e B são ambos 1, e C é 0, A XOR B será de 0, o resultado global será 0.

Como sobre: NÃO (A e B) e NOT (A e C) e NOT (B e C)

Se você virar a lógica ao redor, você quer a condição de ser falso, se você tem qualquer par de booleans que são ambos true:

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

Para algo completamente diferente, você pode colocar os booleans em uma matriz e contar quantos valores verdade que são:

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

Eu iria para manutenção máxima e legibilidade.

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

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

Existem muitas respostas aqui, mas eu tenho uma outra!

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

Uma forma geral de encontrar uma expressão booleana mínimo para uma determinada tabela verdade é usar um mapa de Karnaugh:

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

Existem várias minimizadores online na web. A um aqui (ligada à do artigo, é em alemão, embora) encontra a seguinte expressão:

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

Se você estiver indo para a legibilidade do código, porém, eu provavelmente ir com a ideia de "sum <= 1". Tome cuidado para que nem todos os idiomas garante que falsa == 0 e verdadeiro == 1 - mas provavelmente você está ciente disso, uma vez que você tenha tomado o cuidado de que em sua própria solução.

Boa ol' lógica:

+ = 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))

Tome a dica e simplificar ainda mais se quiser.

E sim, obter a sua auto familiarizar com Karnaugh mapas

Depende se você quer algo que é fácil de entender o que você está tentando fazer, ou algo que é tão logicamente simples quanto pode ser. Outras pessoas estão postando respostas logicamente simples, então aqui está uma em que é mais claro o que está acontecendo (e que o resultado será para diferentes inputs):

  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"

Eu gosto da solução disso, mas aqui é um hack para fazer isso com campos de bits também.

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 */ }

Código demonstração da solução d's:

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

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

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top