(연습문제) 행렬의 대각선의 차

대각선의 차이 구하기

N*N 크기의 행렬이 주어졌을 때, 이 행렬의 대각선상에 위치하는 요소들의 합끼리의 차를 구하는 프로그램을 작성하는 문제이다.

https://www.hackerrank.com/challenges/diagonal-difference


i 번째 행의 (i-1)번, 및 (N-i)번 인덱스의 값을 각각 뺀 다음 (i=1,2,3… 인덱스는 0, 1, 2 순) 이들을 합산하고 절대값을 취하면 된다.

module Main where
import Control.Monad
import Control.Applicative
-- i 와 i번 행을 받아 이를 처리한다.
processLine :: Int -> [Int] -> Int
process i xs = let a = head $ drop (i-1) xs
                   b = head . drop (i-1) . reverse $ xs
                in a - b
main = do
  n <- readLn :: IO Int
  ts <- sum <$> forM [1..n] (\x -> processLine x . map read . words <$> getLine)
  print . abs $ ts

여기서도 <$> 연산자를 유용하게 썼고, forM 함수도 썼다.

forM, <$>

forM 함수는 (Monad m, Traversable t) => t a -> (a -> m b) -> m (t b)의 타입을 가진 함수로 리스트나 트리와 같은 순회 가능한 목록과 모나딕 값을 리턴하는 함수를 이용해서 리스트의 각 원소를 처리하고, 이를 모나딕 리스트나 모나딕 트리로 리턴하는 함수이다.
여기서 두 번째 인자로 쓰인 함수를 살펴보면

(\x -> processLine x . map read . words <$> getLine)

이게 나오는데 <$>는 좌변의 함수(a -> b)를 우변의 t a에 적용하여 t b 타입을 만들어주는 (여기서 t 는 applicative) 연산자이다. 즉 좌변의 함수를 Applicative 문맥으로 감싸고 이를 다시 Applicative 문맥에 들어있는 값에 적용하게 해준다. (인자가 2개 이상이면 <*> 연산자를 이용해서 언커리할 수 있다.)
여기서 왼쪽의 함수는 String -> Int가 되고, 우변의 getLineIO String이므로 이 함수 전체의 타입은 Int -> IO Int가 된다.
결국 forM 함수를 이용해서 처리한 결과는 IO [Int]가 되고 이는 (<$>) sum에 의해서 IO Int로 귀결된다.

원본

기본으로 주어지는 템플릿은 다음과 같은 식으로 표현하고 있다. (processLine은 제외) IO 와 관련하여 입력받은 값을 처리하는데 있어서 Applicative의 활용이 얼마나 중요한지를 보여주는 좋은 예라 하겠다.

import Control.Applicative
import Control.Monad
import System.IO
main :: IO ()
main = do
  n_temp <- getLine
  let n = read n_temp :: Int     -- 이 두 라인은 n <- readLn :: IO Int 로 대체할 수 있다.
  a_temp <- getMultipleLines n
  let a = map ( map ( read :: String -> Int ) . words ) a_temp
getMultipleLines :: Int -> IO [String]
getMultipleLines n
  | n <= 0 = return []
  | otherwise = do
      x <- getLine
      xs <- getMultipleLines (n-1)
      let ret = (x:xs)
      return ret

Read more

워드프레스에서 고스트로 이전

워드프레스에서 고스트로 이전

이 글을 쓰면서도 믿기 힘든 사실인데, 블로그라는 걸 처음 시작한지가 20년이 되었습니다. 이글루스에서 처음 시작했다가, SK컴즈가 인수한다고 발표함과 동시에 워드프레스로 플랫폼을 옮겼죠. 워드프레스오 옮긴 이후에는 호스팅 환경을 이리 저리 옮기긴 했지만 거의 18년 가까이 워드프레스를 사용해온 것 같습니다. 그 동안 워드프레스는 블로깅 툴에서 명실상부한 범용CMS로 발전했습니다. 사실 웬만한 홈페이지들은 이제

By sooop
띄어쓰기에 대한 생각

띄어쓰기에 대한 생각

업무 메일을 쓸 때 가장 많이 쓰는 말 중에 하나가 메일 말미에 ‘업무에 참고 부탁 드립니다.‘인데요, 어느 날부터 아웃룩에서 이 ‘부탁 드립니다’가 틀렸다고 맞춤법 지적을 하기 시작했습니다. 맞는 말은 ‘부탁드립니다’라고 붙여 쓰는 거라고. 사실 아래아한글 시절부터 이전의 MS워드까지, 워드프로세서들의 한국어 맞춤법 검사 실력은 거의 있으나 마나 한

By sooop

구글 포토에서 아이클라우드로 탈출한 후기

한 때 구글 포토가 백업 용량을 무제한으로 제공해 주겠다고해서, 구글 포토를 사용해서 사진을 백업해왔습니다. 물론 이 이야기의 결말은 저나 이 글을 읽고 있는 여러분이나 모두 알고 있습니다. 사실 AI에게 학습 시킬 이미지 데이터를 모으기 위한 것일 뿐이라거나 하는 이야기는 그 당시에도 있었습니다만, 에이 그래도 구글인데 용량은 넉넉하게 주겠지…하는 순진한

By sooop

Julia의 함수 사용팁

연산자의 함수적 표기 Julia의 연산자는 기본적으로 함수이며, 함수 호출 표기와 같은 방식으로 호출하는 것이 가능합니다. 또한 그 자체로 함수이기 때문에 filter(), map() 과 같이 함수를 인자로 받는 함수에도 연산자를 그대로 적용하는 것이 가능합니다. 특히 + 연산자는 sum() 함수와 같이 여러 인자를 받아 인자들의 합을 구할 수 있습니다. 2 + 3 # = 5 +(2,

By sooop