2010-08-12 32 views
28

Cách đơn giản nhất để thực hiện OR độc quyền ba chiều là gì?XOR của ba giá trị

Nói cách khác, tôi có ba giá trị và tôi muốn một tuyên bố đánh giá đúng IFF chỉ một trong ba giá trị là đúng.

Cho đến nay, đây là những gì tôi đã đưa ra:

(! (A^b) & & (a^c) & & (b & & c)) || ((b^a) & & (b^c) & &! (a & & c)) || ((C^a) & & (c^b) & &! (Một & & b))

Có một cái gì đó đơn giản để làm điều tương tự?


Đây là bằng chứng cho thấy ở trên hoàn thành nhiệm vụ:

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 

Trả lời

34

Đối với đúng ba điều kiện, bạn có thể sử dụng biểu thức này:

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

Phần đầu tiên là true iff một hoặc ba các điều khoản là true. Phần thứ hai của biểu thức đảm bảo rằng không phải tất cả ba là true.

Lưu ý rằng biểu thức trên không làm KHÔNG khái quát hóa với nhiều cụm từ hơn. Một giải pháp tổng quát hơn là để thực sự đếm bao nhiêu thuật ngữ này true, vì vậy một cái gì đó như thế này:

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

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

Tuyệt vời, nhưng các giải pháp chung không ngắn mạch. – Ani

+0

'a? 1: 0' có thể được đơn giản hóa thành '!! a' – kaspersky

+0

@ gg.kaspersky, chỉ bằng JavaScript, C và các ngôn ngữ có kiểm tra sự thật/sai thông qua toán tử'! '. Ví dụ, điều này sẽ không hoạt động trong Java hoặc C#. –

9

a^b^c chỉ là 1 nếu một số lượng không đồng đều của các biến là 1 (hai '1' sẽ triệt tiêu lẫn nhau). Vì vậy, bạn chỉ cần kiểm tra đối với trường hợp "cả ba đều 1":

result = (a^b^c) && !(a&&b&&c) 
9
bool result = (a?1:0)+(b?1:0)+(c?1:0) == 1; 
+1

Tôi thích điều đó. Rất đơn giản và dễ hiểu. –

+0

Đơn giản nhất và phải dễ hiểu khi đọc mã (tốt, tôi sẽ thêm vài khoảng trắng) – gerardw

5

Một khả năng khác:

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

đó sẽ xảy ra là 9 ký tự ngắn hơn câu trả lời được chấp nhận :)

1

Đây là triển khai chung không nhanh chóng khi nhiều hơn bool được tìm thấy là true.

Cách sử dụng:

XOR(a, b, c); 

:

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; 
} 
1
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

Vì tôi có thể.

2

Bạn cũng có thể thử (trong C):

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

+0

Điều này chỉ hợp lệ ở một số ngôn ngữ [ví dụ: javascript] và không đơn giản hóa. Trong một ngôn ngữ tự động chuyển đổi boolean thành số cho '+', nếu 'a',' b' và 'c' đã là boolean, bạn cũng không cần phép phủ định kép '!!': chỉ cần 'a + b + c === 1' sẽ là tương đương. – blgt

+1

@ blgt, sai lầm của tôi, tôi nên xác định rằng tôi có nghĩa là một câu trả lời cho ngôn ngữ C. – kaspersky

+0

Sử dụng '!!' để đảm bảo C đúng là '1' thực sự là khá gọn gàng. Một chút hoang tưởng trong bối cảnh của một câu hỏi logic boolean mặc dù. Nếu phần còn lại của mã của bạn được viết tốt, 'a + b + c == 1' vẫn phải đủ – blgt

Các vấn đề liên quan