Tạo biểu đồ tường thuật kiểu xkcd


45

Trong một trong những dải xkcd mang tính biểu tượng hơn, Randall Munroe đã hình dung ra các mốc thời gian của một số bộ phim trong các biểu đồ kể chuyện:

nhập mô tả hình ảnh ở đây (Bấm vào để xem phiên bản lớn hơn.)

Nguồn: xkcd số 657 .

Đưa ra một đặc điểm của dòng thời gian của một bộ phim (hoặc một số câu chuyện khác), bạn sẽ tạo ra một biểu đồ như vậy. Đây là một cuộc thi phổ biến, vì vậy câu trả lời có nhiều phiếu (net) nhất sẽ giành chiến thắng.

Yêu cầu tối thiểu

Để thắt chặt thông số kỹ thuật một chút, đây là bộ tính năng tối thiểu mỗi câu trả lời phải thực hiện:

  • Lấy làm đầu vào một danh sách các tên nhân vật, theo sau là một danh sách các sự kiện. Mỗi sự kiện là một danh sách các nhân vật sắp chết hoặc một danh sách các nhóm nhân vật (biểu thị các nhân vật hiện đang ở cùng nhau). Dưới đây là một ví dụ về cách tường thuật Công viên kỷ Jura có thể được mã hóa:

    ["T-Rex", "Raptor", "Raptor", "Raptor", "Malcolm", "Grant", "Sattler", "Gennaro",
     "Hammond", "Kids", "Muldoon", "Arnold", "Nedry", "Dilophosaurus"]
    [
      [[0],[1,2,3],[4],[5,6],[7,8,10,11,12],[9],[13]],
      [[0],[1,2,3],[4,7,5,6,8,9,10,11,12],[13]],
      [[0],[1,2,3],[4,7,5,6,8,9,10],[11,12],[13]],
      [[0],[1,2,3],[4,7,5,6,9],[8,10,11,12],[13]],
      [[0,4,7],[1,2,3],[5,9],[6,8,10,11],[12],[13]],
      [7],
      [[5,9],[0],[4,6,10],[1,2,3],[8,11],[12,13]],
      [12],
      [[0, 5, 9], [1, 2, 3], [4, 6, 10, 8, 11], [13]], 
      [[0], [5, 9], [1, 2], [3, 11], [4, 6, 10, 8], [13]], 
      [11], 
      [[0], [5, 9], [1, 2, 10], [3, 6], [4, 8], [13]], 
      [10], 
      [[0], [1, 2, 9], [5, 6], [3], [4, 8], [13]], 
      [[0], [1], [9, 5, 6], [3], [4, 8], [2], [13]], 
      [[0, 1, 9, 5, 6, 3], [4, 8], [2], [13]], 
      [1, 3], 
      [[0], [9, 5, 6, 3, 4, 8], [2], [13]]
    ]
    

    Ví dụ, dòng đầu tiên có nghĩa là ở đầu biểu đồ, T-Rex là một người đơn độc, ba Raptors ở cùng nhau, Malcolm chỉ có một mình, Grant và Sattler ở cùng nhau, v.v. Sự kiện thứ hai đến cuối cùng có nghĩa là hai trong số các Raptors chết .

    Làm thế nào chính xác bạn mong đợi đầu vào là tùy thuộc vào bạn, miễn là loại thông tin này có thể được chỉ định. Ví dụ, bạn có thể sử dụng bất kỳ định dạng danh sách thuận tiện. Bạn cũng có thể mong đợi các nhân vật trong các sự kiện sẽ lại là tên nhân vật đầy đủ, v.v.

    Bạn có thể (nhưng không phải) cho rằng mỗi danh sách các nhóm chứa mỗi nhân vật sống trong chính xác một nhóm. Tuy nhiên, bạn không nên cho rằng các nhóm hoặc nhân vật trong một sự kiện theo thứ tự đặc biệt thuận tiện.

  • Kết xuất với màn hình hoặc tệp (dưới dạng vector hoặc đồ họa raster) một biểu đồ có một dòng cho mỗi ký tự. Mỗi dòng phải được dán nhãn bằng một tên nhân vật ở đầu dòng.

  • Đối với mỗi sự kiện thông thường, phải có một số mặt cắt ngang của biểu đồ trong đó các nhóm nhân vật rõ ràng giống với sự gần gũi của các dòng tương ứng.
  • Đối với mỗi sự kiện cái chết, các dòng của các nhân vật có liên quan phải chấm dứt trong một đốm nhìn thấy được.
  • Bạn không phải tái tạo bất kỳ tính năng nào khác của âm mưu của Randall, bạn cũng không phải tái tạo phong cách vẽ của anh ấy. Các đường thẳng với các nét sắc nét, tất cả đều màu đen, không có nhãn tiếp theo và một tiêu đề là hoàn toàn tốt để tham gia cuộc thi. Cũng không cần sử dụng không gian một cách hiệu quả - ví dụ: bạn có khả năng đơn giản hóa thuật toán của mình bằng cách chỉ di chuyển các dòng xuống dưới để đáp ứng với các ký tự khác, miễn là có một hướng thời gian rõ ràng.

