2012-10-08 13 views
2

如果我有4个布尔条件,并且我想说如果这些条件中至少有3个是真的,那么做这个可以在Haskell中实现吗?haskell - 指定条件是真的

或者我必须经历每个排列? (即1.True,2.True,3.True,4.False和1.False,2.True,3.True,4.True等)

谢谢!

回答

4

每个排列?当然不是......你可以计算出真实的条件数量。

+1

是的,当你达到3你可以停止计数。 –

1
requireAtLeast :: Int -> [Bool] -> Bool 
requireAtLeast n = (>= n) . length . filter id 

如果你喜欢极端的贴题或毫无意义的形式,这分别是他们:

requireAtLeast threshold predicates = length (filter (\predicate -> predicate) predicates) >= threshold 

requireAtLeast = (. length . filter id) . (<=) 
+2

喜欢使用'filter id'。 '(过滤(\谓词 - >谓词)谓语)'让我轻笑。 – AndrewC

2
atLeast3 :: Bool -> Bool -> Bool -> Bool -> Bool 
atLeast3 b1 b2 b3 b4 = sum (map fromEnum [b1, b2, b3, b4]) >= 3 
+2

在这种情况下可能不是问题,但如果列表'[b1,b2 ... bn]'非常大,那么比较不需要通过整个列表的懒惰方式? –

+1

@MagnusKronqvist,是的,看到bisserlis,8月或solrize的答案。 – huon

2

这不是最美丽的方式,但你可能会发现

atLeast :: Int -> [Bool] -> Bool 
atLeast n bools = length (filter (==True) bools) >= n 

最容易理解。 filter只保留列表中符合您的规则的事物。在这种情况下,规则是答案必须是True。接下来,length计算剩下多少。

(规则是一个函数a -> Bool其中a是您的列表中元素的类型)。

+1

或者'filter id bools'。 – augustss

+1

是的,就像我说的,不是最美的方式,但也许容易理解。我已经为此提出了Ptharien的火焰;请考虑这样做。 – AndrewC

+1

这实际上是我发现写'== True'的唯一地方,所以我不会和你争论。 – augustss

4

该解决方案与迄今为止提供的其他解决方案不同之处在于其短路(即,在发现nBool s后停止)。所以它可以在一些无限列表上运行(只有那些最终评估为True的列表),并且不一定会强制评估列表中的每个元素(由于懒惰)。

atLeast :: Int -> [Bool] -> Bool 
atLeast 0 _   = True 
atLeast _ []   = False 
atLeast n (True:bs) = atLeast (n - 1) bs 
atLeast n (False:bs) = atLeast n bs 
4

如果您希望在找到N个数字时停止检查列表,您可以使用懒惰自然数进行计数。

import Data.List 
import Data.Number.Natural 

atLeast :: Int -> [Bool] -> Bool 
atLeast n = (>= (fromIntegral n :: Natural)) . genericLength . filter id 
5
atleast :: Int -> [Bool] -> Bool 
atleast n bools = length tn == n 
    where tn = take n . filter id $ bools 

应该懒洋洋地工作,除非我错过了什么。