#haskell #recursion #modulo
Вопрос:
Реализуйте
oddPairs :: [Int] -> [Int] -> [(Int, Int)]
функцию, которая возвращает список пар, но только в том случае, если суммы соответствующих элементов в списках параметров нечетны.Например:
oddPairs [1,2,3] [2,2,2] == [(1,2),(3,2)]
oddPairs [1,3,5] [2,4,6] == zip [1,3,5] [2,4,6]
oddPairs [1,2,3] [1,2,3] == []
До сих пор я пытался
oddPairs (x:xs) (y:ys) | (x y) `mod` 2 == 0 = []
| (x y) `mod` 2 /= 0 = [(x, y)] oddPairs (xs) (ys)
И в первом примере он возвращает только [(1,2)]
, во втором он возвращает правильные значения , но с Non-exhaustive patterns
ошибкой.
Комментарии:
1. Кстати, Прелюдия включает
even :: Integral a => a -> Bool
в себя , реализованную с использованиемmod
и(==)
так, как вы сделали здесь.
Ответ №1:
В случае, если два элемента четны, вы должны не просто возвращать пустой список, а продолжать рекурсию до тех пор, пока хотя бы один из списков не будет исчерпан, так что:
oddPairs :: Integral a => [a] -> [a] -> [(a, a)]
oddPairs [] _ = []
oddPairs _ [] = []
oddPairs (x:xs) (y:ys)
-- keep searching for new items ↓
| (x y) `mod` 2 == 0 = oddPairs xs ys
| otherwise = (x, y) : oddPairs xs ys
Комментарии:
1. ух ты, какой ты быстрый 😀
Ответ №2:
Другой способ взглянуть на проблему заключается в том, что вам нужны только пары с нечетной суммой. Это небольшая разница в акцентах, которая может привести к следующему.
Используйте zip
функцию для объединения каждого списка в пары. Затем используйте filter
, чтобы найти те, у которых нечетная сумма.
oddPairs :: Integral a => [a] -> [a] -> [(a, a)]
oddPairs f s = filter oddPair (zip f s)
where oddPair (l, r) = not $ even (l r)
Ответ №3:
Довольно прямолинейно с пониманием списка:
oddPairs :: [Int] -> [Int] -> [(Int, Int)]
oddPairs ms ns = [(m, n) | (m, n) <- zip ms ns, odd (m n)]
Действительно:
> oddPairs [1, 2, 3] [2, 2, 2] == [(1, 2),(3, 2)]
True
> oddPairs [1, 3, 5] [2, 4, 6] == zip [1, 3, 5] [2, 4, 6]
True
> oddPairs [1, 2, 3] [1, 2, 3] == []
True