2012-10-08 51 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 

應該懶洋洋地工作,除非我錯過了什麼。