Tôi đã thêm một giải pháp tham chiếu đáp ứng chính xác các yêu cầu tối thiểu này.

Làm cho nó đẹp

Đây là một cuộc thi phổ biến, vì vậy, trên hết, bạn có thể thực hiện bất kỳ điều gì bạn muốn. Bổ sung quan trọng nhất là một thuật toán bố trí hợp lý làm cho biểu đồ dễ đọc hơn - ví dụ, điều này làm cho các đường uốn cong dễ theo dõi và làm giảm số lượng đường cắt cần thiết. Đây là vấn đề thuật toán cốt lõi của thách thức này! Các phiếu sẽ quyết định mức độ hiệu quả của thuật toán của bạn trong việc giữ cho biểu đồ gọn gàng.

Nhưng đây là một số ý tưởng khác, hầu hết trong số đó dựa trên biểu đồ của Randall:

Đồ trang trí:

  • Đường màu.
  • Một tiêu đề cho cốt truyện.
  • Dòng ghi nhãn kết thúc.
  • Tự động định tuyến lại các dòng đã đi qua một phần bận rộn.
  • Phong cách vẽ tay (hoặc khác? Như tôi đã nói, không cần phải tái tạo phong cách của Randall nếu bạn có ý tưởng tốt hơn) cho các đường kẻ và phông chữ.
  • Định hướng tùy chỉnh của trục thời gian.

Biểu cảm bổ sung:

  • Đặt tên sự kiện / nhóm / cái chết.
  • Biến mất và xuất hiện lại dòng.
  • Nhân vật nhập muộn.
  • Các điểm nổi bật chỉ ra các thuộc tính (có thể chuyển nhượng?) Của các ký tự (ví dụ: xem ringbearer trong biểu đồ LotR).
  • Mã hóa thông tin bổ sung trong trục nhóm (ví dụ thông tin địa lý như trong biểu đồ LotR).
  • Du hành thời gian?
  • Thực tế thay thế?
  • Một nhân vật biến thành người khác?
  • Hai nhân vật hợp nhất? (Một nhân vật tách ra?)
  • 3D? (Nếu bạn thực sự đi xa đến thế, vui lòng đảm bảo rằng bạn thực sự đang sử dụng thứ nguyên bổ sung để hình dung đôi khi!)
  • Bất kỳ tính năng có liên quan khác, có thể hữu ích để hình dung tường thuật của một bộ phim (hoặc cuốn sách, v.v.).

Tất nhiên, nhiều trong số này sẽ yêu cầu đầu vào bổ sung và bạn có thể tự do tăng định dạng đầu vào của mình khi cần thiết, nhưng vui lòng ghi lại cách nhập dữ liệu.

Vui lòng bao gồm một hoặc hai ví dụ để thể hiện các tính năng bạn đã triển khai.

Giải pháp của bạn sẽ có thể xử lý bất kỳ đầu vào hợp lệ nào, nhưng nó hoàn toàn tốt nếu nó phù hợp với một số loại tường thuật nhất định hơn các loại tường thuật khác.

Tiêu chí bỏ phiếu

