すのものの「いろいろ」(その144)

ソートの過程を「色+数字」で表示する

さまざまなソートのアルゴリズムを、 プログラムを書きながら学んでいるとしよう。 その場合、とりあえずは、 100 未満の自然数に値をもつ乱数で初期化された配列をソートする、 といった程度のプログラムを書けば十分であろう。

その際、配列全体を

 03 14 15 92 65 35 89 79 32 38 46 26 43
のように印字する関数を書いておき、 これを適当なところで呼び出すようにすると、 debug の役に立つし、 途中経過がわかるのでアルゴリズムの理解の手助けにもなる。

配列の一つの要素につき 3 文字分のスペースを要するから、 コンソールの横幅が 120 カラムとすると、配列の大きさは 40 程度。 これで十分なのだが、

表現することにすれば、配列の大きさを三倍、 すなわち 120 程度にまで大きくできる。 それには画面制御エスケープシーケンスで色をつければよいわけだが、 あれには使える色が十種類は用意されていないようだ。 赤、黄、緑、青、マゼンタの五色とその反転を使えば十種類になり、 一応これで使えるものができた。 しかし、 なんとなくくやしいのと、 (いわゆる)ホームページで人に見せたいのとで、 HTML 版を作ってみた。

まずは色を選ぼう。同じ色だが、 左は「#」を、右は色を表わす番号を表示してみた。

    
     
       

       

       
     
    
          ff0000
     ff00aa    ffaa00
ff00ff              ffff00

aa00ff              aaff00

0000ff              00ff00
     00aaff    00ffaa
          00ffff

この十二色から、 10時と11時の位置にある二色を除いた十色を用いて表示するようにしてみた。 クイックソートと組み合わせたプログラム例を下に示す。 配列の大きさは 100 とし、 それを 0 から 99 までの整数が一度ずつ現れるように初期化した。

/******************************************************************************
    0 ... 99 をシャッフルして得られた配列 a[ ] をクイックソートする。
    表示は、十位は色で、一位は数字で。黒地の html ファイルを吐く。
******************************************************************************/
#include <stdio.h>
#include <stdlib.h> /* srand() */
#include <time.h>   /* time() */

#define N 100

void init(void);
void print(void);
void quicksort(int i, int j);
void swap(int i, int j);

int a[N];

int main() {
    printf("<html>\n");         /* html の最初の部分。略式 :-) */
    printf("<body bgcolor=\"black\">\n");
    printf("<p>\n");
    printf("<pre>\n");

    init();
    print();
    quicksort(0, N-1);

    printf("</pre>\n");         /* html の最後の部分。略式 :-) */
    printf("</p>\n");
    printf("</body>\n");
    printf("</html>\n");

    return 0;
}


void init(void) {
    int i;

    for (i = 0; i < N; i++) {
        a[i] = i;
    }
    srand((unsigned)time(NULL));    /* 現在時刻で乱数の種を初期化 */
    for (i = N-1; i > 0; i--) {     /* シャッフルする */
        swap(i, rand() % (i+1));
    }
    return;
}


/* 配列 a[0] ... a[N-1] を印字。十位は色で、一位は数字で表示される */
void print(void) {
    int i;

    for (i = 0; i < N; i++) {
        if (i > 0 && a[i] / 10 == a[i-1] / 10) {    /* 一つ手前と同色のとき */
            printf("%d", a[i] % 10);
        } else {                                    /* そうでないとき */
            printf("<font color=\"");
            switch(a[i] / 10) {
                case 0: printf("#ff0000"); break;   /* 赤 */
                case 1: printf("#ff8800"); break;
                case 2: printf("#ffff00"); break;   /* 黄 */
                case 3: printf("#88ff00"); break;
                case 4: printf("#00ff00"); break;   /* 緑 */
                case 5: printf("#00ff88"); break;
                case 6: printf("#00ffff"); break;   /* シアン */
                case 7: printf("#0088ff"); break;
                case 8: printf("#0000ff"); break;   /* 青 */
                case 9: printf("#8800ff"); break;
                default: ;
            }
            printf("\">%d", a[i] % 10);
        }
        if (i == N-1 || a[i] / 10 != a[i+1] / 10) { /* 次が違う色のとき */
            printf("</font>");
        }
    }
    printf("\n");
}


void swap(int i, int j) {
    int tmp;

    tmp = a[i]; a[i] = a[j]; a[j] = tmp;
}


