グラフを作成する


15

この課題でのタスクは、一連のディレクティブから無向グラフを作成することです。負でない整数ごとに1つのディレクティブがあり、それぞれが特定のグラフを新しいグラフに変換します。

  • ディレクティブ0:新しい切断されたノードを追加します。
  • 指令 1:新しいノードを追加し、既存のすべてのノードに接続します。
  • ディレクティブm > 1:次数(隣接数)がで割り切れるすべてのノードを削除しmます。注0すべてで割り切れるm切断ノードは常に削除されますので、。

ディレクティブは、空のグラフから左から右に1つずつ適用されます。たとえば、シーケンス[0,1,0,1,0,1,3]は次のように処理され、素晴らしいASCIIアートを使用して説明されます。空のグラフから始め、次の指示に従って単一の頂点を追加し0ます。

a

次に、別の頂点を追加し、次の指示に従って、最初の頂点に接続し1ます。

a--b

0andの指示に従って、切断された別の頂点を追加し、次に接続された頂点を追加します1

a--b   c
 \  \ /
  `--d

0andの指示に従って、これをもう一度繰り返します1

  ,--f--e
 /  /|\
a--b | c
 \  \|/
  `--d

最後に、次の指示に従って、次数3の頂点aとを削除b3ます。

f--e
|\
| c
|/
d

これは、シーケンスによって定義されるグラフ[0,1,0,1,0,1,3]です。

入力

一連のディレクティブを表す、負でない整数のリスト。

出力

シーケンスによって定義されたグラフ内のノードの数。

テストケース

[] -> 0
[5] -> 0
[0,0,0,11] -> 0
[0,1,0,1,0,1,3] -> 4
[0,0,0,1,1,1] -> 6
[0,0,1,1,0,0,1,1,2,5,7,0,1] -> 6
[0,0,1,1,1,1,5,1,4,3,1,0,0,0,1,2] -> 6
[0,0,1,1,0,0,1,1,5,2,3,0,0,1,1,0,0,1,1,3,4,0,0,1,1,2,1,1] -> 8
[0,0,1,1,0,0,1,1,2,5,7,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,8] -> 14

詳細なルール

関数または完全なプログラムを作成できます。最短のバイトカウントが優先されます。標準の抜け穴は許可されていません。回答でアルゴリズムを説明してください。


1週間が経過したので、最短の回答を受け入れました。さらに短いものが後で出てきたら、選択を更新します。賞賛に値する言及は、Peter Taylorの回答にあります。これには、勝者を含む他のいくつかの人物が基づいていました。


5
質問を読んで、実際にグラフを描画する必要があると考えている- これは非常に難しい、下にスクロールする- ああ
オプティマイザー14

@Optimizerええ、私は、グラフの実際の表現が重要ではなく、主な困難がディレクティブの実装にあるように質問を投げかけたかったです。ノードの数は、正当性を確認する簡単な方法です。
ズガルブ14

1
私はこの挑戦が本当に好きです!データ構造を設計するようなものです。入力と出力の形式はグラフに関連付けられていないため、グラフの表現方法を理解する必要があります。
xnor 14

回答:


4

ピス37 31

lu?+GH<H2m@Gdf%+*@GTtTs>GTHUGQY

このソリューションでは、reduce関数(u)を使用してリストを作成します。各エントリはリストに残っているノードに対応し、エントリの値はノードが最初にディレクティブ0または1で追加されたかに対応します。

Greduce関数のアキュムレーター変数であり、前述のリストを保持します。空のリストに初期化されYます。

Hは、Q入力の各メンバーの値を1つずつ受け取ります。式の結果はG毎回割り当てられ、の次のエントリQは割り当てられますH、式が再実行されます。

G適切に更新するには、ディレクティブ0または1用と、他のディレクティブ用の2つの可能性があります。これらのケースは、三項で区別されます? ... <H2 ...

