【发布时间】:2023-02-21 22:00:30
【问题描述】:
假设你有这个逻辑表达式
(A or B or C) and (D or E) and (F or G or H)
正如您在这里看到的,我们在括号内有 OR 运算符,在外面有 AND 运算符。我们可以说这个逻辑表达式是 AND(OR) 类型的。
我想将此表达式转换为 OR(AND)。
例子:
(A or B) and (C or D) = (A and C) or (A and D) or (B and C) or (B and D)
实现这个的简单方法(在 javascript 中):
class OrNode<C = string> {
/* constructor logic */
nodeType = 'OR';
children: C[];
}
class AndNode<C = string> {
/* constructor logic */
nodeType = 'AND';
children: C[];
}
function convert(expression: AndNode<OrNode>): OrNode<AndNode> {
let children: AndNode[] = [{ nodeType: 'AND', children: [] }];
expression.children.forEach((orNode) => {
let temp = children;
children = [];
orNode.children.forEach((leafNode) => {
temp.forEach((andNode) => {
children.push({
nodeType: 'AND',
children: [...andNode.children, leafNode],
});
});
});
});
return new OrNode<AndNode>({ nodeType: 'OR', children });
}
假设我们有这个表达式:
const expression = new AndNode<OrNode>({
nodeType: 'AND',
children: [
{ nodeType: 'OR', children: ['A', 'B', 'C'] },
{ nodeType: 'OR', children: ['D', 'E'] },
{ nodeType: 'OR', children: ['F', 'G', 'H'] },
]
});
那么如果我们进行转换,新的转换表达式将等于
{
nodeType: 'OR',
children: [
{ nodeType: 'AND', children: ['A', 'D', 'F'] },
{ nodeType: 'AND', children: ['A', 'D', 'G'] },
{ nodeType: 'AND', children: ['A', 'D', 'H'] },
{ nodeType: 'AND', children: ['A', 'E', 'F'] },
{ nodeType: 'AND', children: ['A', 'E', 'G'] },
{ nodeType: 'AND', children: ['A', 'E', 'H'] },
{ nodeType: 'AND', children: ['B', 'D', 'F'] },
{ nodeType: 'AND', children: ['B', 'D', 'G'] },
{ nodeType: 'AND', children: ['B', 'D', 'H'] },
{ nodeType: 'AND', children: ['B', 'E', 'F'] },
{ nodeType: 'AND', children: ['B', 'E', 'G'] },
{ nodeType: 'AND', children: ['B', 'E', 'H'] },
{ nodeType: 'AND', children: ['C', 'D', 'F'] },
{ nodeType: 'AND', children: ['C', 'D', 'G'] },
{ nodeType: 'AND', children: ['C', 'D', 'H'] },
{ nodeType: 'AND', children: ['C', 'E', 'F'] },
{ nodeType: 'AND', children: ['C', 'E', 'G'] },
{ nodeType: 'AND', children: ['C', 'E', 'H'] },
]
}
这个暴力解法的复杂度是O(M^N),M是括号内条件的最高个数,N是括号块的个数。
有没有办法使用另一种算法来降低这种复杂性?
【问题讨论】:
-
顺便说一句,它有效吗?复杂度是笛卡尔积。
-
你是说我的蛮力算法?是的,但我发布的代码只是为了展示转换算法的思想。实际代码包含更多细节(守卫、构造函数逻辑等)。这种强力算法导致我们的服务器在处理大型逻辑表达式时频繁重启。
-
您可以使用 generator 来创建笛卡尔积。也许这有点帮助。
-
让我想起
(a && b) == !(!a || !b)。转换中的 not 操作可能会有用。 -
@traktor 不幸的是使用 not 操作是不可能的。
标签: javascript algorithm logical-operators