文字のヒストグラム

文字のヒストグラムテキスト内で一番使った漢字ランキングを作るのあたりを見て、似たようなものを作ってみました。

awk ではバリアントによりますが、split() 関数で文字単位に分割することができます。

これをカウントすることで度数を数えることができます。 さらに以前2 番目のフィールドでのソートで用いた柔軟なマージソートを用いて数える際の工夫をしています。

#! /usr/bin/gawk -f
# freq.awk

{
    num_char = split($0, arr_char, "");
    for (i in arr_char) {
        freq[arr_char[i]]++;
    }
}

END {
    for (i in freq) {
        tmp_freq[++j] = i " ... " freq[i];
    }

    merge_sort(tmp_freq, 1, j, 1);
    for (i = 1; i <= j; i++) {
        print tmp_freq[i];
    }
}

#---------------------------------------------------------------------
# function for recursive merge sort
function merge_sort(arr, a, b, key,   k) {
    if (a < b) {
        k = int((a + b) / 2);
        merge_sort(arr, a, k, key);
        merge_sort(arr, k + 1, b, key);
        merge(arr, a, k, b, key);
    }
}

#---------------------------------------------------------------------
# function for merge
function merge(arr, a, k, b, key,   i, j, p, c) {
    j = i = a;
    p = k + 1;
    while (a <= k && p <= b) {
        split(arr[a], arr_key1);
        split(arr[p], arr_key2);
        if (arr_key1[key] <= arr_key2[key]) {
            c[i++] = arr[a++];
        } else {
            c[i++] = arr[p++];
        }
    }
    while (a <= k) {
        c[i++] = arr[a++];
    }
    while (p <= b) {
        c[i++] = arr[p++];
    }
    while (j <= b) {
        arr[j] = c[j];
        j++;
    }
}

実際にこのスクリプト自身をカウントしてみることにします。

$ gawk -f freq.awk freq.awk
! ... 1
" ... 4
# ... 6
$ ... 1
& ... 2
( ... 20
) ... 20
+ ... 27
, ... 29
- ... 139
. ... 4
  ... 362
/ ... 4
0 ... 1
1 ... 7
2 ... 3
; ... 21
< ... 8
= ... 19
D ... 1
E ... 1
N ... 1
[ ... 19
] ... 19
_ ... 15
a ... 37
b ... 10
c ... 15
e ... 42
f ... 19
g ... 9
h ... 8
i ... 34
j ... 9
k ... 22
l ... 8
m ... 12
n ... 14
o ... 14
p ... 14
q ... 7
r ... 71
s ... 11
t ... 17
u ... 7
v ... 1
w ... 6
y ... 11
{ ... 14
} ... 14

プログラムは英語に近い単語で構成されているため、普通の英文に近いのかどうかを調べてみても面白いのではないでしょうか。

もちろん、日本語も通ります。

$ echo 'とうきょうとっきょきょかきょくきょかきょくちょう' | gawk -f freq.awk
う ... 3
か ... 2
き ... 6
く ... 2
ち ... 1
っ ... 1
と ... 2
ょ ... 7

なんとなく思いついた早口言葉で試してみましたが、感じている度数と実際の度数が食い違っていて新たな驚きがありました。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png