Hが0または1の場合、必要なのはに追加HするだけGです。+GHこれを達成します。

それ以外の場合、最初に必要なことは、グラフ内のすべてのノードについて、ノードの数を決定することです。これは、2つのステップで実行されます。

まず、s>GT入力ノード以降のノードの数である1をカウントします。これらはすべて入力ノードに接続されていますが、入力ノードが1の場合は1だけカウントします。

第二に、接続されている入力ノードより前のノードの数が必要です。入力ノードが0の場合、これは0です。入力ノードが1の場合、入力ノードのインデックス、Tこの値はで与えられ*@GTTます。ただし、修正する必要がある最初のセクションからのオーバーカウントがまだあります。したがって、*@GTtT代わりに計算します。これは、入力ノードが1の場合、1減ります。これらの値を合計して、入力ノードに接続されているノードの数を求めます。

% ... Hは、数値がで割り切れるHので0を返します。したがって、削除する必要があり、そうでない場合は0を返しません。

f ... UGしたがってf、フィルタは0 であるため、削除すべきでない入力のインデックスが得られます。

m@Gd これらのインデックスを対応するノードの0と1に変換します。

最後に、0および1というラベルの付いたノードの結果リストが見つかると、その長さが計算され(l)、印刷されます(暗黙的)。

@PeterTaylorの幅広いアイデアに感謝します。


12

GolfScript(53バイト)

])~{:^1>{.-1:H)-,:T;{..H):H*T@-:T+^%!{;}*}%}{^+}if}/,

オンラインデモ

私はまだこれを実際にゴルフしたことはありませんがHTませんが、変数変数。

次の形式で標準入力を入力します [0 1 2 3]。標準出力に出力を残します。

ゴルフをしていない:

])~{
  :^1>{
    # array of 0s and 1s
    # Each 0 has degree equal to the number of 1s after it
    # Each 1 has degree equal to the number of values before it plus the number of 1s after it
    .-1:H)-,:T;
    {
      # Stack: x
      # T' = T - x is the number of 1s after it
      # H' = H + 1 is the number of values before it
      # Degree is therefore H' * x + T' = H * x + T - x = (H-1)*x + T
      # Keep x unless degree % ^ == 0
      ..H):H*T@-:T+^%!{;}*
    }%
  }{^+}if
}/,

4

CJam、129 75 73 68 61 46 42バイト

ピーターのアルゴリズムに基づくソリューション:

Lq~{I+I1>{0:U(<:L{LU<,*LU):U>1b+I%},}*}fI,

従うべきコード拡張。


以前のソリューション(61バイト):

Lq~{:N2<{U):UaN{f+U1$0f=+}*a+}{{:X,(N%_!{X0=L+:L;}*},Lf-}?}/,

STDINから次のような入力を受け取ります。

[0 0 1 1 0 0 1 1 5 2 3 0 0 1 1 0 0 1 1 3 4 0 0 1 1 2 1 1]

出力は、STDOUTの数値です。

8

アルゴリズム

  • U追加するノードのIDを格納する増分変数を維持します。
  • リストのリストを保持します。各リストは、リストの最初の要素と接続されたノードのIDで構成される残りの要素で構成される一意のIDを持つノードです。
  • 各反復(入力ディレクティブの読み取り中)で、
    • ディレクティブがの場合、リストのリストに0追加[U]します
    • ディレクティブがの場合、リストのリストの各リストに1追加Uし、リストの各リストの最初の要素で構成される別のリストを追加し、U
    • 削除するディレクティブについては、length - 1分割可能なすべてのリストを除外しm、それらのリストの最初の要素に注目し続けます。フィルタリング後、削除されたすべてのIDを残りのIDリストから削除します。

コード拡張

