Problem:
Property Distribution

タナカ氏が HW アールの果樹園を残して亡くなりました。果樹園は東西南北方向に H × W の区画に分けられ、区画ごとにリンゴ、カキ、ミカンが植えられています。タナカ氏はこんな遺言を残していました。

果樹園は区画単位でできるだけ多くの血縁者に分けること。ただし、ある区画の東西南北どれかの方向にとなりあう区画に同じ種類の果物が植えられていた場合は、区画の境界が分からないのでそれらは 1 つの大きな区画として扱うこと。

例えば次のような 3 × 10 の区画であれば ('リ'はリンゴ、'カ'はカキ、'ミ'はミカンを表す)

同じ樹がある区画の間の境界を消すと次のようになり、

結局 10 個の区画、つまり 10 人で分けられることになります。

雪が降って区画の境界が見えなくなる前に分配を終えなくてはなりません。あなたの仕事は果樹園の地図をもとに分配する区画の数を決めることです。

果樹園の地図を読み込み、分配を受けられる血縁者の人数を出力するプログラムを作成してください。

Input

複数のデータセットが与えられます。各データセットは空白で区切られた H, W (H, W ≤ 100) を含む行から始まり、続いて H × W の文字からなる H 行の文字列が与えられます。この文字列には、リンゴを表す '@'、カキを表す '#'、ミカンを表す '*'、の 3 文字しか現れません。

入力はゼロが２つの行で終わります。データセットの数は 20 を超えません。

Output

各データセットごとに、分配を受ける人数を１行に出力してください。

Sample Input

10 10
####*****@
@#@@@@#*#*
@##***@@@*
#****#*@**
##@*#@@*##
*@@@@*@@@#
***#@*@##*
*@@@*@@##@
*@*#*@##**
@****#@@#@
0 0

Output for the Sample Input

33

Solution in Haskell (judge verdict: Wrong Answer)

import Control.Applicative
import Control.Monad
import Control.Monad.RWS as RWS
import Data.Array.IArray
import Data.Array.Unboxed
import Data.Array.IO

type Garden = UArray Position Char
type CheckField = IOUArray Position Bool
type Position = (Int, Int)

main = do
    [h,w] <- map read.words<$>getLine
    unless (h == 0) $ do
        garden <- getGarden h w
        checkfield <- newArray ((0,0),(h-1,w-1)) False
        print =<< fst <$> evalRWST (sepGarden (0,0) 0) garden checkfield
        main
        

getGarden :: Int -> Int -> IO Garden
getGarden h w = do
    fs <- replicateM h getLine
    return $ listArray ((0,0), (h-1,w-1)) $ concat fs

sepGarden :: Position -> Int -> RWST Garden String CheckField IO Int
sepGarden (x,y) i = do
    ((ax,ay),(bx,by)) <- bounds<$>RWS.ask
    case (x <= bx, y <= by) of
      (False, False) -> return i
      (True, False)  -> sepGarden (x+1, 0) i
      (False, True)  -> return i
      (True , True)  -> checkField (x,y) i >>= sepGarden (x, y+1)

checkField :: Position -> Int -> RWST Garden String CheckField IO Int
checkField (x,y) i = do
    checked <- isChecked (x,y)
    if checked then return i
               else do
                   checkAround (x,y)
                   return (i+1)

isChecked :: Position -> RWST Garden String CheckField IO Bool
isChecked (x,y) = do
    cf <- get
    liftIO $ readArray cf (x,y)

checkAround (x,y) = do
    cf <- get
    fruit  <- (! (x,y))<$>RWS.ask
    liftIO $ writeArray cf (x,y) True
    checkRight (x,y) fruit
    checkUnder (x,y) fruit

checkRight, checkUnder, checkLeft :: Position -> Char -> RWST Garden String CheckField IO ()
checkRight (x,y) f = do
    g <- RWS.ask
    let ((ax,ay),(bx, by)) = bounds g
    if bx >= x && by >= y+1
       then if g ! (x,y+1) == f
               then do
                   checked <- isChecked (x, y+1)
                   if not checked
                      then do
                          cf <- get
                          liftIO $ writeArray cf (x,y+1) True
                          checkRight (x,y+1) f
                          checkUnder (x,y+1) f
                      else return ()
               else return ()
       else return ()

checkUnder(x,y) f = do
    g <- RWS.ask
    let ((ax,ay),(bx, by)) = bounds g
    if bx >= x+1 && by >= y
       then if g ! (x+1,y) == f
               then do
                   checked <- isChecked (x+1,y)
                   if not checked
                      then do
                          cf <- get
                          liftIO $ writeArray cf (x+1,y) True
                          checkRight (x+1,y) f
                          checkUnder (x+1,y) f
                          checkLeft  (x+1,y) f
                      else return ()
               else return ()
       else return ()

checkLeft (x,y) f = do
    g <- RWS.ask
    let ((ax,ay),(bx, by)) = bounds g
    if ay <= y-1
       then if g ! (x,y-1) == f
               then do
                   cf <- get
                   liftIO $ writeArray cf (x,y-1) True
                   checkUnder (x,y-1) f
                   checkLeft  (x,y-1) f
               else return ()
       else return ()