トライグラム反復子

『プログラミングErlang』15章本文では

  1. 単語ごとに分割する
  2. 単語の両端に空白を付加する
  3. 3文字ずつ取り出す

という3段階の手順になっている。これを1段階に、すなわち先頭から順番に3文字ずつ抜き出していくアルゴリズムに変更してみた。

-define(NL, $\r,$\n).
 
% 先頭に改行を付加して処理開始
my_scan_trigrams([?NL|_]=L, F, A) -> each_trigram(L, F, A);
my_scan_trigrams(L, F, A) -> each_trigram([?NL|L], F, A).
 
each_trigram(L, F, A) ->
    case L of
	%% 終端の処理
	[?NL]      -> A;
	[?NL, X]   -> F([$\s, X, $\s], A);
	[X,   Y]   -> F([X,   Y, $\s], A);
	%% 単語の先頭
	[?NL, X, ?NL|T] -> each_trigram([?NL |T], F, F([$\s, X, $\s], A));
	[?NL, X, Y  |T] -> each_trigram([X, Y|T], F, F([$\s, X, Y  ], A));
	%% 単語の途中
	[X,   Y, ?NL|T] -> each_trigram([?NL |T], F, F([X,   Y, $\s], A));
	[X,   Y, Z  |T] -> each_trigram([Y, Z|T], F, F([X,   Y, Z  ], A))
    end.

微々たる差ではあるが、少しだけ速い。

Counting by my_scan_trigrams - No of trigrams=3357707 time/trigram=0.46476926068891655
Counting by scan_word_list - No of trigrams=3357707 time/trigram=0.5411714006016606

Leave a Reply