Lq~{:N2<{U):UaN{f+U1$0f=+}*a+}{{:X,(N%_!{X0=L+:L;}*},Lf-}?}/,
L                                            "Put an empty array on stack";
 q~                                          "Evaluate the input";
   {                                }/       "For each directive";
    :N                                       "Store the directive in N";
      2<{     ...    }{    ...    }?         "If directive is 0 or 1, run the first";
                                             "block, else second";
{U):UaN{f+U1$0f=+}*a+}
 U):U                                        "Increment and update U (initially 0)";
     a                                       "Wrap it in an array";
      N{         }*                          "Run this block if directive is 1";
        f+                                   "Add U to each list in list of list";
          U1$                                "Put U and list of lists on stack";
             0f=                             "Get first element of each list";
                +                            "Prepend U to the above array";
                   a+                        "Wrap in array and append to list of list";
{{:X,(N%_!{X0=L+:L;}*},Lf-}
 {                   },                      "Filter the list of list on this block";
  :X,(                                       "Get number of connections of this node";
      N%_                                    "mod with directive and copy the result";
         !{        }*                        "If the mod is 0, run this block";
           X0=                               "Get the id of this node";
              L+:L;                          "Add to variable L and update L";
                       Lf-                   "Remove all the filtered out ids from the";
                                             "remaining nodes";
,                                            "After the whole process is completed for"
                                             "all directives, take length of remaining ";
                                             "nodes in the list of list";

ここで試してみてください


3

Pyth、88 80 75文字

JYFHQI!H~Y]]lY)IqH1=Y+m+dlYY]UhlY)VYI&Hq%l@YNH1~J]N))=Ymf!}TJ@YkUlYY;-lYl{J

私はこれで終わりです。たぶん他の誰かがゴルフのヒントを持っています。

Yグラフの隣接リストです。ゴルフの理由から、ノードが削除された後でも、このリストにノードを保持します(そうでなければ、すべてのインデックスを更新する必要があります)。各ノードは自身をネイバーとして持っています。リストJは、削除されたノードを追跡します。

入力例の隣接リストの変更を示します[0,1,0,1,0,1,3]

入力0:Y = [[0]] J = []
入力1:Y = [[0,1]、[0,1]] 0 J = []
入力0:Y = [[0,1]、[0,1]、[2]] J = []
入力1:Y = [[0,1,3]、[0,1,3]、[2,3]、[0,1,2,3]] J = []
入力0:Y = [[0,1,3]、[0,1,3]、[2,3]、[0,1,2,3]、[4]] J = []
入力1:Y = [[0,1,3,5]、[0,1,3,5]、[2,3,5]、[0,1,2,3,5]、[4,5 ]、[0,1,2,3,4,5]] J = []
入力3:Y = [[3,5]、[3,5]、[2,3,5]、[2,3,5]、[4,5]、[2,3,4,5]] J = [0,1]

アルゴリズムは非常に簡単です。input== 0の場合、すべての入力を反復処理します。input== 1の場合、それ自体を隣接ノードとして追加します。input== 1の場合、すべてのノードを隣接ノードとして削除しますinput> 1:の場合、このノードをすべてのノードの隣接リストに追加します。#neighbor-1%input == 0でノードを決定しJ、それぞれに追加して、を使用して各ノードのネイバーを更新しますJ。最後にY、の長さから(のセット)の長さを引いた長さを出力しJます。

JYFHQI!H~Y]]lY)IqH1=Y+m+dlYY]UhlY)VYI&Hq%l@YNH1~J]N))=Ymf!}TJ@YkUlYY;-lYl{J
JY                      set J=[]
  FHQ                   for H in: input()
I!H      )                if H==0:
   ~Y]]lY                   Y.append([len(Y)])
IqH1              )       if H==1:
    =Y+                     Y=                 +
       m+dlYY                 old nodes updated
             ]UhlY                              new node with all neighbors
VY                )       for N in range(len(Q)):
  I&Hq%l@YNH1    )          if H>0 and len(Y[N])%H==1:
             ~J]N             J.append(N) //this node gets deleted
