Pascalの三角形 #2
さて、pascal1.gを元にして、DOT言語で表したグラフとして出力するコードに変更する。
pascal2.g
BEGIN { if (ARGC != 1) { print("usage: gvpr -fpascal2.g -a <step>"); exit(0); } int step = ARGV[0]; graph_t g = graph("pascal_triangle", "U"); node_t p[], q[]; int i, j; for (i = 0; i <= step; i++) { # create nodes in i-th step q[0] = node(g, sprintf("%d_%d", i, 0)); q[0].label = 1; for (j = 1; j < i; j++) { q[j] = node(g, sprintf("%d_%d", i, j)); q[j].label = 0 + p[j - 1].label + p[j].label; } q[i] = node(g, sprintf("%d_%d", i, i)); q[i].label = 1; # create edges from (i-1)-th step to i-th step for (j = 0; j < i; j++) { edge_sg(g, p[j], q[j], ""); edge_sg(g, p[j], q[j + 1], ""); } # prepare for next step for (j = 0; j <= i; j++) p[j] = q[j]; } write(g); }
ノードに表示される値はname属性の値が使われるが、
name属性は各ノードを区別するためのID情報であるため、
同じ表示値のノードが複数ある場合には使えない。
name属性とは無関係にノードの表示値を設定するにはlabel属性を使う。
label属性付きのノードはその表示にlabel属性の値が使われ、
この属性が無いデフォルトではname属性の値が使われることになる。
上のコードでは各ノードのname属性は二つの整数をアンダースコアで繋いだものであり、
"i_j"はを意味する。
label属性には二項係数の値を設定する。
$ gvpr -fpascal2.g -a3 graph pascal_triangle { "0_0" [label=1]; "1_0" [label=1]; "0_0" -- "1_0"; "1_1" [label=1]; "0_0" -- "1_1"; "2_0" [label=1]; "1_0" -- "2_0"; "2_1" [label=2]; "1_0" -- "2_1"; "1_1" -- "2_1"; "2_2" [label=1]; "1_1" -- "2_2"; "3_0" [label=1]; "2_0" -- "3_0"; "3_1" [label=3]; "2_0" -- "3_1"; "2_1" -- "3_1"; "3_2" [label=3]; "2_1" -- "3_2"; "2_2" -- "3_2"; "3_3" [label=1]; "2_2" -- "3_3"; }
上はPascalの三角形を0段目から3段目まで表したDOTである。
次に8段目までのグラフを描かせてみる。
$ gvpr -fpascal2.g -a8 | dot -Tpng -opascal.png