Tôi không ảo tưởng rằng tôi có thể nói với mọi người cách họ nên bỏ phiếu, nhưng đây là một số hướng dẫn được đề xuất theo thứ tự quan trọng:

  • Downvote câu trả lời khai thác sơ hở, tiêu chuẩn hoặc người khác, hoặc mã hóa cứng một hoặc nhiều kết quả.
  • Không đưa ra các câu trả lời không đáp ứng các yêu cầu tối thiểu (cho dù phần còn lại có thể lạ mắt đến mức nào).
  • Đầu tiên và quan trọng nhất, nâng cao các thuật toán bố trí đẹp. Điều này bao gồm các câu trả lời không sử dụng nhiều không gian dọc trong khi giảm thiểu việc vượt qua các đường để giữ cho biểu đồ dễ đọc hoặc quản lý để mã hóa thông tin bổ sung vào trục dọc. Hình dung các nhóm mà không tạo ra một mớ hỗn độn lớn sẽ là trọng tâm chính của thử thách này, vì vậy đây vẫn là một cuộc thi lập trình với một vấn đề thuật toán thú vị.
  • Upvote các tính năng tùy chọn có thêm sức mạnh biểu cảm (nghĩa là không chỉ là trang trí thuần túy).
  • Cuối cùng, upvote trình bày tốt đẹp.

7
bởi vì code-golf không có đủ xkcd
tự hào

8
@proudhaskeller PPCG không bao giờ có thể có đủ xkcd. ;) Nhưng tôi không nghĩ rằng chúng tôi đã cố gắng thực hiện những thách thức về đồ họa / hình ảnh thông tin siêu lớn của anh ấy, vì vậy tôi hy vọng tôi sẽ mang một cái gì đó mới vào bàn với điều này. Và tôi chắc chắn rằng một số người khác cũng sẽ thực hiện những thử thách rất khác biệt và thú vị.
Martin Ender

Có ổn không nếu giải pháp của tôi chỉ xử lý 12 người đàn ông giận dữ, Duel (Spielberg, 1971, người lái xe thường xuyên và người lái xe tải điên cuồng), và Máy bay, Xe lửa và Ô tô? ;-)
Cấp sông St

4
tôi tự hỏi làm thế nào đầu vào cho mồi sẽ trông như thế nào ...
Joshua

1
@ping Có, đó là ý tưởng. Nếu một sự kiện chứa thêm danh sách, đó là một nhóm danh sách. vì vậy [[x,y,z]]sẽ có nghĩa là tất cả các nhân vật hiện đang ở cùng nhau. Nhưng nếu sự kiện không chứa danh sách, mà chỉ có các ký tự trực tiếp, thì đó là một cái chết, vì vậy trong cùng một tình huống [x,y,z]có nghĩa là ba nhân vật đó sẽ chết. Vui lòng sử dụng định dạng khác, với một dấu hiệu rõ ràng về việc một cái gì đó là một sự kiện chết hoặc nhóm nếu điều đó giúp bạn. Các định dạng trên chỉ là một gợi ý. Miễn là định dạng đầu vào của bạn ít nhất là biểu cảm, bạn có thể sử dụng một cái gì đó khác.
Martin Ender

Câu trả lời:


18

Python3 với numpy, scipy và matplotlib

công viên kỷ Jura

chỉnh sửa :

  • Tôi đã cố gắng giữ các nhóm ở vị trí tương đối giống nhau giữa các sự kiện, do đó có sorted_eventchức năng.
  • Hàm mới để tính vị trí y của các ký tự ( coords).
  • Mỗi sự kiện còn sống được vẽ hai lần bây giờ, vì vậy các nhân vật gắn bó với nhau tốt hơn.
  • Đã thêm chú thích và loại bỏ nhãn trục.
import math
import numpy as np
from scipy.interpolate import interp1d
from matplotlib import cm, pyplot as plt


def sorted_event(prev, event):
    """ Returns a new sorted event, where the order of the groups is
    similar to the order in the previous event. """
    similarity = lambda a, b: len(set(a) & set(b)) - len(set(a) ^ set(b))
    most_similar = lambda g: max(prev, key=lambda pg: similarity(g, pg))
    return sorted(event, key=lambda g: prev.index(most_similar(g)))


