ログイン/ログアウトの記録の解析

ログイン/ログアウト記録の解析を awk でやってみました。 Perl 版が Perl 勉強ノート (1) に掲載されていますが、基本的に同じアルゴリズムを使っています。 ここでは awk らしく、Pattern-Action 構造を保ちつつ作ってあります。

#! /usr/bin/gawk -f
# http://d.hatena.ne.jp/omkg/20080701
# http://www.logos.ic.i.u-tokyo.ac.jp/icpc2007/jp/domestic/problems/B_ja.html

NF == 2 {
    delete login;
    delete logout;
}

NF == 4 && $4 == 1 {
    flag[$3]++;
    if (flag[$3] == 1) {
        n_login[$3]++;
        login[$3, n_login[$3]] = $1;
    }
}

NF == 4 && $4 == 0 {
    flag[$3]--;
    if (flag[$3] == 0) {
        logout[$3, n_login[$3]] = $1;
    }
}

NF == 3 {
    elapse = 0;
    for (i = 1; i <= n_login[$3]; i++) {
        if (login[$3, i] <= $2 && logout[$3, i] >= $1) {
            if (login[$3, i] <= $1) {
                login_time = $1;
            } else {
                login_time = login[$3, i];
            }
            if (logout[$3, i] <= $2) {
                logout_time = logout[$3, i];
            } else {
                logout_time = $2;
            }
            elapse += logout_time - login_time;
        }
    }
    print elapse;
}

ログイン/ログアウト記録の解析に載っているサンプルで試すと以下のようになります。

$ gawk -f login_logout.awk login_logout.dat
55
70
30
0
0
50
10
50
0

ACM/ICPC Asia Regional Contest 2007. Tokyo に他の秀逸な問題がいくつかありますので、機会があれば解いていきたいと思います。