((a xor b) xor (c xor d)) and ((a or b) and (c or d))
第一个表达式搜索4个中的1或3个true
。第二个表达式消除4个中的0或1(有时是2)true
。
Java 8,过滤掉错误的值,并计数剩余的正确值:
public static long count(Boolean... values) {
return Arrays.stream(values).filter(t -> t).count();
}
if (3 == count(a, b, c, d)) {
System.out.println("There... are... THREE... lights!");
}
轻松推广到检查 m
个项目中的 n
个是否为真。
以下是使用C#和LINQ的解决方法:
bool threeTrue = new[] { a, b, x, y }.Count(x => x) == 3;
那就是对称布尔函数S₃(4)
。对称布尔函数是一种仅取决于输入设置数量而不取决于其输入的布尔函数。Knuth在计算机程序设计艺术第4卷第7.1.2节中提到了这种类型的函数。
S₃(4)
可以通过以下方式使用7个操作来计算:
(x && y && (a || b)) ^ ((x || y) && a && b)
Knuth指出这是最优的,这意味着您不能使用常规运算符进行少于7次操作: &&, || , ^, <,
和 >
。
然而,如果您想在使用1
表示真和0
表示假的语言中使用它,您也可以轻松使用加法:
x + y + a + b == 3
这使得你的意图非常明确。
(a && b && (c xor d)) || (c && d && (a xor b))
从纯逻辑角度来看,我得出了以下结论。
根据抽屉原理,如果恰好有三个命题为真,则要么 a 和 b 为真,要么 c 和 d 为真。接下来只需要将这些情况中的每一种与另外两个命题之一相 “与” 即可。
mine <=> his
的等价,那么我不知道该说什么,因为这是可以预料的。 - Cruncherif (a)
{
if (b)
return (x != y); // a,b=true, so either x or y must be true
else
return (x && y); // a=true, b=false, so x AND y must be true
}
else
{
if (b)
return (x && y); // a=false, b=true, so x and y must be true
else
return false; // a,b false, can't get 3 of 4
}
"x != y"仅在x和y是布尔类型时才适用。如果它们是其他类型,其中0为false,而其他任何值均为true,这可能会失败。那么使用布尔异或,或者( (bool)x!=(bool)y ),或者编写“if (x) return (y==false) else return (y==true);”,这对计算机来说需要更多的工作。
如果您的编程语言提供三元运算符?:,您可以将其缩短为
if (a)
return b ? (x != y) : (x && y);
else
return b ? (x && y) : false;
可以稍微保留一些可读性,或者大幅简化它以...
return a ? (b ? (x != y) : (x && y)) : (b ? (x && y) : false);
这段代码进行了三次逻辑测试(a的状态、b的状态、x和y的比较),应该比这里其他答案更快。但是你需要加上注释,否则三个月后你可能无法理解它 :)
这里有很多好的答案;以下是其他人尚未发布的一种替代表述:
a ? (b ? (c ^ d) : (c && d)) : (b && c && d)
与第一个答案类似,但是纯Java实现:
int t(boolean b) {
return (b) ? 1 : 0;
}
if (t(x) + t(y) + t(a) + t(b) == 3) return true;
return false;
我更喜欢将它们视为整数,因为这样可以使代码更易读。
import itertools
arrays = list(itertools.product(*[[True, False]]*4))
实际测试
for array in arrays:
print(array, sum(array)==3)
输出
(True, True, True, True) False
(True, True, True, False) True
(True, True, False, True) True
(True, True, False, False) False
(True, False, True, True) True
(True, False, True, False) False
(True, False, False, True) False
(True, False, False, False) False
(False, True, True, True) True
(False, True, True, False) False
(False, True, False, True) False
(False, True, False, False) False
(False, False, True, True) False
(False, False, True, False) False
(False, False, False, True) False
(False, False, False, False) False
y = (x̄3 ^ x2 ^ x1 ^ x0) ∨ (x3 ^ x̄2 ^ x1 ^ x0) ∨ (x3 ^ x2 ^ x̄1 ^ x0) ∨ (x3 ^ x2 ^ x1 ^ x̄0)
如果您想以编程方式实现此目标,需要处理可变数量的变量以及自定义的“阈值”,则通过迭代布尔值列表并计算“true”出现次数是非常简单和直接的。
not a ^ not b ^ not c ^ not d
才为真。这意味着,在原来的值中,恰好有一个是假的。 - Ingo(!a&&b&&c&&d) || (a&&!b&&c&&d) || (a&&b&&!c&&d) || (a&&b&&c&&!d)
。 - Jason C