def parse_data(chars, events):
    """ Turns the input data into 3 "tables":
    - characters: {character_id: character_name}
    - timelines: {character_id: [y0, y1, y2, ...],
    - deaths: {character_id: (x, y)}
    where x and y are the coordinates of a point in the xkcd like plot.
    """
    characters = dict(enumerate(chars))
    deaths = {}
    timelines = {char: [] for char in characters}

    def coords(character, event):
        for gi, group in enumerate(event):
            if character in group:
                ci = group.index(character)
                return (gi + 0.5 * ci / len(group)) / len(event)
        return None

    t = 0
    previous = events[0]
    for event in events:
        if isinstance(event[0], list):
            previous = event = sorted_event(previous, event)
            for character in [c for c in characters if c not in deaths]:
                timelines[character] += [coords(character, event)] * 2
            t += 2
        else:
            for char in set(event) - set(deaths):
                deaths[char] = (t-1, timelines[char][-1])

    return characters, timelines, deaths


def plot_data(chars, timelines, deaths):
    """ Draws a nice xkcd like movie timeline """

    plt.xkcd()  # because python :)

    fig = plt.figure(figsize=(16,8))
    ax = fig.add_subplot(111)
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
    ax.set_xlim([0, max(map(len, timelines.values()))])

    color_floats = np.linspace(0, 1, len(chars))
    color_of = lambda char_id: cm.Accent(color_floats[char_id])

    for char_id in sorted(chars):
        y = timelines[char_id]
        f = interp1d(np.linspace(0, len(y)-1, len(y)), y, kind=5)
        x = np.linspace(0, len(y)-1, len(y)*10)
        ax.plot(x, f(x), c=color_of(char_id))

    x, y = zip(*(deaths[char_id] for char_id in sorted(deaths)))
    ax.scatter(x, y, c=np.array(list(map(color_of, sorted(deaths)))), 
               zorder=99, s=40)

    ax.legend(list(map(chars.get, sorted(chars))), loc='best', ncol=4)
    fig.savefig('testplot.png')


if __name__ == '__main__':
    chars = [
        "T-Rex","Raptor","Raptor","Raptor","Malcolm","Grant","Sattler",
        "Gennaro","Hammond","Kids","Muldoon","Arnold","Nedry","Dilophosaurus"
    ]
    events = [
        [[0],[1,2,3],[4],[5,6],[7,8,10,11,12],[9],[13]],
        [[0],[1,2,3],[4,7,5,6,8,9,10,11,12],[13]],
        [[0],[1,2,3],[4,7,5,6,8,9,10],[11,12],[13]],
        [[0],[1,2,3],[4,7,5,6,9],[8,10,11,12],[13]],
        [[0,4,7],[1,2,3],[5,9],[6,8,10,11],[12],[13]],
        [7],
        [[5,9],[0],[4,6,10],[1,2,3],[8,11],[12,13]],
        [12],
        [[0,5,9],[1,2,3],[4,6,10,8,11],[13]],
        [[0],[5,9],[1,2],[3,11],[4,6,10,8],[13]],
        [11],
        [[0],[5,9],[1,2,10],[3,6],[4,8],[13]],
        [10],
        [[0],[1,2,9],[5,6],[3],[4,8],[13]],
        [[0],[1],[9,5,6],[3],[4,8],[2],[13]],
        [[0,1,9,5,6,3],[4,8],[2],[13]],
        [1,3],
        [[0],[9,5,6,3,4,8],[2],[13]]
    ]
    plot_data(*parse_data(chars, events))

Hah, nhìn xkcd rất đẹp :) ... bất kỳ cơ hội nào bạn sẽ có thể gắn nhãn cho các dòng?
Martin Ender

Dán nhãn các dòng, có độ rộng khác nhau của các dòng (với việc giảm / tăng giữa một số điểm) và cuối cùng ... làm cho các đường ngang hơn khi gần một đỉnh trong khi nội suy, giống như một đường cong bezier hơn và đây sẽ là mục nhập tốt nhất IMO: )
Trình tối ưu hóa

