연속된 자연수의 범위 찾기

출처: 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."

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

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

리스트에서 최소값은 1이고 최대값은 500입니다.

댓글 보기 옵션

원하시는 댓글 전시 방법을 선택한 다음 "설정 저장"을 누르셔서 적용하십시오.

하스켈 버전 1

range [] = "."
range (x:xs) = notation (map fst a) ++ (if length b > 0 then ", " else "") ++ range (map fst b) 
    where 
        (a,b) = break (uncurry (/=)) $ zip (x:xs) [x..]
        notation [y] = show y
        notation (y:ys) = show y ++ "-" ++ show (last ys)

하스켈 버전 2

import Data.Maybe

range = range' Nothing where
    range' Nothing [] = "."
    range' Nothing [x] = show x ++ "."
    range' (Just x) [y] = show x ++ "-" ++ show y ++ "."
    range' x (y:z:zs) = if z-y == 1
        then range' (Just $ maybe y id x) (z:zs)
        else (maybe "" ((++ "-").show) x) ++ show y ++ ", " ++ range' Nothing (z:zs)

maybe 함수는 maybe a f x 꼴로 사용해서 x가 Nothing이면 a, Just n이면 f n을 돌려준다.

얼랑

얼랑은 처음으로 짜본거라 조금 기네요
일단 돌아가는 것에 의의를 뒀습니다^^

%% wookay 2007-02-12
-module(home_on_the_range).
-export([group/4]).
-export([make_group/1]).
-export([make_range/1]).
-export([split_by_space/1]).
-export([comma_join/1]).
-export([get/1]).

group(_, Result, _, [])->
  Result;
group(Pred, Result, Mid, [X,Y|L])->
  case Pred(X, Y) of
    true -> group(Pred, Result, Mid++[X], [Y|L]);
    false -> group(Pred, Result++[Mid++[X]], [], [Y|L])
  end;
group(Pred, P, A, L)->
  group(Pred, P++[A++L], [], []).

make_group(L)->
  group(
    fun(X,Y)-> Y-X==1
    end,
    [],[],L).

split_by_space(S)->
  lists:map(
    fun(I)-> list_to_integer(I)
    end,
    string:tokens(S, " ")).

make_range([H,_,T])->
  [H, "-", T];
make_range([H,T])->
  [H, "-", T];
make_range(L)->
  L.

comma_join([H|L])->
  lists:concat(
    lists:map(
      fun(X)->lists:concat([X, ", "])
      end,
      lists:reverse(L)) ++ [H] ++ ["."]).

get(S)->
  comma_join(
    lists:reverse(
      lists:map(
        fun(X)->lists:concat(make_range(X))
        end,
        make_group(split_by_space(S))))).

실행화면~~~~~

$ erl
Erlang (BEAM) emulator version 5.5 [source] [async-threads:0]

Eshell V5.5  (abort with ^G)
1> c(home_on_the_range).           
{ok,home_on_the_range}
2> home_on_the_range:get("1 2 3").
"1-3."
3> home_on_the_range:get("1 2 3 5 7 8").
"1-3, 5, 7-8."
4> home_on_the_range:get("1 3 4 5 7").  
"1, 3-5, 7."

[code][/code] 태그를

[code][/code] 태그를 코드 앞뒤에 쳐주면 들여쓰기가 보존됩니다. ^^