依存関係グラフの可視化


22

この課題の目標は、依存グラフをツリー形式で視覚化するプログラムを作成することです。この文脈での「依存グラフ」は有向グラフにすぎませんが、ここで説明する視覚化方法は、いくつかの依存関係を説明するグラフに最適です(課題として、課題を読んだ後、サンプルグラフ、および結果が有用かどうかを確認します。)

プログラムへの入力は、次の形式の行である1つ以上のターゲット定義で構成されます。

Target DirectDependency1 DirectDependency2 ...

ターゲットの定義、および関連する直接依存関係(ある場合)。ターゲットとその依存関係は、まとめてオブジェクトと呼ばれます。オブジェクトが依存関係としてのみ表示され、ターゲットとして表示されない場合、そのオブジェクトには依存関係がありません。入力に現れるすべてのオブジェクトのセットはΓと呼ばれます。(入力形式の詳細については、「入力および出力」セクションを参照してください。)

オブジェクトのペアABについて、次のように言います。

  • 依存するB(等価的に、 Bがで必要とされるA)場合、 Aは直接に依存する B場合、または Aは直接に依存する B「および B」に依存する B一部のオブジェクトのために、 B」
  • 適切に依存するB(等価的に、 Bが適切で必要とされるA場合、) Aが依存する B、及び Bは依存しない A

私たちは、不自然なオブジェクトを定義ʀooᴛ ʀooᴛが直接すべてのオブジェクトによって必要とされていないような、ないΓに、そしてすべてのオブジェクトのためにこのような、というAを、ʀooᴛ直接に依存してA場合と場合にのみ、Aは Γであり、そしてAがありません適切Γ内の任意のオブジェクトによって必要とされる(換言すれば、ʀooᴛ直接に依存Aは他のオブジェクトが依存していない場合はA、または依存するすべてのオブジェクト場合Aはまたによって必要とされるA。)

出力ツリー

ルートノードが「oo」であり、各ノードの子がその直接の依存関係であるようなtreeを構築します。例えば、与えられた入力

Bread Dough Yeast
Dough Flour Water
Butter Milk

、結果のツリーは

出力ツリーの例

、またはASCII形式で、

ʀooᴛ
+-Bread
| +-Dough
| | +-Flour
| | +-Water
| +-Yeast
+-Butter
  +-Milk

。プログラムの出力は、上記で定義したツリーであり、「oo」ノードなしで印刷されます。したがって、たとえば、上記の入力に対応する出力は

Bread
+-Dough
| +-Flour
| +-Water
+-Yeast
Butter
+-Milk

。出力ツリーのレイアウトの詳細な説明は、後で説明します。

ノード順序

所与の親ノードの子ノードPは、すべきでソートすべての子ノードのためにそのようなことは、AおよびBPAが表示される前にBと場合のみなら

  • そこに子ノードが存在するCPのように、Aが適切で必要とされるC、及びCの先行、又は、に等しく、Bと同じ順序に従って、。または
  • アルファベット順で先行Bは、(よりpreceisely、Aは先行Bを、ASCII照合を使用して)が存在しないない子ノードCPように、Bは、適切で必要とされるC、及びCの先行、またはと等しいが、Aと同じ順序に従って、 。

(数学的な課題を探している人は、この関係が明確に定義されており、実際には厳密な全順序であることを示すことができます。Γが有限であることを忘れないでください!)

例えば、与えられた入力

X D C B A
B D
C A

、出力は

X
+-A
+-D
+-B
| +-D
+-C
  +-A

A表示される前にB、とB前に表示されC、彼らのアルファベット順による。 Dの前Bに表示されます。これは適切に必要であるためです。また、後Aに表示されます。 Bまた、アルファベット順に先行していても、CDに表示されません。これは、同じルールに従って、B適切にを必要DとするB(つまり、それ自体)およびpreceeds というノードが存在するためCです。

繰り返し

たとえば、複数のオブジェクトで必要な場合、同じオブジェクトAが出力に複数回表示されることがあります。場合Aは、独自の依存関係はありません、特別な処理が、この場合には必要ありません。そうでない場合、出力の冗長性を最小限に抑え、循環依存関係による無限再帰を回避するために、Aの依存関係は、先祖が別のAノードの兄弟ではない最初の発生時にのみリストされます。Aの他のオカレンスには子がなく、後にスペースと省略記号が続くように表示される必要があります。A...

例えば、与えられた入力