1
Cảm ơn, nhưng phong cách xkcd được bao gồm trong matplotlib, vì vậy nó chỉ là một chức năng gọi :) Vâng, tôi đã tạo một huyền thoại, nhưng nó chiếm gần một phần ba hình ảnh, vì vậy tôi đã nhận xét nó.
pgy

Tôi đã sửa đổi câu trả lời của tôi, tôi nghĩ rằng nó có vẻ tốt hơn bây giờ.
pgy

6

T-SQL

Tôi không hài lòng với điều này như là một mục, nhưng tôi nghĩ rằng câu hỏi này xứng đáng ít nhất là một thử. Tôi sẽ cố gắng cải thiện điều này sau này cho phép, nhưng ghi nhãn sẽ luôn là một vấn đề trong SQL. Giải pháp yêu cầu SQL 2012+ và được chạy trong SSMS (SQL Server Management Studio). Đầu ra là trong tab kết quả không gian.

-- Variables for the input
DECLARE @actors NVARCHAR(MAX) = '["T-Rex", "Raptor", "Raptor", "Raptor", "Malcolm", "Grant", "Sattler", "Gennaro", "Hammond", "Kids", "Muldoon", "Arnold", "Nedry", "Dilophosaurus"]';
DECLARE @timeline NVARCHAR(MAX) = '
[
   [[1], [2, 3, 4], [5], [6, 7], [8, 9, 11, 12, 13], [10], [14]],
   [[1], [2, 3, 4], [5, 8, 6, 7, 9, 10, 11, 12, 13], [14]],
   [[1], [2, 3, 4], [5, 8, 6, 7, 9, 10, 11], [12, 13], [14]],
   [[1], [2, 3, 4], [5, 8, 6, 7, 10], [9, 11, 12, 13], [14]],
   [[1, 5, 8], [2, 3, 4], [6, 10], [7, 9, 11, 12], [13], [14]],
   [8],
   [[6, 10], [1], [5, 7, 11], [2, 3, 4], [9, 12], [13, 14]],
   [13],
   [[1, 6, 10], [2, 3, 4], [5, 7, 11, 9, 12], [14]],
   [[1], [6, 10], [2, 3], [4, 12], [5, 7, 11, 9], [14]],
   [12],
   [[1], [6, 10], [2, 3, 11], [4, 7], [5, 9], [14]],
   [11],
   [[1], [2, 3, 10], [6, 7], [4], [5, 9], [14]],
   [[1], [2], [10, 6, 7], [4], [5, 9], [3], [14]],
   [[1, 2, 10, 6, 7, 4], [5, 9], [3], [14]],
   [2, 4],
   [[1], [10, 6, 7, 5, 9], [3], [14]]
]
';

-- Populate Actor table
WITH actor(A) AS ( SELECT CAST(REPLACE(STUFF(REPLACE(REPLACE(@actors,', ',','),'","','</a><a>'),1,2,'<a>'),'"]','</a>') AS XML))
SELECT ROW_NUMBER() OVER (ORDER BY(SELECT \)) ActorID, a.n.value('.','varchar(50)') Name
INTO Actor
FROM actor CROSS APPLY A.nodes('/a') as a(n);

-- Populate Timeline Table
WITH Seq(L) AS (
    SELECT CAST(REPLACE(REPLACE(REPLACE(REPLACE(@timeline,'[','<e>'),']','</e>'),'</e>,<e>','</e><e>'),'</e>,','</e>') AS XML)
    ),
    TimeLine(N,Exerpt,Elem) AS (
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) N
        ,z.query('.')
        ,CAST(REPLACE(CAST(z.query('.') AS VARCHAR(MAX)),',','</e><e>') AS XML)
    FROM Seq 
        CROSS APPLY Seq.L.nodes('/e/e') AS Z(Z)
    ),
    Groups(N,G,Exerpt) AS (
    SELECT N, 
        ROW_NUMBER() OVER (PARTITION BY N ORDER BY CAST(SUBSTRING(node.value('.','varchar(50)'),1,ISNULL(NULLIF(CHARINDEX(',',node.value('.','varchar(50)')),0),99)-1) AS INT)), 
        CAST(REPLACE(CAST(node.query('.') AS VARCHAR(MAX)),',','</e><e>') AS XML) C
    FROM TimeLine 
        CROSS APPLY Exerpt.nodes('/e/e') as Z(node)
    WHERE Exerpt.exist('/e/e') = 1
    )
