スタック* を少々拡張し, 任意の位置のデータが見れるようにしたデータ構造で一つの杭に積んである円盤の番号を保存することにし, これを三つ用意します.
以下の操作を提供する stack 型のオブジェクトがあるとします. すなわち
- init(int n) で n 個の int 値を格納できるよう初期化
- push(int data) で data をスタックにプッシュ
- int pop() でデータをスタックからポップ
- int depth() で現在のスタックの深さを参照
- int data(int position) で指定した位置の値を参照
- finalize() で終了処理を行う
とします.
仮のコードは以下のようになります.
#include <stdio.h> #include <stdlib.h> stack pegs[3]; int N, w; static void print() { int i, j, k; w ミリ秒停止. 端末をクリアして 2行1桁目に移動. for (i = 0; i < N; i++) { for (j = 0; j < 3; j++) { if (pegs[j].depth < N - i) 1 個の ' ', N個の ' ', 1個の '|', N個の ' ' および 1個の ' ' を出力. else 1 個の ' ', (N - pegs[j].data[N - i - 1]) 個の ' ', pegs[j].data[N - i - 1] 個の '-', 1 個の '|', pegs[j].data[N - i - 1] 個の '-', (N - pegs[j].data[N - i - 1]) 個の ' ' および 1 個の ' ' を出力. } 改行を出力. } (6*N + 9) 個の '=' と改行を出力. } static void move(stack *src, stack *tmp, stack *dst, int n) { if (n == 0) return; move(src, dst, tmp, n - 1); dst->push(src->pop()); print(); move(tmp, src, dst, n - 1); } int main(int argc, char *argv[]) { /* * init */ N = (argc < 2)?3:atoi(argv[1]); w = (argc < 3)?500:atoi(argv[2]); pegs[0].init(); pegs[1].init(); pegs[2].init(); for (i = 0; i < N; i++) pegs[0].push(N - i); /* * do */ print(); move(&pegs[0], &pegs[1], &pegs[2], N); /* * fainalize */ free(pegs[0].data); free(pegs[1].data); free(pegs[2].data); return 0; }
stack の実装.
- データ自体は構造体で定義します.
typedef _struct { int depth; int *data; } struct;
stack s; に対して
- s.init(int n) は
s.data = (int *)malloc(n*sizeof(int)); s.depth = 0;
- s.push(int data) は
s.data[s.depth++] = data;
- s.pop() は
s.data[--s.depth];
- s.depth() は
s.depth
- s.data(int position) は
s.data[position]
- s.finalize() は
free(s.data);
のように書けます.
また, 利用される可能性のある最大の長さで, ‘ ‘, ‘-’, ‘=’ の連なった文字列を用意しておき, (用意した長さ – 出力したい長さ)番目の文字から出力することで任意の長さの ‘ ‘ や ‘-’ の連なった文字列を出力します.
それぞれのコード量が少ないので展開してしまいます. コードは以下のようになります.
#include <stdio.h> #include <stdlib.h> typedef struct _stack { int depth; int *data; } stack; stack pegs[3]; int N, w; char *bar, *ws, *grnd; char clsmv21[] = "\x1b[2J\x1b[2;1H"; static void print() { int i, j, k; usleep(w*1000); fputs(clsmv21, stdout); for (i = 0; i < N; i++) { for (j = 0; j < 3; j++) { if (pegs[j].depth < N - i) printf(" %s|%s ", ws, ws); else printf(" %s%s|%s%s ", ws + (pegs[j].data[N - i - 1]), bar + (N - pegs[j].data[N - i - 1]), bar + (N - pegs[j].data[N - i - 1]), ws + (pegs[j].data[N - i - 1])); } putchar('\n'); } fputs(grnd, stdout); } static void move(stack *src, stack *tmp, stack *dst, int n) { if (n == 0) return; move(src, dst, tmp, n - 1); dst->data[dst->depth++] = src->data[--src->depth]; print(); move(tmp, src, dst, n - 1); } int main(int argc, char *argv[]) { int i; /* * init */ N = (argc < 2)?3:atoi(argv[1]); w = (argc < 3)?500:atoi(argv[2]); pegs[0].data = (int *)malloc(N*sizeof(int)); pegs[0].depth = 0; pegs[1].data = (int *)malloc(N*sizeof(int)); pegs[1].depth = 0; pegs[2].data = (int *)malloc(N*sizeof(int)); pegs[2].depth = 0; for (i = 0; i < N; i++) pegs[0].data[pegs[0].depth++] = N - i; /* * for display */ bar = (char *)malloc((N + 1)*sizeof(char)); for (i = 0; i < N; i++) bar[i] = '-'; bar[N] = '\0'; ws = (char *)malloc((N + 1)*sizeof(char)); for (i = 0; i < N; i++) ws[i] = ' '; ws[N] = '\0'; grnd = (char *)malloc((6*N + 11)*sizeof(char)); for (i = 0; i < 6*N + 9; i++) grnd[i] = '='; grnd[6*N + 9] = '\n'; grnd[6*N + 10] = '\0'; /* * do */ print(); move(&pegs[0], &pegs[1], &pegs[2], N); /* * fainalize */ free(bar); free(ws); free(grnd); free(pegs[0].data); free(pegs[1].data); free(pegs[2].data); return 0; }