=Ym           Y           Y=[           for k in Y]
   f!}TJ@YkUlY               k-filtered  //all items of J are removed
;                       end input for loop
-lYl{J                  print len(Y) - len(set(J))

使用法

スクリプトを呼び出して、入力[0,1,0,1,0,1,3]またはその他のテストケースとして指定するだけです。


3

2

Python 2、296

s=input();e=[];n=[];c=0
for t in s:
    if t<2:e=e+[[]]if t==0 else [x+[c]for x in e]+[n[:]];n+=[c];c+=1
    else:
        M=zip(*[(i,n[i])for i,x in enumerate(e)if not len(x)%t])
        if M:e=[list(set(z)-set(M[1]))for j,z in enumerate(e)if j not in M[0]];n=list(set(n)-set(M[1]))
print len(n)

各ノードには一意のIDが与えられ、各ノードのネイバーIDが記録されます。ディレクティブが0の場合、新しいノードに空のネイバーリストが追加されます。ディレクティブが1の場合、既存のすべてのノードのIDは新しいノードのネイバーリストになり、他のすべてのネイバーリストは新しいノードIDを含むように更新されます。m> 1の場合、mの倍数である近隣リストを持つノードは、ノードリストおよびすべての近隣リストから削除されます。以前のバージョンのバグをキャッチしてくれた@Optimizerに感謝します。


2

NetLogo、160

to f[t]foreach t[if ? = 0[crt 1]if ? = 1[crt 1[create-links-with other turtles]]if ? > 1[ask turtles with[count my-links mod ? = 0][die]]]show count turtles
end

実装は簡単で、各シンボルを読み取り、適切なアクションを実行します。

to f[t]
  foreach t [
    if ? = 0 [
      crt 1
    ]
    if ? = 1 [
      crt 1 [create-links-with other turtles]
    ]
    if ? > 1 [
      ask turtles with [count my-links mod ? = 0] [die]
    ]
  ]
  show count turtles
end

コマンドラインからとして実行できますf[0 0 1 1 0 0 1 1 2 5 7 0 1]


2

Ruby 159 157(デモ

N=Struct.new:l
G=->c{n=[]
c.map{|m|m<1?n<<N.new([]):m<2?(w=N.new([])
n.map{|x|x.l<<w;w.l<<x}
n<<w):(n-=r=n.select{|x|x.l.size%m<1}
n.map{|x|x.l-=r})}
n.size}

これは、Gstabby-lambda構文を使用して呼び出される関数を定義します。を使用G[[0, 1]]してコマンド0とで呼び出します1

実装は非常に簡単です。プロパティを介してすべてのリンクされたノードへの参照を保持するNode構造(N上記)がありlます。G必要に応じてノードを作成し、それらのリンクを操作します。読み取り可能なバージョンはこちらから入手できます


1

CJam、99 97バイト

Lal~{I2<{_0={{If+z}2*));0+a+}{;Iaa}?}{_0=!!{{{_:+I%+}%z}2*));1+a+{{W=},z}2*);z_{);}{a}?}*}?}fI0=,

これにはまだゴルフをすることがたくさんあります。このアルゴリズムは、隣接行列を追跡することに基づいていますが、特別に処理する必要なく空の行列を表すことは頭痛の種です。

ここでテストしてください。

入力はCJamスタイルの配列です。

[0 0 1 1 0 0 1 1 2 5 7 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 8]

このテストハーネスを使用して、すべてのテストを実行できます。

"[]
[5]
[0,0,0,11]
[0,1,0,1,0,1,3]
[0,0,0,1,1,1]
[0,0,1,1,0,0,1,1,2,5,7,0,1]
[0,0,1,1,1,1,5,1,4,3,1,0,0,0,1,2]
[0,0,1,1,0,0,1,1,5,2,3,0,0,1,1,0,0,1,1,3,4,0,0,1,1,2,1,1]
[0,0,1,1,0,0,1,1,2,5,7,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,8]"

