サンプルプログラム


■ 10000以下の素数を求める

 "ふるい" のアルゴリズムを使って10000以下の素数をすべて表示します。

    function printRight(n, column)      //  数値を右詰で表示する関数
    {
        var str = string(n);
        var len = str.length();
        while( ++len <= column )
            console.write(" ");
        console.write(n);
    }

    function main()
    {
        var N = 10000;
        var flag;
        for(var i=2;i<=N;++i)
            flag[i] = 0;

        var j, cnt = 0;
        for(i=2;i<=N;++i) {
            if( flag[i] == 0 ) {
                for(j=i+i;j<=N;j+=i)
                    flag[j] = 1;
            }
        }
        for(i=2;i<=N;++i) {
            if( flag[i] == 0 ) {
                printRight(i, 8);
                if( ++cnt % 10 == 0 )
                    console.write("\n");
            }
        }
        console.write("\n");
    }

■ ドメイン数の取得

 メーリングリストの review で取得したメールアドレス一覧から、 各階層ドメインに含まれるユーザ数を求めるプログラムです。
 メールアドレスは "@" を含み、半角空白以降はコメントとします。

    //----------------------------------------------------------------------------
    //
    //      メースアドレスの一覧からドメイン階層の出現数を計算するプログラム
    //
    //----------------------------------------------------------------------------

    var g_stat;         //  統計をとるためのオブジェクト

    //
    //      メールアドレス文字列からドメイン部分を抜き出す
    //
    function getDomain(str)
    {
        var at = str.find("@");
        if( at < 0 )
            return "";
        str = str.mid(at + 1);
        var sp = str.find(" ");
        if( sp >= 0 )
            str = str.left(sp);
        return str;
    }

    //
    //      ドメイン文字列を分割する
    //
    function split(domain)
    {
        var list;
        var count = 0;
        var ix;
        while( (ix = domain.find(".")) >= 0 ) {
            list[count++] = domain.left(ix);
            domain = domain.mid(ix+1);
        }
        list[count] = domain;
        return list;
    }

    //
    //      集計を行う
    //
    function addStat(list)
    {
        var count = list.getCount();
        var prop;
        for(var i = 0; i < count; ++i) {
            prop = list[count - 1 - i] + prop;
            if( g_stat.isMember(prop) )
                g_stat[prop] += 1;
            else
                g_stat[prop] = 1;
            prop = "." + prop;
        }
    }

    //
    //      集計結果を表示する(ソートは行っていない)
    //
    function printStat()
    {
        var prop;
        for(prop in g_stat)
            console.writeln(format("%6d: ", g_stat[prop]) + prop);
    }

    function main()
    {
        var doc = openDocument("d:\\temp\\review.lst");
        var lineCount = doc.getLineCount();
        var total = 0;
        for(var line=0; line<lineCount; ++line) {
            var lineString = doc.getLineString(line);
            var domain = getDomain(lineString);
            if( domain != "" ) {
                total += 1;
                var list = split(domain);
                addStat(list);
            }
        }
        printStat();
        console.writeln("total = " + total);
    }

 実行結果:

   262: jp
   109: or.jp
     2: jomon.or.jp
     2: niftyserve.or.jp
   134: co.jp
     2: mei.co.jp
            === 中略 ===
     1: hongo.fukuda.co.jp
     1: canon.co.jp
     1: cptd.canon.co.jp
total = 270

■ リナンバ

 選択された行の最初の10進数をリナンバするスクリプトです。
 下記プログラムを renum.vvs というファイル名で保存し、リナンバを行いたいドキュメントを開き、 リナンバする範囲を選択後、vi のコロンコマンドで :run renum.vvs と入力します。

    //----------------------------------------------------------------------------
    //      選択範囲行の最初の10進数をリナンバするスクリプト
    //----------------------------------------------------------------------------

    function getNumber(str, ix)
    {
        var val = 0;
        var ch;
        while( (ch = str.charCode(ix++)) >= 0x30 && ch <= 0x39 )
            val = val * 10 + ch - 0x30;
        return val;
    }

    function main()
    {
        var column = 0;
        var sel;
        if( !thisView.isSelected() )
            statusBar.write("範囲を選択してください。");
        else if( isBoxSelectMode() ) {
            sel = thisView.getSelectedRange();
            column = sel.column1;
        } else {
            var num;
            var init = 0;
            sel = thisView.getSelectedRange();
            if( sel.offset2 == 0 )
                sel.line2 -= 1;
        }
        thisView.clearSelected();
        for(var line = sel.line1; line <= sel.line2; ++line) {
            var lineStr = thisView.getLineString(line);
            var offset = 0;
            if( column != 0 ) {
                offset = thisView.columnToOffset(line, column);
                if( offset > 0 )
                    lineStr = lineStr.mid(offset);
            }
            var ix = lineStr.findOneOf("0123456789");
            if( ix >= 0 )
                if( !init ) {
                    init = 1;
                    num = getNumber(lineStr, ix);
                } else {
                    var len = 1;
                    for(var i=ix+1;
                            lineStr.charAt(i) >= 0x30 && lineStr.charAt(i) <= 0x39;
                            ++i)
                        len += 1;
                    column = thisView.offsetToColumn(line, offset + ix);
                    var cmd = format(":%d\n%d|%ds%d", line+1, column+1, len, ++num);
                    thisView.viCommand(cmd);
                }
        }
    }

■ 左辺と右辺の交換

 コーディングで式の左辺と右辺を交換したい場合は意外とよくあります。 次のスクリプトはカーソル位置の左辺と右辺を交換します。

   foo.bar = a;

      ↓

   a = foo.bar;

    //----------------------------------------------------------------------------
    //      [ \t]* left_value " = " right_valur; ...
    //                      ↓
    //      [ \t]* right_value " = " left_valur; ...
    //----------------------------------------------------------------------------

    function doSwap(lineStr)
    {
        var ixAsn = lineStr.find(" = ");
        var ixScln = lineStr.find(";");
        if( ixAsn < 0 || ixScln < 0 || ixAsn > ixScln )
            return lineStr;
        var ix = 0;
        while( lineStr.charAt(ix) == " " || lineStr.charAt(ix) == "\t" )
            ix += 1;
        return lineStr.left(ix) + lineStr.substring(ixAsn + 3, ixScln) + " = " +
                        lineStr.substring(ix, ixAsn) + lineStr.mid(ixScln);
    }

    function main()
    {
        thisView.clearSelected();
        var pos = thisView.getCursorPos();
        var lineStr = thisView.getLineString(pos.line);
        var newLine = doSwap(lineStr);
        if( newLine != lineStr ) {
            thisView.viCommand("0D");
            thisView.insertText(newLine);
        }
    }