Xkcd-Style Anlatım Grafikleri oluşturma


45

Daha ikonik olan xkcd şeritlerinden birinde Randall Munroe, birkaç filmin zaman çizelgelerini anlatım tablolarında görselleştirdi:

görüntü tanımını buraya girin (Daha büyük versiyon için tıklayınız.)

Kaynak: xkcd No. 657 .

Bir filmin (veya başka bir anlatının) zaman çizelgesinin bir spesifikasyonu göz önüne alındığında, böyle bir grafik oluşturmalısınız. Bu bir popülerlik yarışmasıdır, bu nedenle en fazla (net) oyu olan cevap kazanacaktır.

Minimum Gereksinimler

Spesifikasyonu biraz sıkmak için, her cevabın uygulanması gereken asgari özellik kümesi:

  • Girdi olarak karakter isimlerinin bir listesini ve ardından bir etkinlik listesini alın. Her olay, ölen karakterlerin bir listesi veya karakter gruplarının bir listesidir (şu anda hangi karakterlerin birlikte olduğunu belirtir). Jurassic Park anlatısının nasıl kodlanabileceğine bir örnek:

    ["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]]
    ]
    

    Örneğin, ilk satır, tablonun başında T-Rex'in yalnız olduğu, üç Raptors'un bir arada olduğu, Malcolm'ın yalnız olduğu, Grant ve Sattler'in bir arada olduğu vs. anlamına geliyor. .

    Bu tür bir bilgi belirtilebildiği sürece, girişin tam olarak ne kadar beklediğiniz size kalmış. Örneğin herhangi bir uygun liste formatı kullanabilirsiniz. Ayrıca olaylardaki karakterlerin tekrar tam karakter adları olmasını bekleyebilirsiniz.

    Her grup listesinin, her bir canlı karakteri tam olarak bir grupta içerdiğini varsayabilir (ancak buna mecbur değilsiniz). Ancak, gereken değil grupları veya karakterler varsayalım içinde bir olay özellikle elverişli olarak sıralanmıştır.

  • Ekrana veya dosyaya (vektör veya raster grafik olarak), her karakter için bir satır içeren bir grafik oluşturur. Her satır, satırın başında bir karakter adıyla etiketlenmelidir.

  • Her normal olay için, sırayla, karakter gruplarının ilgili satırlarının yakınlığına açıkça benzetildiği grafiğin bazı kesiti olmalıdır.
  • Her ölüm olayı için ilgili karakterlerin satırları görünür bir satırda sona ermelidir.
  • Sen do not Randall parsellerin başka özelliklerini çoğaltmak zorunda, ne sen onun çizim tarzı çoğaltmak var. Keskin dönüşleri olan düz çizgiler, tümü siyah renkte, daha fazla etiket olmadan ve bir başlık, rekabete girmek için mükemmel derecede iyidir. Ayrıca, alanı verimli bir şekilde kullanmaya gerek yoktur - örneğin, fark edilebilir bir zaman yönü olduğu sürece, diğer karakterlerle buluşmak için çizgileri yalnızca aşağı doğru hareket ettirerek algoritmanızı basitleştirebilirsiniz.

Bu minimum gereklilikleri tam olarak karşılayan bir referans çözümü ekledim .

Güzel yapma

Bu bir popülerlik yarışması olsa da, bunun üzerine, ne istersen hayal gücünü uygulayabilirsin. En önemli ekleme, çizelgeyi daha okunaklı hale getiren iyi bir yerleşim algoritmasıdır - örneğin, hatlardaki virajları takip etmesini kolaylaştırır ve gerekli satır geçişlerinin sayısını azaltır. Bu, bu zorluğun temel algoritmik problemidir! Oylar algoritmanın grafiğin düzenli kalmasında ne kadar iyi performans gösterdiğine karar verecek.

Ancak burada, çoğu Randall'ın çizelgelerine dayanarak, çoğu fikir var:

