2-gram

30分プログラム、その60。Haskellで2-gram。

2-gramは自然言語の統計的性質のひとつ。特定の2文字がどれくらいの頻度で、連続するかを調べる。
例えば、

*Main> mapM_ (putStrLn.show) $ makeGram "The licenses for most software are"
(('a','r'),2)
(('e',' '),2)
(('r','e'),2)
((' ','a'),1)
((' ','f'),1)
((' ','l'),1)
((' ','m'),1)
((' ','s'),1)
(('T','h'),1)
(('c','e'),1)
(('e','n'),1)
(('e','s'),1)
(('f','o'),1)
(('f','t'),1)
(('h','e'),1)
(('i','c'),1)
(('l','i'),1)
(('m','o'),1)
(('n','s'),1)
(('o','f'),1)
(('o','r'),1)
(('o','s'),1)
(('r',' '),1)
(('s',' '),1)
(('s','e'),1)
(('s','o'),1)
(('s','t'),1)
(('t',' '),1)
(('t','w'),1)
(('w','a'),1)

のようになる。

import System
import Data.List

makePair :: String->[(Char,Char)]
makePair str = sort $ zip str (tail str)

count :: [(Char,Char)]->[((Char,Char),Int)]
count pairList = map (\xs@(x:_)->(x,length xs)) $ group pairList

filterSymbol :: String->String
filterSymbol = filter (\x-> x /= '.' && x /= '\n')

makeGram :: String ->[((Char,Char),Int)]
makeGram s = sortBy (\(_,n) (_,m)-> m `compare` n) $ count $ makePair $ filterSymbol s

main = do path:_ <- getArgs
          content <- readFile path
          mapM_ (putStrLn.show) $ take 20 $ makeGram content
  • これを2-gramじゃなくて、n-gramに対応させれないかなぁ
  • 1:02余った