2012-06-12 2 views
1

Мне нужна программа, которая проверяет, находится ли разница между всеми парами элементов в интервале от -2 до 2 (>= -2 && < 2). Если это так, верните True, иначе верните False. Например, [1,2,3] является True, но [1,3,4] является False. Я использую функцию all. Что не так с моей статьей if?haskell all function

allfunc (x : xs) 
    = if all (...) xs 
     then allfunc xs 
     else [x] ++ allfunc xs 
allfunc _ 
    = [] 

Или я делаю что-то совершенно не так?

+0

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

+0

Уместен ли порядок? какой результат для [-2,0]? – is7s

ответ

3

Для этого, вероятно, проще использовать перечни или обозначения.

pairsOf lst = do 
    x <- lst 
    y <- lst 
    return (x, y) 

pairsOf возвращает список пар чисел на входе lst. Например, pairsOf [1,2,3] приводит к [(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)].

Теперь вы можете определить разницу между парой в однострочнике \(x, y) -> x - y и карту, которая по списку:

differences lst = map (\(x, y) -> x - y) (pairsOf lst) 

Теперь вы просто должны убедиться, что каждый элемент в differences lst между -2 и 2.

Конечно, это всего лишь один из возможных способов сделать это. Есть много других способов.

+1

Возможно, можно упростить и сделать что-то вроде: 'diffs lst = [(x - y) | x <-lst, y <-lst] ', затем перетащите список результатов различий в' checkDiffS = all (\ x-> x <2 && x> -2) ' – user268396

-1

В принципе, да, вы делаете что-то неправильно. all предназначен для использования предиката и списка значений для проверки. Таким образом, он вернет True тогда и только тогда, когда все значения верны при применении к данной предикатной функции. I.e .:

allValuesEven = all even 
allValuesOdd = all odd 
+0

Ваше первое предложение неверно:' [] 'не соответствует pattern 'x: xs'. –

0

Ну, проблема в спецификации не очень ясна.

Вы говорите:

diffence между всеми элементами в интервале от -2 до 2 (> = -2 & & < 2)

Но также:

Например, [1,2,3] имеет значение True, но [1,3,4] является ложным

Как это верно для [1,2,3]?

Предполагая, что вы имеете в виду -2 <= diff <= 2, то я хотел бы использовать это:

allfunc :: (Ord a, Num a) => [a] -> Bool 
allfunc theList = all (\x -> (x >= -2) && (x<2)) [x-y | x <- theList, y <- theList ] 

allfunc [1,2,3] -- => True 
allfunc [1,3,4] -- => False 
1

Почему бы не просто ...

allfunc xs = (maximum xs - minimum xs) <= 2 

Или, если вы действительно хотите, чтобы исследовать каждую пару, вы можете использовать монады:

import Control.Monad 
allfunc xs = all ((<=2).abs) $ liftM2 (-) xs xs 

liftA2 из Control.Applicative будет делать так же.

2

Наивный способ сделать то, что вы описываете:

allfunc xs = all (<=2) [abs(a-b) | a <- xs, b <- xs ] 

Однако более эффективным методом было бы сравнить минимум и максимум списка:

fastfunc [] = true 
fastfunc xs = maximum xs - minimum xs <= 2