単語の出現数を数える
C++
// // word_count.cpp // #include#include #include
$ g++ word_count.cpp $ ./a.out Alice : 2 Bob : 1 $
C++ で書いてみたけれど,C++ の流儀が分からないのでこれでいいのかよく分からない.メモリリークもしているかもしれない.
気持ち悪い点は,
Ruby
# # word_count.rb # # Array に単語を追加 ary = ['Alice', 'Bob', 'Alice'] # デフォルト値が 0 (Integer) の Hash を生成 h = Hash.new(0) # Array の単語を順番に見ていく ary.each do |str| # 単語の出現回数を増加 h[str] += 1 end # Hash の中身を表示 p h # Hash の単語と出現回数を順番に見ていく h.each do |key, value| # key が単語,value が出現回数 print key, " : ", value, "\n" end
$ ruby word_count.rb {"Alice"=>2, "Bob"=>1} Alice : 2 Bob : 1 $
Ruby で書いてみた.圧倒的に簡潔になる.
Haskell
{- word_count.hs -} -- List ライブラリのインポート import List -- 単語のリスト word_list :: [String] word_list = ["Alice", "Bob", "Alice"] {- sort … リストをソートする ["Alice", "Bob", "Alice"] -> ["Alice", "Alice", "Bob"] group … リスト中で隣接する同じ要素をリストにまとめる ["Alice", "Alice", "Bob"] -> [["Alice", "Alice"], ["Bob"]] head … リストの最初の要素を取得 ["Alice", "Alice"] -> "Alice" ["Bob"] -> "Bob" length … リストの長さを取得 ["Alice", "Alice"] -> 2 ["Bob"] -> 1 \xs -> 〜 … xs を引数とする無名関数 \xs -> (head xs, length xs) … 引数 xs に head, length を適用した組 (head xs, length xs) を返す ["Alice", "Alice"] -> ("Alice", 2) ["Bob"] -> ("Bob", 1) map f xs … リスト xs の各要素に関数 f を適用したもののリストを返す [x1, x2, ..., xn] -> [(f x1), (f x2), ..., (f xn)] [["Alice", "Alice"], ["Bob"]] -> [("Alice", 2), ("Bob", 1)] -} word_count :: [String] -> [(String, Int)] word_count = (map (\xs -> (head xs, length xs))) . group . sort main = print (word_count word_list)
$ ghc --make word_count.hs Chasing modules from: word_count.hs Compiling Main ( word_count.hs, word_count.o ) Linking ... $ ./a.out [("Alice", 2), ("Bob", 1)] $
ムシャクシャしてやった.言語なら何でもよかった.今は反省している.
Haskell は簡潔に書けるが,知らない人には全く読めないだろうし,知っている人はもっとうまく書くかもしれない.