提问人:Simon Kuang 提问时间:3/7/2014 最后编辑:thefourtheyeSimon Kuang 更新时间:5/17/2014 访问量:14650
测试 3 个(共 4 个)为真的逻辑
Logic to test that 3 of 4 are True
答:
很长但非常简单,(析取)正态形式:
(~a & b & c & d) | (a & ~b & c & d) | (a & b & ~c & d) | (a & b & c & ~d)
它可能会被简化,但这需要更多的思考:P
评论
(a & b & (c ^ d)) | ((a ^ b) & c & d)
我能做的最好的是 ((x ^ y) ^ (a ^ b)) && ((a || x) && (b || y))
评论
不确定它是否更简单,但也许。
((x xor y) and (a and b)) or ((x and y) and (a xor b))
评论
#1:使用分支:3 或 4 次操作
A ^ B ? C & D : ( C ^ D ) & A
#2 非分支,7 个操作
(A ^ B ^ C ^ D) & ((A & B) | (C & D))
当我过去分析所有内容时,我发现非分支解决方案的操作速度要快得多,因为 CPU 可以更好地预测代码路径,并同时执行更多操作。不过,这里的分支语句中的工作量减少了大约 50%。
评论
这个答案取决于表示系统,但如果 0 是唯一被解释为 false 的值,并且总是返回相同的数值,那么应该可以解决问题。not(false)
not(a) + not(b) + not(c) + not(d) = not(0)
如果你追求的是纸上(非编程)解决方案,那么 K-maps 和 Quine-McCluskey 算法就是你所追求的,它们可以帮助你缩小布尔函数。
就您而言,结果是
y = (x̄3 ^ x2 ^ x1 ^ x0) ∨ (x3 ^ x̄2 ^ x1 ^ x0) ∨ (x3 ^ x2 ^ x̄1 ^ x0) ∨ (x3 ^ x2 ^ x1 ^ x̄0)
如果你想以编程方式做到这一点,非固定数量的变量和自定义的“阈值”,那么只需遍历布尔值列表并计算“true”的出现次数就非常简单明了。
评论
我建议以一种表明你的意思的方式编写代码。如果您希望 3 个值为真,那么在我看来,值 3 出现在某个地方似乎很自然。
例如,在:C++
if ((int)a + (int)b + (int)c + (int)d == 3)
...
这在 : the 中得到了很好的定义,表示转换为会给出预期值 0 或 1。C++
standard (§4.7/4)
bool
int
在 Java 和 C# 中,可以使用以下构造:
if ((a?1:0) + (b?1:0) + (c?1:0) + (d?1:0) == 3)
...
评论
if (!!a + !!b + !!c + !!d == 3)
更容易写,虽然我不知道编译器是否优化了这一点
请记住,对于编程问题,而不是仅仅是逻辑问题,答案显然取决于编程语言的选择。某些语言支持其他语言不常见的功能。
例如,在 C++ 中,您可以使用以下命令测试条件:
(a + b + c + d) == 3
这应该是在支持从布尔类型到整数类型的自动(低级)转换的语言中进行检查的最快方法。但同样,这个问题没有普遍的答案。
评论
要检查至少全部为真,(n 必须小于或等于:p总数)n
Boolean
Boolean
if (((a ? 1:0) + (b ? 1:0 ) + (c ? 1:0) + (d ? 1:0 )) >= n) {
// do the rest
}
编辑:在@Cruncher的评论之后
检查 3 分中的第 4 分boolean
if (((a ? 1:0) + (b ? 1:0 ) + (c ? 1:0) + (d ? 1:0 )) == 3) {
// do the rest
}
另一个:
((c & d) & (a ^ b)) |((a & b) & (c ^ d))
(详情)
评论
如果你想在编程语言中使用这个逻辑,我的建议是
bool test(bool a, bool b, bool c, bool d){
int n1 = a ? 1 : 0;
int n2 = b ? 1 : 0;
int n3 = c ? 1 : 0;
int n4 = d ? 1 : 0;
return n1 + n2 + n3 + n4 == 3;
}
或者,如果需要,可以将所有这些放在一行中:
return (a ? 1 : 0) + (b ? 1 : 0) + (C ? 1 : 0) + (d ? 1 : 0) == 3;
您也可以将此问题推广为:n of m
bool test(bool *values, int n, int m){
int sum = 0;
for(int i = 0; i < m; i += 1){
sum += values[i] ? 1 : 0;
}
return sum == n;
}
评论
如果这是 Python,我会写
if [a, b, c, d].count(True) == 3:
或
if [a, b, c, d].count(False) == 1:
或
if [a, b, c, d].count(False) == True:
# In Python True == 1 and False == 0
或
print [a, b, c, d].count(0) == 1
或
print [a, b, c, d].count(1) == 3
或
if a + b + c + d == 3:
或
if sum([a, b, c, d]) == 3:
所有这些都有效,因为布尔值是 Python 中整数的子类。
if len(filter(bool, [a, b, c, d])) == 3:
或者,受到这个巧妙技巧的启发,
data = iter([a, b, c, d])
if not all(data) and all(data):
评论
a=5;not not a == 1
布尔
:)
((a xor b) xor (c xor d)) and ((a or b) and (c or d))
拳头表达式在 4 个中搜索 1 或 3 个。第二个消除 0 或 1(有时是 2)中的 4。true
true
(a && b && (c xor d)) || (c && d && (a xor b))
从纯粹的逻辑角度来看,这就是我想出的。
根据鸽子洞原理,如果正好 3 为真,则 a 和 b 为真,或者 c 和 d 为真。然后,只需将这些案例中的每一个与另外 2 个案例中的一个进行处理即可。
评论
mine <=> his
当且仅当 4 个布尔值中有 3 个为 true 时,我想返回 true。
给定 4 个布尔值 a、b、x、y,此任务转换为以下 C 语句:
return (a+b+x+y) == 3;
评论
true
如果你使用像 Karnaugh Maps 这样的逻辑可视化工具,你会看到这是一个问题,如果你想用一行 if (...) 来写一个完整的逻辑术语,你就无法避免它。Lopina 已经展示了它,不可能写得更简单。你可以考虑一下,但它对你和机器来说都很难阅读。
计数解决方案还不错,它们显示了您真正追求的东西。如何有效地进行计数取决于您的编程语言。使用 Python 或 LinQ 的数组解决方案很好看,但请注意,这很慢。Wolf 的 (a+b+x+y)==3 可以很好地快速工作,但前提是您的语言将“true”等同于 1。如果 “true” 用 -1 表示,则必须测试 -3 :)
如果你的语言使用真正的布尔值,你可以尝试显式编程(我使用 != 作为 XOR 测试):
if (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 的比较),并且应该比这里的大多数其他答案更快。但是你需要评论它,否则3个月后你不会理解它:)
下面是使用 LINQ 在 C# 中解决该问题的方法:
bool threeTrue = new[] { a, b, x, y }.Count(x => x) == 3;
与第一个答案类似,但纯 Java:
int t(boolean b) {
return (b) ? 1 : 0;
}
if (t(x) + t(y) + t(a) + t(b) == 3) return true;
return false;
我更喜欢将它们算作整数,因为它使代码更具可读性。
这里有很多好的答案;这是其他人尚未发布的替代公式:
a ? (b ? (c ^ d) : (c && d)) : (b && c && d)
评论
Java 8,过滤掉 false 值,并计算剩余的 true 值:
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!");
}
轻松推广到检查项目是否为真。n
m
在 Python 中,要查看有多少个可迭代元素是 True,请使用(这非常简单):sum
设置
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
((a^b)^(x^y))&((a|b)&(x|y))
是你想要的。基本上,我拿走了你的代码并添加了检查是否真的 3 是真的而不是 3 是假的。
由于可读性是一个大问题,因此您可以使用描述性函数调用(包装任何建议的实现)。如果需要在多个地方进行此计算,则函数调用是实现重用的最佳方式,并明确说明您正在做什么。
bool exactly_three_true_from(bool cond1, bool cond2, bool cond3, bool cond4)
{
//...
}
一个没有涉及递归的答案的编程问题?不可思议!
有足够多的“正好 3 个 4 个真”的答案,但这里有一个通用的 (Java) 版本,用于“正好 m 个真”(否则递归真的不值得),因为你可以:
public static boolean containsTrues(boolean[] someBooleans,
int anIndex, int truesExpected, int truesFoundSoFar) {
if (anIndex >= someBooleans.length) {
return truesExpected == truesFoundSoFar; // reached end
}
int falsesExpected = someBooleans.length - truesExpected;
boolean currentBoolean = someBooleans[anIndex];
int truesFound = truesFoundSoFar + (currentBoolean ? 1 : 0);
if (truesFound > truesExpected) {
return false;
}
if (anIndex - truesFound > falsesExpected) {
return false; // too many falses
}
return containsTrues(someBooleans, anIndex + 1, truesExpected,
truesFound);
}
这可以用类似的东西来调用:
boolean[] booleans = { true, false, true, true, false, true, true, false };
containsTrues(booleans, 0, 5, 0);
它应该返回(因为 8 个值中有 5 个是真的,正如预期的那样)。对“真”和“假”这两个词不太满意,但现在想不出更好的名字......请注意,当找到太多或太多的值时,递归将停止。true
true
false
评论
true
containsNumberOfTrueValues()
doesArray: someBooleans startingAt: anIndex containNumberOfTrueValues: anExpectedNumber foundSofar: aNumberFoundSoFar
containsTruth
在 PHP 中,使其更具动态性(以防万一您更改条件的数量等):
$min = 6;
$total = 10;
// create our boolean array values
$arr = array_map(function($a){return mt_rand(0,1)>0;},range(1,$total));
// the 'check'
$arrbools = array_map(function($a){return (int)$a;},$arr);
$conditionMet = array_sum($arrbools)>=$min;
echo $conditionMet ? "Passed" : "Failed";
这就是对称布尔函数。对称布尔函数是一个布尔函数,它仅取决于设置的输入数量,但不依赖于它们是哪些输入。Knuth 在《计算机编程的艺术》第 4 卷的第 7.1.2 节中提到了这种类型的函数。S₃(4)
S₃(4)
可以用 7 个操作计算,如下所示:
(x && y && (a || b)) ^ ((x || y) && a && b)
Knuth 表明这是最优的,这意味着您不能使用普通运算符在少于 7 次操作中执行此操作: 和 。&&, || , ^, <,
>
但是,如果您想在用于 true 和 false 的语言中使用它,您也可以轻松地使用加法:1
0
x + y + a + b == 3
这使您的意图非常明确。
(((a AND b) OR (x AND y)) AND ((a XOR b) OR (x XOR y)))
虽然我可以证明这是一个很好的解决方案,但 Sam Hocevar 的答案很容易写出来,以后也很容易理解。在我的书中,这让它变得更好。
这是我刚刚写的一些 c# 代码,因为你启发了我:
它需要任意数量的参数,并会告诉您其中 n 个是否为真。
static bool boolTester(int n, params bool[] values)
{
int sum = 0;
for (int i = 0; i < values.Length; i++)
{
if (values[i] == true)
{
sum += 1;
}
}
if( sum == n)
{
return true;
}
return false;
}
你这样称呼它:
bool a = true;
bool b = true;
bool c = true;
bool d = false;
bool test = false;
test = boolTester(3, a, b, c, d);
因此,您现在可以随心所欲地测试 7/9 或 15/100。
评论
not a ^ not b ^ not c ^ not d
(!a&&b&&c&&d) || (a&&!b&&c&&d) || (a&&b&&!c&&d) || (a&&b&&c&&!d)