【问题标题】:Simplifying logical expressions简化逻辑表达式
【发布时间】:2011-11-27 09:00:03
【问题描述】:

注意:这是不是家庭作业。

我想提出正确的方法来设计正确的算法来处理这个简单的问题。

我有一个随时间变化的状态(用一个正整数表示)。我有另一个值,它是一个恒定的特定状态(可以用一个特定的正整数表示),第一个状态可能等于它。

最好这样说明:

// this is C pseudocode

int things_happen(int *value) {
  ... // value possibly gets changed!
}

const int y = VALUE_Y_CONST; 
int x = y; // to simplify things we assume x starts out equal to y

while (things_happen(&x)) {
  // I am now interested in changes to x with respect to y. 
  if (/* expression of interest */) { 
    x_is_changed(); // I want to know whenever x is no longer y
  }
  if (/* another expression of interest */) {
    x_is_back(); // and I want to know whenever x becomes equal to y again
  }
}

我该如何确定何时应该致电x_is_changed() 和x_is_back()?

在尝试编程时,我已经多次遇到这种情况。每次我想出的解决方案看起来复杂得不合理,而且经常有错误。

到目前为止,我的解决方案需要我创建第三个变量,用于在 while 循环的底部缓存 x 的值。它让我知道我的 x 从哪个值改变了。有了这些知识,我就使用了看起来太多的条件语句:

int x_cache = y;
while(things_happen(&x)) {
  if (x_cache != x) {
    if (x == y && x_cache != y)
      x_is_back();
    else if (x != y && x_cache == y)
      x_is_changed();
    x_cache = x;
  }
}

这是迄今为止我做过的最简洁的方法。代码很难遵循。我想知道的是,没有更好的算法来解决这个问题吗?我应该采取什么样的方法?我以为我可以绘制一个真值表,但我只能在真值上做到这一点。我用 3 个变量之间的等式做到了,得到了这张表:

x_cache == x | x_cache == y | x == y  ||  x_is_changed | x_is_back
                                      || 
    T                T          T     ||       F            F 
    T                T          F     ||       F            F
    T                F          T     ||       F            F
    T                F          F     ||       F            F
    F                T          T     ||       F            F
    F                T          F     ||       T            F
    F                F          T     ||       F            T
    F                F          F     ||       F            F

这似乎是我在我的逻辑课中唯一记得的东西。 我注意到由于传递性,第 2,3 和 5 行是不可能的。因此,如果我只考虑值之间的相等性检查,我肯定似乎在限制自己。

我是否应该继续提出命题变量,并寻找可以减少我的操作总数的特定组合?一定有更简单的方法吗?为任意条件提出最有效算法的一般问题显然是 NP 完全的(关于变量的数量)。

再看那张表,删除第 2、3 和 5 行,我看到条件 x_cache != x 将消除前 4 行,这很好,那么我就剩下 3 种可能性。我可以看到此时x_cache == y 等于x_is_changed,并且x == y 也等于x_is_back。

这意味着我可以从上面简化为:

...
  if (x_cache != x) {
    if (x == y)
      x_is_back();
    else if (x_cache == y)
      x_is_changed();
    x_cache = x;
  }
...

我仍然觉得这不是最佳选择。我认为没有其他关系运算符可以帮助解决这个问题。现在想想,它实际上可能是最佳的。

我直觉认为第 2、3 和 5 行是不可能的。没有这些知识,我无法将问题减少到如此少的操作。是否有一些数学/逻辑概念可以让我系统地执行这种“修剪”?

【问题讨论】:

  • 如果您最初将 x_cache 设置为 y(而不是 -1),这不会删除第一个 if 吗?
  • 我想是的。我有如果在那里,因为我不想做出假设,但我想我已经在做一个(x 开始等于 y)......我更新了问题。
  • 公平地说,当x从等于y过渡到不等于y时要调用x_is_changed,当x从不等于y过渡到不等于y时要调用x_is_back等于 y?
  • @VaughnCato 是的,这正是我的意思。我之所以没有像你刚才那样用文字来表达它的原因是,当这种方式出现时,它非常难以理解。 ---- 我也希望新的 c 标签能给我带来更多的观众。

标签: c logic conditional


【解决方案1】:

我认为最简单的形式是:

int x_cache = 1;
while(things_happen(&x)) {
  if (x_cache != (x==y)) {
    if (x == y)
      x_is_back();
    else
      x_is_changed();
    x_cache = (x==y);
  }
}

另一种选择是

for (;;) {
  while (things_happen(&x) && x==y) { }
  if (x==y) break;
  x_is_changed();
  while (things_happen(&x) && x!=y) { }
  if (x!=y) break;
  x_is_back();
}

【讨论】:

  • 这不起作用。 x = y = 2。 x 从 2 变为 0。x 从 0 变为 1。我不想在从 0 变为 1 时调用 x_is_changed,因为它最初不在 2 上。
  • 哦,我喜欢这样。我刚刚开始考虑基于 (x==y) 的预测。
  • 没有办法避免缓存 x 的值,是吗?
  • 嗯,是的。我已经添加了那个方法。
  • 你确定你的意思是break;?唔。伙计,我想你刚刚打破了我的想法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-26
相关资源
最近更新 更多