数字を桁ごとに分解する方法

最近「すごいHaskell 楽しく学ぼう!」という本を買い、ちまちま読み進めているところ。

第 6 章に「すみません。各桁の数の合計が 40 になる最初の自然数は何でしょうか?」というお題があって、これの解説中に map digitToInt . show という式があって、感動に打ち震えた(大げさ)。

map digitToInt . show

digitToInt は Data.Char モジュールに定義されている、文字を数値に変換してくれる関数。これと show を使うっていうアイデアにしびれたわけ。

自分だったら、数字を 10 で割った数と、その余りをみてリスト化するという方法しか考えつかなかっただろうから。こんなかんじに。:

digitize n = aux n [] where
 aux n ds | 0 == d    = ds'
          | otherwise = aux d ds'
  where (d,m) = divMod n 10
        ds'   = m:ds

10 で割った数がなくなれば、その余りが最上位桁になる。そうでなければ、今までの桁のリストの先頭に余りを追加しつつ、割った数に対して同じ計算を繰り返すというもの。

これに対し map digitToInt . show は、 C 言語でたとえて言うなら printf("%d", n) して数字を文字列(つまり文字のリスト)に変換して、その要素を数字に変換し直すというやり方。

いやあ、見事だわ。