测试3个中的4个是否为真的逻辑

165

如果且仅当4个布尔值中有3个为真时,我想返回True

我得到的最接近的结果是(x ^ y) ^ (a ^ b):

我该怎么办?


10
嗯,我能想到的唯一方法是使用计数,好问题! :) - I am Cavic
10
你的想法并不错,但你需要注意否定:当只有一个否定值为真时,not a ^ not b ^ not c ^ not d 才为真。这意味着,在原来的值中,恰好有一个是假的。 - Ingo
23
你在这些细节背后的实际问题是什么? - Wolf
5
当只有一个是假的并且其中三个是假的时,如果@Ingo不是a、不是b、不是c、也不是d,则返回true。 - NameSpace
10
明显的非计数解决方案是 (!a&&b&&c&&d) || (a&&!b&&c&&d) || (a&&b&&!c&&d) || (a&&b&&c&&!d) - Jason C
显示剩余9条评论
27个回答

5
如果且仅如果四个布尔值中有三个是true,我希望返回true。 给定四个布尔值a、b、x、y,这个任务可以转化为以下的C语句:
return (a+b+x+y) == 3;

1
好陷阱。这假设 true 等于 1。但在所有语言/情况下都不是如此(无恶意)。http://blogs.msdn.com/b/oldnewthing/archive/2004/12/22/329884.aspx - JensG
@JensG 你是对的:我会明确表达这个假设。谢谢 :) - Wolf

4
((a^b)^(x^y))&((a|b)&(x|y))

这是您想要的。基本上,我使用了您的代码,并添加了检查是否确实有3个为真而不是3个为假的功能。


4

没有涉及递归的编程问题?不可思议!

虽然有足够的“确切三个中的四个为真”的答案,但是这里提供了一个通用(Java)版本的“确切m个中的n个为真”(否则递归并不值得),仅仅因为你可以:

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);

这个函数将返回true(因为8个值中有5个是true,符合预期)。不太满意"trues"和"falses"这两个词,但现在想不到更好的名称了...请注意,当找到太多truefalse时,递归会停止。


@FélixSaparelli:不确定“truth”是否适用于此处...这听起来像你只需要一个true。也许可以使用类似containsNumberOfTrueValues()的东西。顺便说一下:Smalltalk的命名方式更加适合这种情况:doesArray: someBooleans startingAt: anIndex containNumberOfTrueValues: anExpectedNumber foundSofar: aNumberFoundSoFar。对于一些Java开发人员来说可能太长了,但Smalltalkers从不害怕适当的命名;-) - Amos M. Carpenter
那大多数是幽默的。而 containsTruth 的意思是“包含一些未公开的真相”,字面上来说,所以我认为这很好。 - Félix Saparelli

3

鉴于易读性是一个重要问题,您可以使用描述性的函数调用(包装任何建议的实现)。 如果这个计算需要在多个地方完成,则函数调用是实现重用和清晰表达您正在执行的操作的最佳方式。

bool exactly_three_true_from(bool cond1, bool cond2, bool cond3, bool cond4)
{
    //...
}

3
在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";

2
(((a AND b) OR (x AND y)) AND ((a XOR b) OR (x XOR y)))

虽然我可以展示这是一个好的解决方案,但Sam Hocevar的答案既易于编写,又易于以后理解。在我的观点中,这使它更好。


1

我刚刚写了一些C#代码,因为你激发了我的灵感:

它可以接受任意数量的参数,并告诉您其中有多少个是真的。

    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;                
    }

and you call it like so:

        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。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接