or1ko's diary

日々を書きます

ブロックソートをHaskellで書いてみた(2回目)

ku-ma-meさんの参考に少し直した。

import Data.List (sort, tails, inits, elemIndex, sortBy)
import Data.Maybe (fromJust)

main :: IO ()
main = print . decode . encode $ "cocoa"

decode :: Ord a => ([a], Int) -> [a]
decode (s,i) = map (\n -> s !! n) ns
  where
    suffix = map snd $ sortBy comp $ zip s [0..]
    comp (x,_) (y,_) = compare x y
    ns = take (length s) $ iterate f $ f $ pred i
    f n = suffix !! n

encode :: Ord a => [a] -> ([a], Int)
encode s = (map last tmp, succ i)
  where
    tmp = sort $ init $ zipWith (++) (tails s) (inits s)
    i = fromJust $ elemIndex s tmp

以下、感想。

  • elemIndexの存在を忘れてました。
  • succ, pred, fromJustは知りませんでした。勉強になります。
  • ku-ma-meさんのdecodeの発想は思い浮かびませんでした...というか、wikipediaに記載されている複号の方法だー\(^o^)/