SELECT * 
INTO TimeLine
FROM (
    SELECT N, null G, null P, node.value('.','int') ActorID, 1 D 
    FROM TimeLine CROSS APPLY TimeLine.Elem.nodes('/e') AS E(node)
    WHERE Exerpt.exist('/e/e') = 0
    UNION ALL
    SELECT N, G, DENSE_RANK() OVER (PARTITION BY N, G ORDER BY node.value('.','int')), node.value('.','int') ActorID, 0
    FROM Groups CROSS APPLY Groups.Exerpt.nodes('/e') AS D(node)
    ) z;

-- Sort the entries again
WITH ReOrder AS (
            SELECT *, 
                ROW_NUMBER() OVER (PARTITION BY N,G ORDER BY PG, ActorID) PP, 
                COUNT(P) OVER (PARTITION BY N,G) CP, 
                MAX(G) OVER (PARTITION BY N) MG, 
                MAX(ActorID) OVER (ORDER BY (SELECT\)) MA
            FROM (
                SELECT *,
                    LAG(G,1) OVER (PARTITION BY ActorID ORDER BY N) PG,
                    LEAD(G,1) OVER (PARTITION BY ActorID ORDER BY N) NG
                FROM timeline
                ) rg
    )
SELECT * INTO Reordered
FROM ReOrder;
ALTER TABLE Reordered ADD PPP INT
GO
ALTER TABLE Reordered ADD LPP INT
GO
WITH U AS (SELECT N, P, LPP, LAG(PP,1) OVER (PARTITION BY ActorID ORDER BY N) X FROM Reordered)
UPDATE U SET LPP = X FROM U;
WITH U AS (SELECT N, ActorID, P, PG, LPP, PPP, DENSE_RANK() OVER (PARTITION BY N,G ORDER BY PG, LPP) X FROM Reordered)
UPDATE U SET PPP = X FROM U;
GO

SELECT Name, 
    Geometry::STGeomFromText(
        STUFF(LS,1,2,'LINESTRING (') + ')'
        ,0)
        .STBuffer(.1)
        .STUnion(
        Geometry::STGeomFromText('POINT (' + REVERSE(SUBSTRING(REVERSE(LS),1,CHARINDEX(',',REVERSE(LS))-1)) + ')',0).STBuffer(D*.4)
        )
FROM Actor a
    CROSS APPLY (
        SELECT CONCAT(', '
            ,((N*5)-1.2)
                ,' ',(G)+P
            ,', '
            ,((N*5)+1.2)
                ,' ',(G)+P 
            ) AS [text()]
        FROM (
            SELECT ActorID, N,
                CASE WHEN d = 1 THEN
                    ((MA+.0) / (LAG(MG,1) OVER (PARTITION BY ActorID ORDER BY N)+.0)) * 
                    PG * 1.2
                ELSE 
                    ((MA+.0) / (MG+.0)) * 
                    G * 1.2
                END G,
                CASE WHEN d = 1 THEN
                (LAG(PPP,1) OVER (PARTITION BY ActorID ORDER BY N) -((LAG(CP,1) OVER (PARTITION BY ActorID ORDER BY N)-1)/2)) * .2 
                ELSE
                (PPP-((CP-1)/2)) * .2 
                END P
                ,PG
                ,NG
            FROM Reordered
            ) t
        WHERE a.actorid = t.actorid
        ORDER BY N, G
        FOR XML PATH('')
        ) x(LS)
    CROSS APPLY (SELECT MAX(D) d FROM TimeLine dt WHERE dt.ActorID = a.ActorID) d
GO

DROP TABLE Actor;
DROP TABLE Timeline;
DROP TABLE Reordered;

Dòng thời gian kết quả trông như sau nhập mô tả hình ảnh ở đây


4

Toán học, Giải pháp tham khảo

Để tham khảo, tôi cung cấp một kịch bản Mathicala đáp ứng chính xác các yêu cầu tối thiểu, không hơn, không kém.

