【发布时间】:2010-09-21 21:55:37
【问题描述】:
如何用布尔逻辑表示 X 中的 Y 为真?像以下 2 条规则必须为真(A、B、C、D、E、F)
它是乘法还是集合运算的一种形式?
最终结果是所有排列,如 AB OR AC OR AD,如果你说 3 跟随它就像 ABC、ABD、ABE 等。所以它就像 (A,B,C)^2?
谢谢!
【问题讨论】:
如何用布尔逻辑表示 X 中的 Y 为真?像以下 2 条规则必须为真(A、B、C、D、E、F)
它是乘法还是集合运算的一种形式?
最终结果是所有排列,如 AB OR AC OR AD,如果你说 3 跟随它就像 ABC、ABD、ABE 等。所以它就像 (A,B,C)^2?
谢谢!
【问题讨论】:
在布尔逻辑中(v 是 OR,谓词后面的 ' 是 NOT):
A B C'D'E'F' v
A B'C'D'E'F v
A'B C'D'E'F' v
: : : : : :
<absolute bucketload of boolean expressions>
: : : : : :
A'B'C'D'E F
使用排列,您需要编写大量子表达式。
当然,如果这是一个编程问题,您可以将布尔值转换为 0 或 1,将它们全部相加并确保结果为 2。
【讨论】:
假设 C# 或其他某种语言,其中 bool != int:
bool nOf(int n, bool[] bs)
{
foreach(bool b in bs)
{
if((n -= b ? 1 : 0) <= 0) break;
}
return n == 0;
}
【讨论】:
Python:
expressions = [A, B, C, D, E, F, G ]
numTrue = len(filter(None, expressions)
PHP:
$expressions = array(A, B, C, D, E, F, G);
$numTrue = count(array_filter($expressions));
【讨论】:
你已经明白了。要表达“n 中的 k 个”,您将需要列举所有 k 的情况。所以,如果我们有变量 A B C D E,而你想要 3 of 5,你需要
(A & B & C & ~D & ~E) |
(A & B & ~C & D & ~E) |
(A & B & ~C & ~D & E) | ...
(~A & ~B & C & D & E)
& 是“和”,|是“或”,~ 是“非”。
【讨论】:
假设“A 或更多”
你可以通过建造一棵树做得更好
2 : a&(b|c|d|e|f) | b&(c|d|e|f) | c&(d|e|f) | d&(e|f) | e*f
3 : a&(b&(c|d|e|f) | c&(d|e|f) | d&(e|f) | e*f) | b&(c&(d|e|f) | d&(e|f) | e*f) | c&(d&(e|f) | e*f) | d&e&f
或作为代码
bool AofB(int n, bool[] bs)
{
if(bs.length == 0) return false;
if(n == 0) return true;
foreach(int i, bool b; b[0..$-n])
if(b && AofB(n-1,b[i+1..$]) return true;
return false;
}
更好
bool AofB(int n, bool[] bs)
{
foreach(bool b; bs) if(b && --n == 0) return true;
return false;
}
【讨论】:
我会数一数。 但是,如果您必须仅使用布尔运算生成谓词,那么您可以将输入视为加法器系统中的位。
Basic Half-Adder
A, B : 1st 2nd bits
O, C : unit output and carry to next unit
O := A xor B;
C := A and B;
您可以在 [Wikipedia][http://en.wikipedia.org/wiki/Half_adder (Half-Adder)] 找到更多示例和链接
然后您可以将这六个变量分成 3 对,然后弄清楚如何使用这些输出来更接近答案并自己解决其余的问题。
另一种选择是使用电路来查找弹出计数(横向添加)并检查是否唯一的位与 2 匹配。 组装而不是逻辑门的著名例子是 [Hakmem 169][http://home.pipeline.com/~hbaker1/hakmem/hacks.html#item169 (popcount)]。
【讨论】:
您的意思是“恰好两个必须为真”还是“至少两个必须为真”会有所不同。
对于变量集 {A..F},Pax 和 Charlie Martin 的回答涵盖了“正好两个”的情况(两个为真,其余为假),而您问题中的表达式似乎处理“至少两个”的情况:
(A && B) || (A && C) || ... || (D && E) || (D && F) || (E && F)
是一个表达式,例如,当 A 和 B 为真且其余变量为任意值(真或假)时为真。
如果您要求的是一个类似于集合论的表达式来描述上述情况,您可以这样表达:
#{x | x <- {A, B, C, D, E, F} | x} = 2
符号以这种方式工作的地方:
#{...}
表示封闭集合的大小,以及集合本身:
{x | x <- {A, B, C, D, E, F} | x}
读取“x 的集合,其中x 是A 到F 之一,x 为真”。换句话说,给定变量集A 到F,由具有真值的变量组成的子集正好有两个元素。 (使用 <= 而不是 '=' 来表达对您问题的其他解释。)
【讨论】: