RubyとHaskellでランレングス法

ライブドアブログ(livedoor Blog)| 読みたいブログが見つかるより。
HaskellはData.Listにgroupって関数があるので、これを使うと簡単に書けます。こんな感じ。

module Main (main) where

import Data.Char (digitToInt)
import Data.List (group)

runlength :: String -> [(Int, Int)]
runlength cs = [((digitToInt . head) xs, length xs) | xs <- group cs]

main = print $ runlength "1001000" -- => [(1,1),(0,2),(1,1),(0,3)]

Haskell版の発想でRuby版を書くと、こんな感じ。これはこれで綺麗です。

module Enumerable
  def group
    inject([]) do |r, e|
      if r.empty? or r.last.last != e
        r << []
      end
      r.last << e
      r
    end
  end
end

def runlength(s)
  s.split(//).group.map {|xs| [xs.first.to_i, xs.size] }
end

p runlength('1001000') # => [[1, 1], [0, 2], [1, 1], [0, 3]]

ランレングス法、最近どっかで見たなぁと思ったら、↓でした(main関数の中で使ってます)。
参照: ICPC: Problem A Keitai Message - 趣味的にっき