2012-05-21 4 views
2

Мне нужно написать код, который даст True, если функция удовлетворяет большинству элементов списка и false в нем не удовлетворяет. например: moreThan odd [1,2,3] есть True, но moreThan odd [1,2,3,4] есть False. Вот мой код:Функция, которая удовлетворяет большинству элементов в haskell

moreThan funkt xs 
    = let 
     control funkt n (x : xs) 
     = control (if .?. then n + 1 else n) xs 
     contol funkt _ 
     = False 
    in 
    control funtk 0 xs 

кто-нибудь может сказать, как я могу контролировать, что и то, что я должен написать в .?. Спасибо!

+0

'Morethan = ((\ (lTrue, lFalse) -> длина lTrue> длина lFalse).). раздел "будет несколько более идиоматичным. – leftaroundabout

+0

Ну, было бы более идиоматично, если бы вы просто использовали 'let' вместо того, чтобы бросать беспорядочную бессмысленную лямбду. –

+0

вы можете показать, как? –

ответ

1

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

moreThan :: (a -> Bool) -> [a] -> Bool 
moreThan f xs = length ts > length fs where 
    ts = filter id bools 
    fs = filter not bools 
    bools = map f xs 
+0

Это выглядит хорошо ... но это не работает. =) –

+0

Я исправил его (надеюсь!) –

3

Функция, которую вы написали, вернет False для всех аргументов, так как вы всегда возвращаете False, когда список заканчивается.

Функция, которую вы пишете, должна отслеживать две переменные: количество обработанных элементов и количество элементов, для которых ваш предикат является истинным. Поскольку этот код, вероятно, является домашним заданием, я даю вам конструкцию, которую вы можете использовать для записи функции. Заполните свой собственный код в -- ??? местах.

moreThan :: (a -> Bool) -> [a] -> Bool 
moreThan pred = go 0 0 where 
    -- procd: number of elements processed 
    -- holds: number of elements for which pred holds 
    go procd holds (x:xs) = go procd' holds' xs where 
    procd' = -- ??? 
    holds' = -- ??? 
    go procd holds []  = -- ??? 

Если вам нужно больше советов, не стесняйтесь оставлять комментарии.


Более идиоматических способ написать эту функцию использует складку:

moreThan pred = finalize . foldr go (0,0) where 
    -- process one element of the input, produce another tuple 
    go (procd,holds) x = -- ??? 
    -- produce a boolean value from the result-tuple 
    finalize (procd,holds) = -- ??? 
+2

'foldr' - плохой выбор для этой проблемы.И вам нужно только отслеживать одну вещь, разницу в подсчетах. '(> 0). foldl '(\ n x -> если p x, тогда n + 1 else n-1) 0' - это то, что я нашел бы идиоматическим. –

+0

@ Daniel Fischer, на каком пути складывается uniodeomatic? Идея с единственным счетчиком хороша. – fuz

+3

Я не говорю, что 'foldr' является унииоматическим (особенно не в общем), это просто неправильная идиома для данной проблемы. Функция обновления является строгой в обоих аргументах, результат не зависит от порядка, в котором обрабатываются элементы списка, ясный случай для 'foldl''. –

2

Знай свои библиотеки!

import Data.List(partition) 
import Data.Function(on) 

moreThan f = (uncurry $ on (>) length) . partition f 

Если вы не можете использовать раздел, написать его самостоятельно:

part f xs = (filter f xs, filter (not.f) xs) 

Или пойти числовой путем:

moreThan f xs = 2*s > length xs where s = sum $ map (fromEnum.f) xs 
0

Я надеюсь, что это является эффективным (только траверсы список один раз), но все же достаточно ясно.

majority :: (a -> Bool) -> [a] -> Bool 
majority pred = g . sum . map f 
    where f x | pred x = 1 
      | otherwise = -1 
     g y = 0 < y 
1
majority :: (a -> Bool) -> [a] -> Bool 
majority p = (0 <) . sum . map (\x -> if pred x then 1 else -1) 

То есть карта (если пред х, то 1 еще -1) над элементами списка, затем суммирует элементы списка и выглядит, если результат> 0.

Смежные вопросы