오늘 뉴스그룹에서 본 멋진 표현 하나...

haskell 뉴스 그룹에 어떤 사람이 주어진 리스트를 임의로 섞은 리스트를 만드는 방법에 대해 질문(http://groups.google.com/group/comp.lang.haskell/browse_thread/thread/35522560876ee1a5)이 올라왔는데 그에 대한 풀이 중 멋진 소스가 하나 있어서 소개합니다.

[code]
permutation :: [a] -> IO [a]
permutation xs = selektion (length xs) xs

selektion :: Int -> [a] -> IO [a]
selektion 0 xs = return []
selektion k xs = do
i <- randomRIO (0, length xs - 1)
let (here, y : there) = splitAt i xs
ys <- selektion (pred k) $ here ++ there

구스타포

Gustavo는 수를 셀 줄 알지만, 숫자를 1,2,3,4 밖에 쓸 줄 모른다. 게다가 4는 1과 같다고 생각한다. Gustavo는 큰 수를 나타낼 때 자신이 알고 있는 숫자를 더해서 나타낸다. 예를 들어 6은 1+3+2라고 쓴다.

Gustavo와 같은 방식으로 수를 표현한다면 한 수를 몇 가지 방법으로 쓸 수 있는 지 알아내는 프로그램을 만들어보자. 예를 들어 2는 1+1, 1+4, 4+1, 4+4, 2 다섯 가지 방법으로 나타낼 수 있다.
우선 간단히 4와 순서에 대해서는 생각하지 말고 수를 어떻게 1,2,3의 합으로 만들지만 생각해보자. 예를 들어 4는 3+1, 2+2, 2+1+1, 1+1+1+1 네 가지 방법으로 만들 수 있다.

Four Box

문제

Quote:
4개의 직사각형이 평면에 있는데 밑변이 모두 가로축에 평행하다. 이 직사각형들이 차지하는 면적을 구하는 프로그램을 작성하시오. 이 네 개의 직사각형들은 서로 떨어져 있을 수도 있고 겹쳐 있을 수도 있다. 또한 하나가 다른 하나를 포함할 수도 있으며, 변이나 꼭지점이 겹쳐질 수도 있다. 실행 파일의 이름은 RECT.EXE로 하시오.

입력형식

하나의 직사각형은 왼쪽 아래의 꼭지점과 오른쪽 위의 꼭지점의 좌표로 주어진다. 입력은 네 줄이며, 각 줄은 네 개의 정수로 하나의 직사각형을 나타낸다. 첫 번째와 두 번째의 정수는 사각형의 왼쪽 아래 꼭지점의 x좌표, y좌표이고, 세 번째와 네 번째의 정수는 사각형의 오른쪽 위 꼭지점의 x좌표, y좌표이다. 단, x좌표와 y좌표는 1 이상이고 1000 이하인 정수이다.

졸리 점퍼(jolly jumper)

연속으로 주어진 숫자들이 n개 있으면 이 숫자들의 간격이 1부터 n-1까지 종류별로 모두 있는 경우를 졸리 점퍼(Jolly jumper)라고 부른다. 예를 들어 1 4 2 3이라는 4개의 숫자가 있을 때 1과 4의 간격은 3, 4와 2의 간격은 2, 2와 3의 간격은 1로 1에서 3까지 모두 있다.

숫자 리스트를 입력 받아 졸리 점퍼인지 판단하는 프로그램을 작성하라.

셀프 넘버(self number)

넥슨 입사문제중 에서

어떤 자연수 n이 있을 때, d(n)을 n의 각 자릿수 숫자들과 n 자신을 더한 숫자라고 정의하자. 예를 들어 d(91) = 9 + 1 + 91 = 101이 때, n을 d(n)의 제네레이터(generator)라고 한다. 위의 예에서 91은 101의 제네레이터이다. 어떤 숫자들은 하나 이상의 제네레이터를 가지고 있는데, 101의 제네레이터는 91 뿐 아니라 100도 있다. 그런데 반대로, 제네레이터가 없는 숫자들도 있으며, 이런 숫자를 인도의 수학자 Kaprekar가 셀프 넘버(self-number)라 이름 붙였다. 예를 들어 1,3,5,7,9,20,31 은 셀프 넘버 들이다.

자리 올림 세기

대안언어축제 위키에서
입력값(또는 stdin)으로 두 개의 숫자를 받아서 두 숫자의 합에서 발생하는 “자리올림”(carry)의 갯수를 출력(stdout)한다. “0 0″이 입력되면 중단한다.

ex) input : 999  1
    output : 3 carry operations.

ex) input : 123  456
    output : no carry operation.

체스판 위의 개미

개미 한 마리가 체스판 위를 기어다닌다. 개미는 체스판의 왼쪽 아래 구석에서 시작한다. 처음에는 위로 1칸 올라간 다음, 왼쪽으로 1칸 아래로 1칸 간다. 그리고 오른쪽으로 1칸 간 다음 위로 2칸, 왼쪽으로 2칸 간다. 다시 위로 1칸 간 다음 오른쪽으로 3칸 아래로 3칸을 간다. 개미가 움직이는 순서를 그림으로 나타내면 아래와 같다.


숫자 그리기

#과 공백으로 숫자를 그린다. 다른 문자를 이용해도 좋다. 단, 숫자의 크기를 자유롭게 지정할 수 있어야 한다.

예시는 다음과 같다.

연속된 자연수의 범위 찾기

출처: CodeGolf

오름차순으로 정렬된 자연수의 리스트에서 연속으로 이어진 부분들은 범위를 나타내는 표시로 바꾸는 문제입니다. 예시는 다음과 같습니다.

  1. "1 2 3" => "1-3."
  2. "1 2 3 5 7 8" => "1-3, 5, 7-8."
  3. "1 3 4 5 7" => "1, 3-5, 7."

입력은 정수리스트나 문자열로 받습니다. 원래 리스트에서 숫자들은 스페이스 한 칸으로 구분되어 있습니다.

출력은 문자열입니다. 범위는 줄표(-)를 이용하여 "시작-끝"과 같은 형식으로 표현합니다. 쉼표(,)는 범위의 끝, 마침표(.)는 리스트의 끝을 나타냅니다.

로마 숫자를 아라비아 숫자로 바꾸기

출처: CodeGolf(via gimmesilver's blog)

로마 숫자를 아라비아 숫자로 바꾸는 문제입니다. 로마 숫자는 알파벳마다 다음과 같이 특정한 수가 할당되어 있습니다.

  1. I = 1
  2. V = 5
  3. X = 10
  4. L = 50
  5. C = 100
  6. D = 500
  7. M = 1000

수를 쓸 때는 큰 수부터 작은 수 순서대로 쓰면 됩니다. 단 다음과 같이 각 자릿수에서 1에 해당하는 수가 5나 10에 해당하는 수 앞에 나오면 1을 뺍니다.

내용묶음
10111213
98714
23615