IP Ethernet
TCP IP
UDP IP
WebRTC TCP UDP

、出力は

WebRTC
+-TCP
| +-IP
|   +-Ethernet
+-UDP
  +-IP ...

。別の例として、循環依存と祖先の考慮事項の両方を特徴として、

Rock Scissors
Paper Rock
Scissors Paper

、結果として

Paper
+-Rock ...
Rock
+-Scissors ...
Scissors
+-Paper ...

。たとえば、の最初の出現はRock、その親でPaperあるが別のRockノードの兄弟であるため、その依存関係をリストしません。2番目のRockノードの親であるʀooᴛ(出力には表示されません)Rockは兄弟としてないため、の依存関係はRockこのノードにリストされます。

出力ツリーのレイアウト

ASCIIアートとしてツリーをどのように表現すべきかについては理解していると思います(もしあれば、このセクションをスキップしてください)が、完全を期すために...

ʀooᴛの子ノードは、インデントなしで別々の行に順番に印刷されます。各ノードの直後には、子があれば、同じ形式で再帰的に印刷され、右側に2文字インデントされます。子を持つ各ノードについて、|(パイプ)文字で構成される垂直線は、ノードの最初の文字のすぐ下の文字から、最後の子ノードの子を含まない最後の子ノードの行まで伸びます。ノードのインデントがゼロ以外の場合、+-その親は(その親と同じインデントレベルで)先行し、上記の垂直線を上書きします。

入出力

STDINを介して、または同等の方法を使用して入力を読み取ることができます。空の行ないと想定し、最後の行が改行文字で終了するか、終了しないことを要求する場合があります。オブジェクト名は、印刷可能なASCII文字(スペースを含まない)で構成されていると想定できます。ターゲット定義内のオブジェクトは単一のスペース文字で区切られており、先頭または末尾にスペースないと想定できます。各ターゲットは最大1回しか定義されおらず、その依存関係リストには繰り返しないと仮定できます。

出力をSTDOUTに書き込むか、同等の方法を使用できます。最長を除くすべての出力行には、末尾のスペースが含まれる場合があります。最後の出力行は、改行文字で終わる場合とそうでない場合があります。

スコア

これはcode-golfです。バイト単位の最短回答が勝ちです。

テストケース

プログラムは、次の各テストケースを妥当な時間内に処理する必要があります。


入力

Depender Dependee
Independent

出力

Depender
+-Dependee
Independent

入力

Earth Turtle
Turtle Turtle

出力

Earth
+-Turtle
  +-Turtle ...

入力

F A C B D I
A B
B A C
D E H
C
G F
J H G C E I
E D
H D
I G

出力

J
+-C
+-E
| +-D
|   +-E ...
|   +-H ...
+-H
| +-D ...
+-G
| +-F
|   +-C
|   +-A
|   | +-B ...
|   +-B
|   | +-C
|   | +-A ...
|   +-D ...
|   +-I ...
+-I
  +-G ...

Civilization Vテクノロジーツリー

入力

出力


Cygwin syslog-ngパッケージ依存関係グラフ

入力

出力


GNU grep regex.cコールグラフ

入力

出力(Whoops!SEが処理するには長すぎます。)


5
明確に指定されています!
チャールズではないチャールズ

ノード順序セクションの自己参照は、頭を痛めます。
再帰的

回答:


5

Haskell、512バイト

import Data.List
r=reverse
n j|let(w,s)#p|let a?b=or[q!b<GT|(q,r)<-i,a==r,elem q(h p)>elem(a,q)i];a!b|a==b=EQ|a?b||(a<b)>b?a=LT;_!_=GT;l=nub.sortBy(!)$h p;m(v,s)q|h q==[]=(v,[q]:s)|elem q w=(v,[q++" ..."]:s)|(w,x:y)<-(v,[])#q=(w,(q:(u"| "=<<r y)++u"  "x):s)=foldl m(l++w,[])l;c(p,q)=z$p:q:h q;y=z=<<j;i=iterate(nub.sort.(c=<<))y!!length j;h""=[p|p<-id=<<j,and[elem(p,r)i|(r,q)<-i,p==q]];h p=[r|(q,r)<-y,p==q]=unlines=<<r(snd$mempty#"")
u s(x:y)=("+-"++x):map(s++)y
z(x:y)=(,)x<$>y
main=interact$n.map words.lines

Ideoneでオンラインで実行


おめでとうございます。非常に素晴らしい!
エル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.