본문 바로가기

Haskell

리스트의 홀수번째 원소만 골라내기

리스트의 자리로 필터링하는 문제이다.

원문 : https://www.hackerrank.com/challenges/fp-filter-positions-in-a-list/problem

접근

인덱스를 0부터 시작한다고 할 때, 홀수 인덱스에 있는 원소를 뺀 나머지 리스트를 구하는 함수를 작성해야 한다. 우선 원래 리스트에서 출발한다고 하면  head를 취해야 한다. 그리고 앞에서 두 개를 버린 리스트에 대해 재귀적으로 적용한다.

f [] = []
f lst = (head . tail $ lst):(f . drop 2 $ lst)

간단한 문제인데, 이런 유형은 zip을 이용하는 것도 좋다. (파이썬에서는 보다 functional하기 풀기 위해서 zip을 잘 활용하면서 정작 함수형 언어에서 zip을 안 쓸 이유가...)

f = map snd . filter (odd . fst ) . zip [0..]

이 함수는 다음과 같이 동작한다.

  1. 먼저 0, 1, 2 ...로 이어지는 무한 리스트를 준비하고
  2. lst의 각 원소에 대해 zipping한다. (0, a0), (1, a1).... 과 같이 튜플로 인덱스값과 원소값이 묶인다.
  3. 그 중에서 fst 값이 홀수인 것을 버린다. : filter (odd . fst)
  4. 필터링된 결과에 대해서 튜플의 뒤의 값만 취하도록 맵핑한다.

최종 코드는 다음과 같다.

f = map snd . filter (odd . fst) . zip [0..]
main = getContents >>=
  mapM_ print . f . (map read) . lines