or1ko's diary

日々を書きます

09

言語処理100本ノック 2015

09. Typoglycemia
スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ.ただし,長さが4以下の単語は並び替えないこととする.適当な英語の文(例えば"I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind .")を与え,その実行結果を確認せよ.

09.hs

import System.Random
import Data.List

main = do
  gen <- getStdGen
  print $ unwords $ map typoglycemia $ zip (words s) (randoms gen :: [Int])
    where 
      s = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."

typoglycemia (s, hint) 
    | length s <= 4 = s
    | otherwise     = [head s] ++ shuffle hint (init $ tail s) ++ [last s]

-- hint は文字列をシャフルする際に使う数値
shuffle hint s = tmp !! (mod hint (length tmp))
              where
                 tmp = permutations s
> runghc 09.hs
"I cun'oldt bevilee that I could autlclay udanrestnd what I was randeig : the paomehnnel peowr of the haumn mind ."
> runghc 09.hs
"I could'nt bieelve that I colud aclltuay ueandsntrd what I was reandig : the paemnhonel poewr of the hamun mind ."
> runghc 09.hs
"I c'dlunot beileve that I cluod alucltay unednrstad what I was rdianeg : the panhonemel poewr of the hmuan mind ."

shuffleが難しかった。
typoglycemia関数をString -> IO String型にするバージョンも作成してみた。

import Control.Monad
import System.Random
import Data.List

main = do
  typoglycemias <- mapM typoglycemia $ words s
  putStrLn $ unwords typoglycemias
   where 
     s = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."

typoglycemia s 
    | length s <= 4 = return s
    | otherwise     = do
       body <- shuffle (init $ tail s) 
       return ([head s] ++ body ++ [last s])

shuffle s = 
  do 
    g <- getStdGen
    return $ tmp !! (mod (fst $ next g) (length tmp))
      where
        tmp = permutations s