有向グラフと無向グラフの変換 #1
有向グラフ
shiritori.gv
digraph kobutanukituneko { piglet -> "raccoon dog" -> fox -> cat -> piglet; }
を無向グラフに変換する。
$ gvpr "BEG_G { graph_t g = graph(name, 'U'); } E { clone(g, $); } END_G { \$O = g; }" shiritori.gv graph kobutanukituneko { piglet -- "raccoon dog"; "raccoon dog" -- fox; fox -- cat; cat -- piglet; }
このワンライナは、無向グラフのオブジェクトgを作成して、そこに全てのエッジをクローンしているだけである。
\$Oの\はgvprのためではなくbashに対して$Oを変数として解釈しないようにするためのエスケープ文字。
もし何かの間違いでgvprに\$Oの形で渡ったら文法エラーになる。
$Oの$のエスケープが面倒なら、ダブルクォートの代わりにシングルクォートで囲って、
$ gvpr 'BEG_G { graph_t g = graph(name, "U"); } E { clone(g, $); } END_G { $O = g; }' shiritori.gv
で解釈を防げるが、cmdではシングルクォートは解釈されずgvprにそのまま渡ってしまう。
bashでなくcmdなら、
C:\foo> gvpr "BEG_G { graph_t g = graph(name, 'U'); } E { clone(g, $); } END_G { $O = g; }" shiritori.gv
もしbashとcmdで共通した形式のプログラムを与えたいなら、
プログラムをファイルにして-fオプションで与えるか、
このプログラムに限れば
gvpr "BEG_G { graph_t g = graph(name, 'U'); } E { clone(g, $); } END_G { write(g); }" shiritori.gv
のようにビルトイン変数$Oにgを与えるのではなく、
ビルトイン関数write(graph_t)を使って出力すればいい。
もちろんこの方法は代替手段があるからこその方法なので、
汎用的にはワンライナをbashとcmdで共通化するのは難しい気がする。
まあ、その場で簡単に手打ちするからこそのワンライナなので、
シェルに適当に合わせてやればすむ話であり共通化する必要は全くない。
無向グラフから有向グラフへの変換も同様にできる。
$ gvpr "BEG_G { graph_t g = graph(name, 'U'); } E { clone(g, $); } END_G { write(g); }" shiritori.gv | gvpr "BEG_G { graph_t g = graph(name, 'D'); } E { clone(g, $); } END_G { write(g); }" digraph kobutanukituneko { piglet -> "raccoon dog"; "raccoon dog" -> fox; fox -> cat; cat -> piglet; }
前半部で有向グラフから無向グラフに変換したものを、後半部で有向グラフに変換している。
有向グラフにクローンされたエッジの尾部と頭部は、入力の無向グラフの--の前後関係を反映するようだ。