Trực quan đồ thị phụ thuộc


22

Mục tiêu của thử thách này là viết một chương trình trực quan hóa biểu đồ phụ thuộc dưới dạng cây. Mặc dù "biểu đồ phụ thuộc" trong ngữ cảnh này có nghĩa là không có gì khác hơn biểu đồ có hướng, phương pháp trực quan được mô tả ở đây hoạt động tốt nhất cho các biểu đồ mô tả một số mối quan hệ phụ thuộc (như một bài tập, sau khi bạn đọc thử thách, hãy thử đảo ngược hướng của một trong các biểu đồ mẫu và xem kết quả có hữu ích không.)

Đầu vào của chương trình bao gồm một hoặc nhiều định nghĩa đích , là các dòng có dạng

Target DirectDependency1 DirectDependency2 ...

, xác định mục tiêu và các phụ thuộc trực tiếp liên quan của nó , nếu có. Các mục tiêu và các phụ thuộc của chúng được gọi chung là các đối tượng . Nếu một đối tượng chỉ xuất hiện dưới dạng phụ thuộc và không phải là mục tiêu thì nó không có phụ thuộc. Tập hợp của tất cả các đối tượng xuất hiện trong các đầu vào được gọi là Γ . (Xem phần Đầu vào và Đầu ra để biết thêm chi tiết về định dạng đầu vào.)

Đối với bất kỳ cặp đối tượng, AB , chúng tôi nói rằng:

  • A phụ thuộc vào B (tương đương, B được yêu cầu bởi A ), nếu A phụ thuộc trực tiếp vào B hoặc nếu A phụ thuộc trực tiếp vào B ' B' phụ thuộc vào B , đối với một số đối tượng B ' ;
  • Một đúng phụ thuộc vào B (tương đương, B được yêu cầu đúng cách Một ), nếu A phụ thuộc vào B , và B không phụ thuộc vào một .

Chúng tôi định nghĩa một đối tượng bị tước , ʀooᴛ , không phải trong, sao cho ooᴛ không được yêu cầu trực tiếp bởi bất kỳ đối tượng nào và vì vậy, đối với tất cả các đối tượng A , ʀooᴛ phụ thuộc trực tiếp vào A khi và chỉ khi A ở trong và A không cần đúng cách bởi bất kỳ đối tượng trong Γ (nói cách khác, ʀooᴛ trực tiếp phụ thuộc vào A nếu không có đối tượng khác phụ thuộc vào A , hoặc nếu tất cả các đối tượng mà phụ thuộc vào A cũng được yêu cầu bởi Một .)

Cây đầu ra

Chúng ta xây dựng một cây , có nút gốc là ʀooᴛ và sao cho các phần tử con của mỗi nút là các phụ thuộc trực tiếp của nó. Ví dụ, đưa ra đầu vào

Bread Dough Yeast
Dough Flour Water
Butter Milk

, cây kết quả là

Ví dụ cây đầu ra

hoặc, ở dạng ASCII,

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

. Đầu ra của chương trình là cây được xác định ở trên, được in mà không có nút ʀooᴛ. Vì vậy, ví dụ, đầu ra tương ứng cho đầu vào trên là

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

. Một mô tả chi tiết về cách bố trí của cây đầu ra được đưa ra sau.

Thứ tự nút

Các nút con của một nút cha đã cho, P , nên được sắp xếp , sao cho tất cả các nút con AB của P , A xuất hiện trước B khi và chỉ khi

  • tồn tại một nút con C của P , sao cho A được yêu cầu đúng bởi CC có trước, hoặc bằng, B , theo cùng một thứ tự; hoặc ,
  • Một bảng chữ cái trước B (preceisely hơn, Một đến trước B sử dụng ASCII collation,) có tồn tại không có nút con C của P , sao cho B là cần thiết đúng bởi C , và C đến trước, hoặc tương đương với, Một , theo thứ tự .

(Những người tìm kiếm một thách thức toán học có thể muốn chỉ ra rằng mối quan hệ này được xác định rõ và trên thực tế, đó là một tổng số nghiêm ngặt. Đừng quên rằng là hữu hạn!)

Ví dụ, đưa ra đầu vào

X D C B A
B D
C A

, đầu ra phải là

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

. Axuất hiện trước BBxuất hiện trước C, do thứ tự chữ cái của chúng; Dxuất hiện trước B, vì nó được yêu cầu đúng bởi nó, và sau đó A, vì nó theo thứ tự abc; BCkhông xuất hiện trước đó D, mặc dù chúng có trước theo thứ tự abc, vì tồn tại một nút, cụ thể là, Byêu cầu đúng D, và nó tương đương với B(tức là chính nó) và Ctheo các quy tắc tương tự.

Sự lặp lại

