2012-06-30 23 views
0

編輯:很難描述我正在試圖做的,但這裏的一個嘗試(從評論):哈斯克爾比較所有列表項

我建立一個wordfeud求解器,所以我有一個詞,一些字母(都是char列表)。我將這個(How to find the frequency of characters in a string in Haskell?)應用於這兩個列表以獲取所有字母的頻率。我現在正在做的是遍歷'word'char列表,​​並檢查'​​letters'char列表中是否有足夠的字符。

我寫了一個Haskell函數,它通過對兩個列表的項目應用一個函數並比較結果來比較兩個列表。

比較像這樣做:

hasLetters' :: [Char] -> [Char] -> Bool 
hasLetters' word letters = (getCharOccurrence (head word) (getCharOccurrences word)) <= (getCharOccurrence (head word) (getCharOccurrences letters)) 

這只是比較單詞的第一個字母的出現。但是所有的單詞都應該進行比較(並且所有單詞的結果都應爲TRUE)。

我真的不知道如何做到這一點。我找到了可以讓我定義一個謂詞的'all'方法,這非常好。它看起來像這樣:

all (<= (getCharOccurrence (head word) (getCharOccurrences letters))) 

(我認爲這是正確的) 它確保每一個進入列表項小於或等於所提供的功能的結果。

但是:'all'方法需要另一個參數。這將是定義應該與謂詞進行比較的「源」參數。這將是很容易當這只是一個清單的話,我會做這樣的事情:

all (<= (getCharOccurrence (head word) (getCharOccurrences letters))) [0..10] 

但問題是:我沒有這樣的結果列表,我需要它比較的結果:

(getCharOccurrence (head word) (getCharOccurrences letters)) 

我想,我可以用「地圖」功能的「字」字符表此功能適用於每一個角色,但我不知道如何使用它。我開始是這樣的:

map (getCharOccurrence (head word) (getCharOccurrences word)) word 

但這是錯誤的。

所以我(想我)需要:將上述函數應用於'單詞'字符列表的所有字符,並將其與謂詞進行比較。

但也許我只是認爲錯誤的方式。我是絕對的Haskell /函數式編程新手。請幫我:-)

+0

可不可以給的是什麼,你要解決一個簡明的例子嗎?我發現很難從一個函數名解碼,甚至沒有做你想做的事情。 –

+0

如果不清楚,我很抱歉,很難形容。但是我正在構建一個wordfeud求解器,所以我有一個單詞和一些字母(都是char列表)。我將這個(http://stackoverflow.com/questions/7108559/how-to-find-the-frequency-of-characters-in-a-string-in-haskell)應用到這兩個列表中以獲得所有字母的頻率。我現在正在做的是遍歷'word'char列表,​​並檢查'​​letters'char列表中是否有足夠的字符。希望有所幫助。 –

+0

我也不明白你想要什麼,難道你只是給一些簡單的例子嗎? – leftaroundabout

回答

2

因此,據我所知,你有一個字符串word與你想要形成的字和字符letters代表瓷磚在您的處置列表。你想檢查這個單詞是否可以由瓷磚組成。

在這裏,我假設你提到的職能類型

getCharOccurrence :: Char -> [(Char, Integer)] -> Integer 
getCharOccurrences :: [Char] -> [(Char, Integer)] 

首先,您需要修改hasLetters'採取而是採用head word一個字符參數:

hasLetters' :: Char -> [Char] -> [Char] -> Bool 
hasLetters' c word letters = (getCharOccurrence c (getCharOccurrences word)) <= (getCharOccurrence c (getCharOccurrences letters)) 

然後你可以結合上面的主功能(我們稱之爲sufficientTiles)與

sufficientTiles :: [Char] -> [Char] -> Bool 
sufficientTiles word letters = and $ map (\c -> hasLetters' c word letters) word 

我們在這裏完成的是將hasLetter'函數映射到word的每個字符。這會給我們一個布爾名單。然後我們使用and來檢查該列表中的所有元素是否爲True

+0

是的,你完全理解我的問題,並獲得getCharOccurrence和getCharOccurrences正確的類型:-)現在一個真正的愚蠢的問題,但我怎麼用你的最後一個表達式?假設我想要檢查「happy」這個單詞是否可以用字母「appyhg」組成,我該怎麼做? –

+2

你可能想把它定義爲一個函數,我們稱它爲'sufficientTiles'。所以用'fullyTiles word letters = and $ ...'聲明它,然後使用'sufficientTiles「開心」「appyhg」'。 – niklon

+1

非常感謝你!像魅力一樣工作,現在解決難題:) –

1

所以我想我明白你想比較兩個列表。如果第二個列表的每個元素的數量至少與第一個列表的數量相同,則測試通過。因此,您至少需要一個平等的約束,但順序會有所幫助。

解決方法有很多,這是第一位想到的一個是那種每個列表,羣組和計數的獨特元素,並確保所有的結果都是<=

someCompare a b = let op :: String -> [(Char,Int)] 
         op = map (head &&& length) . group . sort 
        in [c <= k | (x,c) <- op a, k <- maybeToList (lookup x (op b))] 

或者您可以使用地圖上的計數器並結合兩張地圖:

someCompare2 a b = 
     let op = foldl' (\m c -> Map.insertWith (+) c 1 m) Map.empty 
     in all (<= 0) . Map.elems $ Map.unionWith (+) (op a) (Map.map negate $ op b) 

等等等等

3

使用multiset包:

import Data.MultiSet 
compareAll as bs = fromList as `isSubsetOf` fromList bs 

或:

import Data.Function 
import Data.MultiSet 
compareAll = isSubsetOf `on` fromList