Frage

Was ist der einfachste Weg, um ein Drei-Wege-Exklusiv-Oder?

zu tun

Mit anderen Worten, ich habe drei Werte, und ich möchte eine Erklärung, dass die Werte TRUE IFF nur ein der drei Werte wahr ist.

Bisher das ist, was ich habe kommen mit:

((a ^ b) && (a ^ c) &&! (B && c)) || ((B ^ a) && (b ^ c) &&! (A && c)) || ((C ^ a) && (c ^ b) &&! (A && b))

Gibt es etwas einfacher, das Gleiche zu tun?


Hier ist der Beweis dafür, dass die obige Aufgabe erfüllt:

a = true; b = true; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = true; b = true; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = true; b = false; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = true; b = false; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> true

a = false; b = true; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = false; b = true; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> true

a = false; b = false; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> true

a = false; b = false; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false
War es hilfreich?

Lösung

Für genau drei Begriffe, können Sie diesen Ausdruck verwenden:

(a ^ b ^ c) && !(a && b && c)

Der erste Teil ist true iff ein oder drei der Begriffe true sind. Der zweite Teil des Ausdrucks stellt sicher, dass nicht alle drei sind true.

Beachten Sie, dass der obige Ausdruck tut nicht zu mehr Begriffe verallgemeinern. Eine allgemeine Lösung ist eigentlich count , wie viele Begriffe sind true, so etwas wie folgt aus:

int trueCount =
   (a ? 1 : 0) +
   (b ? 1 : 0) +
   (c ? 1 : 0) +
   ... // more terms as necessary 

return (trueCount == 1); // or some range check expression etc

Andere Tipps

bool result = (a?1:0)+(b?1:0)+(c?1:0) == 1;

a^b^c ist nur 1, wenn eine ungerade Anzahl von Variablen ist 1 (zwei ‚1‘ gegenseitig aufheben würde). So dass Sie nur für den Fall zu überprüfen, müssen „alle drei sind 1“:

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

Eine andere Möglichkeit:

a ? !b && !c : b ^ c

, die 9 Zeichen kürzer als die akzeptierte Antwort sein geschieht:)

Sie können auch versuchen (in C):

!!a + !!b + !!c == 1

Hier ist eine allgemeine Implementierung, die schnell schlägt fehl, wenn mehr als ein bool gefunden wird true sein.

Verwendung :

XOR(a, b, c);

Code :

public static bool XOR(params bool[] bools)
{
    return bools.Where(b => b).AssertCount(1);
}

public static bool AssertCount<T>(this IEnumerable<T> source, int countToAssert)
{
    int count = 0;
    foreach (var t in source)
    {
        if (++count > countToAssert) return false;
    }

    return count == countToAssert;
}
f= lambda{ |a| [false, false, true].permutation.to_a.uniq.include? a }
p f.call([false, true, false])
p f.call([false, true, true])
  

$ true

     

$ false

Weil ich es kann.

Noch besser wäre es auf Python:

result = (1 if a else 0)+(1 if b else 0)+(1 if c else 0) == 1

Dies kann auch auf, wenn Anweisungen verwendet werden!

Es sparte meinen Tag für CLI sich gegenseitig ausschließende Argumente durch Click (alle Hasse klicken)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top