Dekorasyon:

  • Renkli çizgiler
  • Arsa için bir başlık.
  • Etiketleme çizgisi biter.
  • Meşgul bir bölümden geçen satırları otomatik olarak yeniden etiketler.
  • Çizilmiş stil (veya diğer? Dediğim gibi, daha iyi bir fikriniz varsa Randall'ın stilini çoğaltmanıza gerek yoktur) satırlar ve yazı tipleri için.
  • Zaman ekseninin özelleştirilebilir yönü.

Ek Etkileyicilik:

  • Adlandırılmış olaylar / gruplar / ölümler.
  • Kaybolan ve yeniden görünen çizgiler.
  • Karakterler geç giriyor.
  • Karakterlerin (aktarılabilir?) Özelliklerini gösteren özellikler (örneğin, LotR grafiğindeki halka alıcısına bakın).
  • Gruplandırma ekseninde ek bilgi kodlaması (örneğin, LotR tablosundaki gibi coğrafi bilgiler).
  • Zaman yolculuğu?
  • Alternatif gerçekler?
  • Bir karakter diğerine dönüşüyor mu?
  • İki karakter birleşiyor mu? (Bir karakter bölme?)
  • 3 BOYUTLU? ( Gerçekten çok ileri giderseniz, lütfen bir şeyi görselleştirmek için ek boyutu kullandığınızdan emin olun!)
  • Bir filmin (veya kitabın vb.) Anlatımını görselleştirmek için yararlı olabilecek diğer tüm ilgili özellikler.

Elbette, bunların çoğu ek girdi gerektirecek ve girdi biçiminizi gerektiği gibi yükseltmekte özgürsünüz, ancak lütfen verilerin nasıl girilebileceğini belgeleyin.

Lütfen uyguladığınız özellikleri göstermek için bir veya iki örnek ekleyin.

Çözümünüz geçerli herhangi bir girdiyle başa çıkabilmelidir, ancak belirli anlatı türlerine diğerlerinden daha uygunsa kesinlikle iyi.

Oy Verme Kriterleri

İnsanlara oylarını nasıl kullanmaları gerektiğini söyleyebileceğim konusunda hiçbir fikrim yok, ama işte önem sırasına göre önerilen bazı öneriler:

  • Boşluklardan, standart olanlardan veya başkalarından yararlanan yanıtları veya bir veya daha fazla sonucu sabit kodlayan yanıtları azaltın .
  • Minimum gereklilikleri yerine getirmeyen cevapları değiştirmeyin (geri kalanının ne kadar hoş olacağına bakılmaksızın).
  • Birincisi ve en önemlisi, güzel yerleşim algoritmalarını iyileştirin. Bu, grafiği okunaklı tutmak için çizgilerin geçişini en aza indirirken çok fazla dikey alan kullanmayan veya ek bilgileri dikey eksene kodlamayı yöneten yanıtları içerir. Gruplaşmaları büyük bir karışıklık yaratmadan görselleştirmek, bu zorluğun ana odağı olmalıdır, öyle ki bu, kalbinde ilginç bir algoritmik problem olan bir programlama yarışması olmaya devam edecek.
  • Etkileyici güç katan isteğe bağlı özellikleri iyileştirin (örn. Yalnızca saf dekorasyon değildir).
  • Son olarak, güzel tanıtıma oy verin.

7
çünkü kod-golf yeterli xkcd'ye sahip değil
proud haskeller 11:14

8
@prodhaskeller PPCG hiçbir zaman yeterli xkcd'ye sahip olamaz. ;) Ama onun yerini almış bilgi grafikleri / görselleştirmelerinde henüz zorluk çıkarmaya çalıştığımızı sanmıyorum, bu yüzden masaya bununla yeni bir şey getirdiğimi umuyorum. Ve bazılarının da çok farklı ve ilginç zorluklar yaratacağından eminim.
Martin Ender

Benim çözümüm sadece 12 kızgın adamı, Duel'i (Spielberg, 1971, düzenli motorcu vs çılgın kamyon şoförü) ve Uçaklar, Trenler ve Otomobilleri ele alırsa sorun olur mu? ;-)
Level River St

4
primer girişinin nasıl görüneceğini merak ediyorum ...
Joshua

1
@ Evet, fikir buydu. Bir etkinlik başka listeler içeriyorsa, bu bir liste gruplandırmasıdır. Bu [[x,y,z]], tüm karakterlerin şu anda birlikte olduğu anlamına gelir. Ancak olay listeler içermiyorsa, ancak doğrudan karakterler içeriyorsa, bu bile bir ölümdür, bu nedenle aynı durumda [x,y,z]bu üç karakterin ölmesi anlamına gelir. Başka bir format kullanmaktan çekinmeyin, bir şeyin ölüm ya da gruplama olayı olup olmadığını açık bir şekilde belirtiyorsa, bu size yardımcı olur. Yukarıdaki format sadece bir öneridir. Giriş biçiminiz en az etkileyici olduğu sürece başka bir şey kullanabilirsiniz.
Martin Ender

Yanıtlar:


18

Numt, scipy ve matplotlib içeren Python3

Jurassic Park

düzenle :

  • Grupları olaylar arasında göreceli pozisyonda tutmaya çalıştım, dolayısıyla sorted_eventişlev.
  • Karakterlerin y konumunu ( coords) hesaplamak için yeni fonksiyon .
  • Her canlı olay şimdi iki kez çizildi, bu yüzden karakterler birbirine daha iyi yapışıyor.
  • Açıklama eklendi ve kaldırılan eksen etiketi.
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, çok güzel bir xkcd görünüm:) ... satırları etiketleyebilme şansınız var mı?
Martin Ender

