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

#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