","SerN/{
La\~{I2<{_0={{If+z}2*));0+a+}{;Iaa}?}{_0=!!{{{_:+I%+}%z}2*));1+a+{{W=},z}2*);z_{);}{a}?}*}?}fI0=,
N}/

1

Python 2、174

l=input()
g={}
n=0
for x in l:
 n+=1;g[n]=set()
 if x>1:h={i for i in g if len(g[i])%x};g={i:g[i]&h for i in set(g)&h}
 if x==1:
  for i in g:g[i]^={n};g[n]^={i}
print len(g)

これはおそらくまだ多くのことができます。

gグラフを表すために辞書を使用しました。ノードには番号のラベルが付けられ、一連の隣接ノードにマップされます。つまり、エッジの各更新は、両方のエンドポイントで実行する必要があります。

新しいノードインデックスは、カウントアップして作成されますn。毎回、新しい空のノードを作成しますn。commandについては0、そのまま残ります。commandについては1、を介して他の各ノードに接続されますg[i]^={n};g[n]^={i}。xorを使用して、ノードがそれ自体に接続されないようにします。コマンド> 1の場合、すぐに削除されます。

次数が倍数であるノードのフィルタリングは、最初に残りのノード(h)を見つけてから、ノードandのリストと各ノードの隣接ノードでフィルタリングします。

最後に、グラフ辞書のエントリ数が答えです。


0

Mathematica、223バイト

うわー、これは思ったよりも長くなった。

f=(g={};t=Append;l=Length;m=ListQ;h=Flatten;k=Position;o=If;(d=#;o[d==0,g=g~t~{},o[d==1,g=o[m@#,t[#,l@g+1],#]&/@g;g=t[g,h@k[g,_?m,1]],g=o[l@#~Mod~d==0,0,#]&/@g;p=h@k[g,0];(c=#;g=#~DeleteCases~c&/@g)&/@p]])&/@#;g~Count~_?m)&

使用法:

f@{0, 1, 0, 1, 0, 1, 3}

テストケースの結果は次のとおりです。

f /@ {
  {},
  {5},
  {0, 0, 0, 11},
  {0, 1, 0, 1, 0, 1, 3},
  {0, 0, 0, 1, 1, 1},
  {0, 0, 1, 1, 0, 0, 1, 1, 2, 5, 7, 0, 1},
  {0, 0, 1, 1, 1, 1, 5, 1, 4, 3, 1, 0, 0, 0, 1, 2},
  {0, 0, 1, 1, 0, 0, 1, 1, 5, 2, 3, 0, 0, 1, 1, 0, 0, 1, 1, 3, 4, 0, 0, 1, 1, 2, 1, 1},
  {0, 0, 1, 1, 0, 0, 1, 1, 2, 5, 7, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 8}
}

Out: {0, 0, 0, 4, 6, 6, 6, 8, 14}

少ないゴルフ:

f = (
   a = #;
   g = {};
   Table[
    If[a[[n]] == 0,
     AppendTo[g, {}],
     If[a[[n]] == 1,
      g = If[ListQ@#, Append[#, Length@g + 1], #] & /@ g; 
      g = Append[g, Flatten@Position[g, _?ListQ, 1]],
      If[a[[n]] > 1,
       g = If[Mod[Length@#, a[[n]]] == 0, 0, #] & /@ g;
       p = Flatten@Position[g, 0];
       (c = #; g = DeleteCases[#, c] & /@ g) & /@ p
       ]
      ]
     ],
    {n, Length@a}];
   Count[g, _?ListQ]
   ) &

これが機能する方法は、グラフを「隣接リスト」のリストとして表すことです。0ディレクティブ、私は空のリストを追加します。 以下のために1つのディレクティブ、私は以前のすべてのノードのリストを追加し、以前のすべてのノードに新しいノードを追加します。 ディレクティブ> 1の場合、指定されたノードを削除し、残りを更新します。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.