Problem:
0 から 9 までの数字だけで構成された文字列が与えられたとき,その文字列から次の規則に従って新しい文字列を作る操作を考える.与えられた文字列を左端から1文字ずつ順に読んで行き,同じ数字 a が r 個続いていた場合,個数 r と数字a を空白で区切らずにこの順で書き出す.与えられた文字列の右端まで読み,最後の書き出しが終わったところまでを途中何回書き出しがあったとしても全部まとめて操作1回とカウントする.2回目以降の操作は前回の操作により書き出された文字列を与えられた文字列として同様の操作を実施する.例えば “122244” という文字列が与えられた場合には左端から順に1個の1, 3個の2,2個の4なのでこの操作1回で得られる文字列は “113224” であり,“44444444444” (11 個の4)の場合には得られる文字列は “114” となる.

100 文字以下の与えられた文字列に上の操作を n 回実施した文字列を出力するプログラムを作成せよ.ただし, n ≤ 20 とする.

入力データ は 2 行からなり,1 行目に操作回数 n, 2 行目に最初の文字列が書かれている.

入力例

5

11

　

出力例

13112221

入力

入力は複数のデータセットからなる．n が 0 のとき入力が終了する．データセットの数は 5 を超えない．

出力

データセットごとに、指定された回数の操作を施した文字列 を１行に出力する．

入力例

5
11
5
11
0

出力例

13112221
13112221

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in Haskell (judge verdict: Accepted)

{-#LANGUAGE BangPatterns#-}
module Main where

import Data.Functor
import Control.Monad

main::IO ()
main=do
  n<-read <$> getLine::IO Int
  when (n/=0) $
    do
      str <- getLine
      let out=times (toStr . split) str n
      putStrLn out
      main

toStr::[(Int,Char)]->String
toStr list=concatMap (\(n,c)->show n ++ [c])list

split::Eq a=>[a]->[(Int,a)]
split list=reverse $ split' 0 [] list

split'::Eq a=>Int->[(Int,a)]->[a]->[(Int,a)]
split' _ result []=result
split' !n result (x:y:ys)
  |x==y =split' (n+1) result (y:ys)
  |otherwise =split' 0 ((n+1,x):result) (y:ys)
split' !n result [x]=split' 0 ((n+1,x):result) []

times::(a->a)->a->Int->a
times _ x 0=x
times f x n=times f (f x) (n-1)