/* ↓あまりしっかりチェックしていないのでミスがあるかも */
void quicksort(int left, int right) {
    int i, j;
    int pivot;

    if (left >= right) {
        return;
    }

    pivot = a[left];
    i = left;
    j = right;
    while (i < j) {
        while (i <= right && a[i] <= pivot) {
            i++;
        }
        while (j >= left && a[j] >= pivot) {
            j--;
        }
        if (i < j) {
            swap(i, j); i++; j--;
        }
    }
    /* ここへきたときは i == j または i == j + 1 になっている */
    if (i != j || a[i] > pivot) {
        i--;
    }
    swap(left, i);

    print();
    quicksort(left, i-1);
    quicksort(i+1, right);
}

上のプログラムでは、 再帰呼び出しの直前に印字関数を呼んでいる。 全く同じ行が二回続けて出力されることがあるが、 それは前々項に書いた「間に合わせ版 uniq」で取り除けばよい。 また、pivot としては左端の元を選んでいる。

出力例を次に示す。

5187401274681271323444986859306904303908753072658196102447166987108510222382769397437246165358905595
2190401571681641323444989357326322005788956705658196172440163709108313402980969867437272465328975585
1890751023462841323644989357126327500481956705658196172440163709108313402980969867437272465328975585
6890751023412841323644989357126327500481956705658196172440163709108313402980969867437272465328975585
1430256079812841323644989357126327500481956705658196172440163709108313402980969867437272465328975585
0134256079812841323644989357126327500481956705658196172440163709108313402980969867437272465328975585
0123456079812841323644989357126327500481956705658196172440163709108313402980969867437272465328975585
0123456879012841323644989357126327500481956705658196172440163709108313402980969867437272465328975585
0123456789012841323644989357126327500481956705658196172440163709108313402980969867437272465328975585
0123456789012168323644905757826323908411954705658196172440163709108313402980969867437272465328975585
0123456789012468573091465237826323908411954705658196172440163709108313402980969867437272465328975585
0123456789012348576091465237826323908411954705658196172440163709108313402980969867437272465328975585
0123456789012346578091465237826323908411954705658196172440163709108313402980969867437272465328975585
0123456789012345678091465237826323908411954705658196172440163709108313402980969867437272465328975585
0123456789012345678901465237826323908411954705658196172440163709108313402980969867437272465328975585
0123456789012345678901234567826323908411954705658196172440163709108313402980969867437272465328975585
0123456789012345678901234567890123208431954765658196172440163709108313402980969867437272465328975585
0123456789012345678901234567890127208631954345658196172440163709108313402980969867437272465328975585
0123456789012345678901234567890126453781902345658196172440163709108313402980969867437272465328975585
0123456789012345678901234567890123456781902345658196172440163709108313402980969867437272465328975585
0123456789012345678901234567890123456780912345658196172440163709108313402980969867437272465328975585
0123456789012345678901234567890123456789012345658196172440163709108313402980969867437272465328975585
0123456789012345678901234567890123456789012345758196572450163709108315402782969836434262775608993481
0123456789012345678901234567890123456789012345024366819757163402108375402752999816834562775608993481
0123456789012345678901234567890123456789012345679806314257163402108375402752999816834562775608993481
0123456789012345678901234567890123456789012345678906314257163402108375402752999816834562775608993481
0123456789012345678901234567890123456789012345678905314267163402108375402752999816834562775608993481
0123456789012345678901234567890123456789012345678902314567163402108375402752999816834562775608993481
0123456789012345678901234567890123456789012345678901234567163402108375402752999816834562775608993481
0123456789012345678901234567890123456789012345678901234567763408108995212054739816234562775608993481
0123456789012345678901234567890123456789012345678901234567963425108798012054739816234562775608993481
0123456789012345678901234567890123456789012345678901234567893425106798012054739816234562775608993481
0123456789012345678901234567890123456789012345678901234567891023546798012054739816234562775608993481
0123456789012345678901234567890123456789012345678901234567890123546798012054739816234562775608993481
0123456789012345678901234567890123456789012345678901234567890123456798012054739816234562775608993481
0123456789012345678901234567890123456789012345678901234567890123456789012054739816234562775608993481
0123456789012345678901234567890123456789012345678901234567890123456789012654739801234562775608993481
0123456789012345678901234567890123456789012345678901234567890123456789012354679801234562775608993481
0123456789012345678901234567890123456789012345678901234567890123456789012345679801234562775608993481
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234562775608993481
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234560718928963457
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234568790128963457
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890128963457
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890125763489
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

2006-03-19 (0) 01:04:33 +0900


すのもの Sunomono