본문 바로가기

하스켈

최대 공약수를 찾는법 조금 어려운 초급 연습문제. 어떤 임의의 정수 N을 소인수 분해한 결과가 다음과 같다고 하자.$$ p_1^{a_1} \times p_2^{a_2} \times p_3^{a_3} \times p_2^{a_4} ... $$이를 [p1, a1, p2, a2, p3, a3 ... ]의 리스트로 표현하기로 약속한다. 리스트의 개수 N을 입력받고 이후 N 줄에 대해서 각각 공백으로 띄워진 숫자리스트를 입력받는다. 리스트는 인수와 지수의 짝이어야 하므로 짝수개의 인자가 들어오는 것을 보장한다.자 이렇게 구성된 N 개의 정수들의 최대 공약수를 구해서 입력과 동일한 형태의 리스트로 출력하는 프로그램을 작성해보자. 접근 가장 손쉬운 방법은 Integer 타입으로 만들어서 gcd 함수를 적용하는 것이다. 이는 만들어지는 각.. 더보기
원소 필터링 문제 연습문제 - 이번에는 약간 쉽지 않다. N개의 정수로 이루어진 리스트 A를 받는다. 그리고 정수 K를 받는다. 리스트 A에서 K번 이상 등장한 정수들을 필터링하여, 최초에 등장했던 순서대로 출력하는 것이다. 예를 들어 A = [4, 5, 2, 5, 4, 3, 1, 3, 4] 이고, K=2라면 이 중에서 두 번 이상 등장한 원소는 순서대로 4, 5, 3 이므로 출력은 4 5 3 이다. 만약 K번 이상 등장한 원소가 없다면 -1을 출력해야 한다. 출처 : https://www.hackerrank.com/challenges/filter-elements/problem입력 첫줄에서는 시행횟수를 받는다 각 시행의 첫입력은 리스트의 길이와 K 값을 공백으로 구분하여 받음 각 시행의 둘째 입력은 리스트의 내용 접근 원.. 더보기
몇 가지 간단한 연습문제 기타 몇 가지 하스켈 초급 문제들을 해결해보고, 입출력을 처리하는 과정을 살펴보자. 리스트를 뒤집기 일련의 리스트를 입력된 순서를 거꾸로하여 출력한다. 단, reverse 함수를 쓰지 말 것. (https://www.hackerrank.com/challenges/fp-reverse-a-list/problem) 이 문제는 reverse 함수를 구현해보라는 의미이다. 예를 들어 1 2 3 의 리스트가 있다고 할 때, 이를 (2 3을 뒤집은 결과) + [1] 로 만드는 처리를 재귀적으로 수행하면 역순의 리스트를 만들 수 있다. 따라서 다음과 같은 함수를 정의할 수 있다. rev :: [a] -> [a] rev [] = [] rev (x:xs) = (rev xs) ++ [x] 실제로 이 구현은 '매우 정직한' .. 더보기
파스칼의 삼각형 이번 연습문제는 파스칼의 삼각형을 출력하는 문제이다. 출처 : https://www.hackerrank.com/challenges/pascals-triangle/problem파스칼의 삼각형을 출력한다. 숫자의 정렬은 무시하고 입력받는 정수 n행까지의 숫자 리스트를 공백으로 띄워서 출력한다. 접근 출력은 다음과 같은 모양이다. 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 .... 이 중에 4행과 5행을 보자. 1 3 3 1 + 1 3 3 1 ------------- 1 4 6 4 1 특정한 행을 어슷하게 배치해서 각 위치의 숫자를 더하면 그 다음 행이 된다. 그렇다면 [1, 3, 3, 1, 0]과 [0, 1, 3, 3, 1] 두 리스트에 대해서 같은 위치에 있는 원소끼리 더해서 하나의 리스트를 만.. 더보기
데이터를 입력받는 방법 - 1 이번 시간에는 기본 입출력 액션에 대해서 살펴보자. 컴퓨터 프로그램이 하는 일을 일반화해보면 주어진 자료를 처리하여 그 결과를 내놓는 것이다. 여기서 "자료가 주어진다"는 것은 소스코드에 정적으로 포함된 데이터만 처리하는 것이 아니라 (물론 이렇게 동작하는 프로그램도 많다. 초보들이 연습용으로 작성하는 코드들 대부분이 여기에 속한다.) 외부로 부터 데이터를 입력받을 수 있다는 것이다. 외부로부터의 데이터 입력이란 키보드로부터 문자열을 입력 받거나, 텍스트 파일을 읽어들이거나, 혹은 외부 네트워크에 요청하여 데이터를 받아올 수도 있다는 의미이다. 대응해야 하는 케이스가 엄청 많은 것 같지만, 이로부터 유발되는 혼란을 피하기 위해서 우리의 선조(?) 아키텍트들은 프로그램이 외부와 소통하는 창구를 표준화하였다.. 더보기
피보나치 수열의 일반항 피보나치 수열의 일반항 구하기 출처 : https://www.hackerrank.com/challenges/functional-programming-warmups-in-recursion---fibonacci-numbers/problem피보나치 수열은 다음과 같이 이루어집니다.n = 1 : 0 n = 2 : 1 n = 3... : f(n) = f(n-2) + f(n-1) 이 때 n을 입력받아 피보나치 수열의 일반항을 출력하는 프로그램을 작성하세요. 접근 곧이 곧대로 코드를 짤 수도 있을 것이다. fib :: Int -> Int fib n = case n of 1 -> 0 2 -> 1 _ -> (fib (n-2)) + (fib (n-1)) main :: IO () main = do n Int -> a fib.. 더보기
숫자값 타입간의 형 변환 하스켈의 숫자 타입들 1 : Integral Integral 타입 클래스는 소수점이 없는 숫자를 말하며 여기에는 Integer와 Int 타입이 속한다. Integer : 임의 정밀도를 가지는, 자리수의 제한을 받지 않는 숫자값 Int : 고정크기 정수로 64비트 정수 이러한 정수형으로부터의 변형은 fromIntegral 함수를 쓰며, 이는 임의의 Intergral 타입속의 값을 Num 타입속의 값으로 전환한다. (여기에는 Int, Integer, Rational, Double이 들어간다.) fromIntegral :: (Num b, Integral a) => a -> b 예를 들어 Int 타입의 n이라는 값이 있고, 그 제곱근을 구하고자 한다면 sqrt n을 쓰고 싶어진다. 하지만 sqrt 함수는 Flo.. 더보기
연습문제 - 문자열 압축하기 문자열 압축하기 연속되는 문자열에 대해서 같은 문자가 2개 이상 연속하는 경우 aaa -> a3와 같이 변경하여 문자열을 압축한다. 출처 : https://www.hackerrank.com/challenges/string-compression/problem 이를 위해서는 aabbccdd -> aa,bb,cc,dd로 분해하는 함수가 필요한데, group 함수가 여기에 딱이다. (Data.List에 포함되어 있다.) encode :: String -> [String] encode = concapMap (\x -> [(head x):"", p x]) . group where p a = if (> 1) . length a then show . length x else "" 혹은 다음과 같이 1을 뺄 수 있다. .. 더보기