Çizgileri etiketleyin, farklı çizgi genişliğine sahip olun (bazı noktalar arasında azalan / artan) ve son olarak ... enterpolasyon yaparken, bir bezier eğrisi gibi, daha çok bir çerçeve eğrisi gibi çizgileri daha yatay hale getirin ve bu en iyi giriş IMO olacaktır: )
Doktoru

1
Teşekkürler, ama xkcd tarzı matplotlib'e dahil edilmiştir, bu yüzden sadece bir işlev çağrısıydı :) Eh, bir efsane oluşturdum ama görüntünün neredeyse üçte birini işgal etti, ben de yorum yaptım.
pgy

Cevabımı değiştirdim, sanırım şimdi daha iyi görünüyor.
pgy

6

T-SQL

Bir giriş olarak bundan memnun değilim, ama bence bu soru en azından bir denemeyi hak ediyor. Daha sonra izin vererek bunu daha da geliştirmeye çalışacağım, ancak etiketleme SQL'de her zaman bir sorun olacak. Çözüm, SQL 2012+ gerektiriyor ve SSMS'de çalışıyor (SQL Server Management Studio). Çıktı uzaysal sonuçlar sekmesindedir.

-- 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;

Elde edilen zaman çizelgesi aşağıdaki gibi gözüküyor görüntü tanımını buraya girin


4

Mathematica, Referans Çözümü

Başvuru için, tam olarak asgari gereklilikleri yerine getiren, daha fazla değil, daha az olmayan bir Mathematica betiği sunuyorum.

Karakterlerin sorudaki formatın charsve olayların içindeki bir listesi olmasını bekler 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
  }
 ]

Örnek olarak, Mathematica'nın liste türünü kullanan Jurassic Park örneği:

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}}
};

alacağız:

görüntü tanımını buraya girin

(Daha büyük versiyon için tıklayınız.)

Bu çok kötü gözükmüyor , fakat bunun nedeni girdi verilerinin az ya da çok sıralı olmasıdır. Her olaydaki grupları ve karakterleri karıştırırsak (aynı yapıyı korurken), bunun gibi şeyler olabilir:

görüntü tanımını buraya girin

Bu biraz karışıklık.

Dediğim gibi, bu sadece asgari şartları yerine getiriyor. Güzel bir düzen bulmaya çalışmıyor ve hoş değil, ama siz girdiğiniz yer orası!


Keskin köşeleri çıkarmak için ikinci dereceden ya da kübik eğri çizgiler kullanarak 'güzelleştirebilirsin' diye düşündüm. (Bu şekilde, verilen noktalardaki
teğetin

@flawr Tabii ya da bu numaraların bazılarını uygulayabilirim , ancak bu cevabın amacı değildi. ;) Gerçekten sadece mutlak asgari için bir referans vermek istedim.
Martin Ender

3
Üzgünüm, bunun kendi sorunuz olduğunu bile fark
etmediniz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.