Nó hy vọng các ký tự sẽ là một danh sách định dạng trong câu hỏi charsvà các sự kiện trong events.

n = Length@chars;
m = Max@Map[Length, events, {2}];
deaths = {};
Graphics[
 {
  PointSize@Large,
  (
     linePoints = If[Length@# == 3,
         lastPoint = {#[[1]], #[[2]] + #[[3]]/(m + 2)},
         AppendTo[deaths, Point@lastPoint]; lastPoint
         ] & /@ Position[events, #];
     {
      Line@linePoints,
      Text[chars[[#]], linePoints[[1]] - {.5, 0}]
      }
     ) & /@ Range@n,
  deaths
  }
 ]

Ví dụ, đây là ví dụ về Công viên kỷ Jura sử dụng loại danh sách của Mathicala:

chars = {"T-Rex", "Raptor", "Raptor", "Raptor", "Malcolm", "Grant", 
   "Sattler", "Gennaro", "Hammond", "Kids", "Muldoon", "Arnold", 
   "Nedry", "Dilophosaurus"};
events = {
   {{1}, {2, 3, 4}, {5}, {6, 7}, {8, 9, 11, 12, 13}, {10}, {14}},
   {{1}, {2, 3, 4}, {5, 8, 6, 7, 9, 10, 11, 12, 13}, {14}},
   {{1}, {2, 3, 4}, {5, 8, 6, 7, 9, 10, 11}, {12, 13}, {14}},
   {{1}, {2, 3, 4}, {5, 8, 6, 7, 10}, {9, 11, 12, 13}, {14}},
   {{1, 5, 8}, {2, 3, 4}, {6, 10}, {7, 9, 11, 12}, {13}, {14}},
   {8},
   {{6, 10}, {1}, {5, 7, 11}, {2, 3, 4}, {9, 12}, {13, 14}},
   {13},
   {{1, 6, 10}, {2, 3, 4}, {5, 7, 11, 9, 12}, {14}},
   {{1}, {6, 10}, {2, 3}, {4, 12}, {5, 7, 11, 9}, {14}},
   {12},
   {{1}, {6, 10}, {2, 3, 11}, {4, 7}, {5, 9}, {14}},
   {11},
   {{1}, {2, 3, 10}, {6, 7}, {4}, {5, 9}, {14}},
   {{1}, {2}, {10, 6, 7}, {4}, {5, 9}, {3}, {14}},
   {{1, 2, 10, 6, 7, 4}, {5, 9}, {3}, {14}},
   {2, 4},
   {{1}, {10, 6, 7, 4, 5, 9}, {3}, {14}}
};

chúng tôi sẽ nhận được:

nhập mô tả hình ảnh ở đây

(Bấm vào để xem phiên bản lớn hơn.)

Điều đó không có vẻ quá tệ, nhưng điều đó chủ yếu là do dữ liệu đầu vào được sắp xếp ít nhiều. Nếu chúng ta xáo trộn các nhóm và nhân vật trong mỗi sự kiện (trong khi duy trì cùng cấu trúc), những thứ như thế này có thể xảy ra:

nhập mô tả hình ảnh ở đây

Đó là một chút lộn xộn.

Vì vậy, như tôi đã nói, điều này chỉ đáp ứng các yêu cầu tối thiểu. Nó không cố gắng tìm một bố cục đẹp và nó không đẹp, nhưng đó là nơi các bạn đến!


Tôi chỉ nghĩ rằng bạn có thể 'tô điểm' nó bằng cách sử dụng các phép chia bậc hai hoặc khối để loại bỏ các góc nhọn? (Tôi sẽ làm theo cách mà tiếp tuyến tại các điểm đã cho luôn luôn là 0)
flawr

@flawr Chắc chắn, hoặc tôi có thể áp dụng một số mẹo này , nhưng đó không phải là mục đích của câu trả lời này. ;) Tôi thực sự chỉ muốn cung cấp một tài liệu tham khảo cho mức tối thiểu tuyệt đối.
Martin Ender

3
Ôi xin lỗi, thậm chí không nhận thấy rằng đây là câu hỏi của riêng bạn = P
flawr
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.