2012-06-30 8 views
0

Edit: это трудно описать то, что я пытаюсь сделать, но вот попытка (с комментариями):Haskell сравнить все элементы списка

Я строю Wordfeud решатель, так что у меня есть слово, и некоторые буквы (оба списка символов). Я применил это (How to find the frequency of characters in a string in Haskell?) к обоим спискам, чтобы получить частоту всех букв. То, что я делаю сейчас, повторяется, но список символов «слово», и проверяет, достаточно ли все символы в списке символов «буквы».

Я написал функцию Haskell, которая сравнивает два списка, применяя функцию к элементам обоих списков и сравнивая результаты.

Сравнение делается так:

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

Это только сравнивает вхождения первой буквы слова. Но ВСЕ слова следует сравнивать (и результат должен быть ИСТИННЫМ для всех из них).

Я действительно не знаю, как это осуществить. Я нашел метод «все», который позволяет мне определить предикат, это довольно хорошо. Это выглядит следующим образом:

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

(я думаю, что это правильно) Это гарантирует, что каждый элемент, который входит в список меньше или равно результат предоставленной функции.

НО: для метода «все» нужен другой параметр. Это будет параметр «источник», который определяет, что следует сравнивать с предикатом. Это было бы легко, если бы это было просто список, то я хотел бы сделать что-то вроде этого:

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

Но проблема: я не имею список результатов, как это, мне нужно, чтобы сравнить его с результатом :

(getCharOccurrence (head word) (getCharOccurrences letters)) 

я понял, что я мог бы применить эту функцию для каждого символа в слове «» списка полукокса с «картой» функцией, но я не знаю, как использовать его. Я начал вот так:

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

Но это неправильно.

Так что мне (думаю, я) нужно: примените указанную выше функцию ко всем символам списка символов «слово» и сравните ее с предикатом.

Но, может быть, я просто ошибаюсь. Я абсолютный новичок Haskell/функционального программирования. Пожалуйста, помогите мне :-)

+0

Не могли бы вы дать краткий пример того, что именно вы хотите решить? Мне сложно декодировать только имя функции и использовать ее, даже не делая того, что вы хотите. –

+0

Прошу прощения, если это не ясно, трудно описать. Но я строю речевой редактор wordfeud, поэтому у меня есть слово и несколько букв (оба списка символов). Я применил это (http://stackoverflow.com/questions/7108559/how-to-find-the-frequency-of-characters-in-a-string-in-haskell) к обоим спискам, чтобы получить частоту всех букв , То, что я делаю сейчас, повторяется, но список символов «слово», и проверяет, достаточно ли все символы в списке символов «буквы». Надеюсь, это поможет. –

+0

Я также не понимаю, чего вы хотите, не могли бы вы просто привести несколько простых примеров? – leftaroundabout

ответ

2

Итак, из чего я понимаю, у вас есть строка word со словом, которое вы хотели бы сформировать, и список символов letters, представляющий плитки в вашем распоряжении. Вы хотите проверить, может ли слово быть сформировано плиткой или нет.

Здесь я предполагаю, что функции, которые вы уже упомянутые имеют типы

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

Во-первых, вам нужно изменить hasLetters' взять параметр Char вместо использования 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. Это даст нам список Bools. Затем мы используем and, чтобы проверить, что все элементы этого списка: True.

+0

Да, вы полностью поняли мой вопрос и получили типы для getCharOccurrence и getCharOccurrences правильно :-) Настоящий тупой вопрос сейчас, но как использовать последнее выражение? Предположим, я хочу проверить, можно ли сформировать слово «счастливый» с буквами «appyhg», как это сделать? –

+2

Вероятно, вы хотите определить его как функцию, назовем его 'достаточным тилом'. Поэтому объявляйте это с помощью 'достаточных слов word letter = и $ ...', а затем используйте с 'достаточным типом 'счастливым" "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 
Смежные вопросы