Cùng một đối tượng, A , có thể xuất hiện nhiều lần trong đầu ra, ví dụ, nếu nó được yêu cầu bởi nhiều hơn một đối tượng. Nếu A không có sự phụ thuộc của riêng nó, thì không cần xử lý đặc biệt trong trường hợp này. Mặt khác, để giảm thiểu mức độ chi tiết của đầu ra và để tránh đệ quy vô hạn do phụ thuộc vòng tròn, các phụ thuộc của A chỉ được liệt kê trong lần xuất hiện đầu tiên mà không có tổ tiên nào là anh em ruột của một nút A khác ; bất kỳ sự xuất hiện nào khác của A sẽ không có con và sẽ xuất hiện theo sau là khoảng trắng và dấu chấm lửng, như trong .A...

Ví dụ, đưa ra đầu vào

IP Ethernet
TCP IP
UDP IP
WebRTC TCP UDP

, đầu ra phải là

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

. Một ví dụ khác, có cả sự phụ thuộc vòng tròn và các cân nhắc về tổ tiên,

Rock Scissors
Paper Rock
Scissors Paper

, nên dẫn đến

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

. Lưu ý rằng, ví dụ, lần xuất hiện đầu tiên Rockkhông liệt kê các phụ thuộc của nó, vì cha mẹ của nó Paper, là anh chị em của một Rocknút khác . RockCha mẹ của nút thứ hai , ʀooᴛ (không xuất hiện trong đầu ra), không có Rockanh chị em, vì vậy các phụ thuộc của Rockđược liệt kê trên nút này.

Bố trí cây đầu ra

Tôi chắc chắn rằng bạn đã hiểu được cách cây được thể hiện như nghệ thuật ASCII (và thoải mái bỏ qua phần này nếu bạn có,) nhưng vì lợi ích của sự hoàn chỉnh ...

Các nút con của ʀooᴛ được in trên các dòng riêng biệt, không có bất kỳ vết lõm nào, theo thứ tự. Mỗi nút ngay lập tức được theo sau bởi các con của nó, nếu có, được in theo cùng một kiểu, đệ quy, được thụt vào bởi hai ký tự bên phải. Đối với mỗi nút có con, một đường thẳng đứng, bao gồm các |ký tự (ống), kéo dài xuống từ ký tự ngay bên dưới ký tự đầu tiên của nút, cho đến hàng của nút con cuối cùng của nó, không bao gồm các con của nút con cuối cùng. Nếu thụt lề của một nút là khác 0, thì nó được đặt trước +-(trên cùng mức thụt lề như cha mẹ của nó), ghi đè lên đường thẳng đứng được mô tả ở trên.

Đầu vào và đầu ra

Bạn có thể đọc đầu vào thông qua STDIN hoặc sử dụng một phương thức tương đương . Bạn có thể cho rằng không có dòng trống nào và bạn có thể yêu cầu dòng cuối cùng kết thúc hoặc không kết thúc bằng ký tự dòng mới. Bạn có thể giả sử rằng tên đối tượng bao gồm các ký tự ASCII có thể in (không bao gồm khoảng trắng). Bạn có thể giả định rằng các đối tượng trong một định nghĩa mục tiêu được phân tách bằng một ký tự khoảng trắng duy nhấtkhông có khoảng trắng ở đầu hoặc cuối . Bạn có thể giả định rằng mỗi mục tiêu được xác định nhiều nhất một lầnkhông có sự lặp lại trong danh sách phụ thuộc của nó.

Bạn có thể viết đầu ra cho STDOUT hoặc sử dụng một phương thức tương đương . Tất cả các dòng đầu ra, ngoại trừ dài nhất, có thể bao gồm các dấu cách. Dòng đầu ra cuối cùng có thể, hoặc không, kết thúc bằng một ký tự dòng mới.

Ghi bàn

Đây là mã golf . Các câu trả lời ngắn nhất , tính bằng byte, thắng.

Các trường hợp thử nghiệm

Chương trình của bạn nên xử lý từng trường hợp kiểm tra sau trong một khoảng thời gian hợp lý.


Đầu vào

Depender Dependee
Independent

Đầu ra

Depender
+-Dependee
Independent

Đầu vào

Earth Turtle
Turtle Turtle

Đầu ra

Earth
+-Turtle
  +-Turtle ...

Đầu vào

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

Đầu ra

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

Cây công nghệ V

Đầu vào

Đầu ra


Biểu đồ phụ thuộc gói Cygwin syslog-ng

Đầu vào

Đầu ra


regex.cĐồ thị cuộc gọi GNU grep

Đầu vào

Đầu ra (Rất tiếc! Quá lâu để SE xử lý.)


5
Được chỉ định rõ!
Không phải Charles

Việc tự tham khảo trong phần thứ tự Node khiến đầu tôi đau.
đệ quy

Câu trả lời:


5

Haskell, 512 byte

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

Chạy trực tuyến tại Ideone


Chúc mừng. Rất đẹp!
Ell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.