Buat grafik

15

Dalam tantangan ini, tugas Anda adalah membuat grafik yang tidak diarahkan dari urutan arahan. Ada satu arahan untuk setiap integer nonnegatif, dan masing-masing mengubah grafik yang diberikan menjadi yang baru.

  • Arahan 0: Tambahkan node terputus baru.
  • Arahan 1: Tambahkan node baru, dan hubungkan ke setiap node yang ada.
  • Arahan m > 1: Hapus semua node yang derajatnya (jumlah tetangga) habis dibagi m. Catatan yang 0dapat dibagi oleh semua m, sehingga node terputus selalu dihapus.

Arahan diterapkan satu per satu, dari kiri ke kanan, dimulai dengan grafik kosong. Misalnya, urutan [0,1,0,1,0,1,3]diproses sebagai berikut, dijelaskan menggunakan seni ASCII yang mengagumkan. Kami mulai dengan grafik kosong, dan menambahkan satu titik seperti yang diarahkan oleh 0:

a

Kemudian, tambahkan simpul lain dan hubungkan ke yang pertama, seperti yang diarahkan oleh 1:

a--b

Kami menambahkan simpul terputus lain dan kemudian terhubung, seperti yang diarahkan oleh 0dan 1:

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

Kami mengulangi ini sekali lagi, sebagaimana diarahkan oleh 0dan 1:

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

Akhirnya, kami menghapus simpul derajat-3 adan b, sebagaimana diarahkan oleh 3:

f--e
|\
| c
|/
d

Ini adalah grafik yang ditentukan oleh urutan [0,1,0,1,0,1,3].

Memasukkan

Daftar bilangan bulat negatif, mewakili urutan arahan.

Keluaran

Jumlah node dalam grafik ditentukan oleh urutan.

Uji kasus

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

Aturan terperinci

Anda dapat menulis fungsi atau program lengkap. Hitungan byte terpendek menang. Celah standar tidak diijinkan. Tolong jelaskan algoritma Anda dalam jawaban Anda.


Sudah seminggu, jadi saya telah menerima jawaban terpendek. Jika yang lebih pendek datang nanti, saya akan memperbarui pilihan saya. Disebutkan dengan terhormat jawaban Peter Taylor , yang menjadi dasar beberapa orang lain, termasuk pemenangnya.

Zgarb
sumber
5
Ketika saya membaca pertanyaan, berpikir Anda harus benar-benar menggambar grafik - Ini sangat sulit , gulir ke bawah - oh
Pengoptimal
@ Pengoptimal Ya, saya ingin mengajukan pertanyaan sehingga representasi sebenarnya dari grafik tidak penting, dan kesulitan utama terletak pada penerapan arahan. Jumlah node hanyalah cara mudah untuk memeriksa kebenaran.
Zgarb
1
Saya sangat suka tantangan ini! Ini seperti merancang struktur data. Anda harus mencari cara untuk merepresentasikan grafik karena format input dan output tidak terikat padanya.
xnor

Jawaban:

4

Pyth , 37 31

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

Solusi ini menggunakan fungsi pengurangan ( u) untuk membangun daftar, di mana setiap entri sesuai dengan simpul yang tersisa dalam daftar, dan nilai entri yang sesuai dengan apakah simpul awalnya ditambahkan di bawah direktif 0 atau 1.

Gadalah variabel akumulator dalam fungsi pengurangan, dan memegang daftar tersebut di atas. Ini diinisialisasi ke daftar kosong Y,.

Hmengambil nilai setiap anggota Q, input, satu per satu. Hasil dari ekspresi ditugaskan untuk Gsetiap waktu, dan entri berikutnya Qditugaskan untuk H, dan ekspresi dijalankan kembali.

Untuk memperbarui Gdengan benar, ada dua kemungkinan, satu untuk arahan 0 atau 1, dan satu untuk arahan lainnya. Kasus ini dibedakan dengan ternary? ... <H2 ...

Jika Hadalah 0 atau 1, maka semua yang perlu kita lakukan adalah append Huntuk G. +GHmenyelesaikan ini.

Jika tidak, hal pertama yang perlu adalah menentukan, untuk setiap node dalam grafik, berapa banyak tetangga yang dimilikinya. Ini dicapai dalam dua langkah:

Pertama, s>GTmenghitung jumlah node pada atau setelah input node yang 1s. Ini semua terhubung ke input node, kecuali bahwa kita akan menghitung lebih dari 1 jika input node adalah 1.

Kedua, kita membutuhkan jumlah node lebih awal dari input node yang terhubung dengannya. Ini adalah 0 jika simpul input adalah 0, dan indeks dari simpul input T,, jika simpul input adalah 1. Nilai ini akan diberikan oleh *@GTT. Namun, masih ada kelebihan dari bagian pertama yang perlu diperbaiki. Jadi, kita menghitung *@GTtTsebaliknya, yaitu 1 kurang jika simpul input adalah 1. Nilai-nilai ini dijumlahkan, untuk memberikan jumlah simpul yang terhubung ke simpul input.

% ... Hakan memberi 0 adalah angka itu dapat dibagi dengan H, dan dengan demikian harus dihapus, dan tidak akan memberikan 0 sebaliknya.

f ... UGdengan demikian akan memberikan indeks input yang tidak boleh dihapus, karena fmerupakan filter, dan 0 salah.

m@Gd mengkonversi indeks ini ke 0s dan 1s dari node yang sesuai.

Akhirnya, setelah daftar node yang dihasilkan berlabel 0 dan 1 ditemukan, panjangnya dihitung ( l) dan dicetak (implisit).

Gagasan luas berkat @PeterTaylor.

isaacg
sumber
12

GolfScript (53 byte)

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

Demo online

Saya belum benar-benar bermain golf ini, tetapi saya telah menemukan bahwa itu tidak mudah untuk menghilangkan Hdan Tvariabel jadi ini mungkin minimum lokal.

Mengambil input pada stdin dalam format [0 1 2 3]. Meninggalkan output pada stdout.

Tidak Disatukan:

])~{
  :^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
}/,
Peter Taylor
sumber
4

CJam, 129 75 73 68 61 46 42 byte

Solusi berdasarkan algoritma Peter:

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

Perluasan kode untuk diikuti.


Solusi sebelumnya (61 byte):

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

Mengambil input dari STDIN seperti:

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

Output adalah angka pada STDOUT:

8

Algoritma :

  • Pertahankan variabel yang bertambah U yang menyimpan id dari node yang akan ditambahkan.
  • Menyimpan daftar daftar di mana, setiap daftar adalah node dengan id unik yang dibuat oleh elemen pertama dari daftar dan elemen yang tersisa menjadi id dari node yang terhubung.
  • Di setiap iterasi (sambil membaca arahan input),
    • Jika arahannya adalah 0, tambahkan[U] ke daftar daftar
    • Jika direktif adalah 1, tambahkan Uke setiap daftar dalam daftar daftar dan tambahkan daftar lain yang terdiri dari elemen pertama dari masing-masing daftar daftar danU
    • Agar arahan dihapus, saya memfilter semua daftar yang length - 1dapat dibagi dengan mdan terus mencatat elemen pertama dari daftar tersebut. Setelah memfilter, saya menghapus semua id yang dihapus dari daftar id yang tersisa.

Perluasan kode :

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

Coba di sini

Pengoptimal
sumber
3

Pyth, 88 80 75 karakter

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

Saya selesai. Mungkin ada orang lain yang punya kiat bermain golf.

Yadalah daftar kedekatan grafik. Untuk alasan bermain golf, saya juga menyimpan simpul dalam daftar ini, bahkan setelah simpul dihapus (Kalau tidak, saya harus memperbarui semua indeks). Setiap node memiliki dirinya sendiri sebagai tetangga. DaftarJ melacak node yang dihapus.

Saya menunjukkan perubahan daftar kedekatan pada input contoh [0,1,0,1,0,1,3]:

masukan 0: Y = [[0]] J = []
input 1: Y = [[0,1], [0,1]] 0 J = []
masukan 0: Y = [[0,1], [0,1], [2]] J = []
input 1: Y = [[0,1,3], [0,1,3], [2,3], [0,1,2,3]] J = []
masukan 0: Y = [[0,1,3], [0,1,3], [2,3], [0,1,2,3], [4]] J = []
input 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 = []
input 3: Y = [[3,5], [3,5], [2,3,5], [2,3,5], [4,5], [2,3,4,5]] J = [0,1]

Algoritma kemudian cukup sederhana: Iterate atas semua input, jika input == 0: tambahkan node baru dengan dirinya sebagai tetangga, jika input == 1: tambahkan node baru dengan semua node sebagai tetangga (juga yang dihapus) dan tambahkan node ini ke daftar adjacency dari semua node, jika input> 1: tentukan node dengan # neighbor-1% input == 0 dan tambahkan mereka J, dalam setiap kasus, perbarui tetangga masing-masing node menggunakan J. Pada akhirnya cetak panjang Yminus panjang (set) 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))

Pemakaian

Panggil saja skrip dan berikan sebagai input [0,1,0,1,0,1,3]atau beberapa test case lainnya.

Jakube
sumber
3

APL, 71 65 55 karakter

{⍬≡⍺:≢⍵⋄r←1↓⍺⋄1<c←⊃⍺:r∇i⌿⍵/⍨i←0≠c|+/⍵⋄c:r∇∨⌿↑a(⍉a←⍵,1)⋄r∇0,0⍪⍵}∘(0 0⍴0)

{⍺←0 0⍴0⋄⍬≡⍵:≢⍺⋄(⍺{1<⍵:i⌿⍺/⍨i←×⍵|+/⍺⋄⍵:-⌿↑(1,1⍪⍺)1⋄0,0⍪⍺}⊃⍵)∇1↓⍵}

{g←0 0⍴0⋄(≢g)⊣{1<⍵:g⌿⍨←g/⍨←×⍵|+/g⋄(⊃g)-←g⍪⍨←g,⍨←⍵}¨2,⍵}

Grafik direpresentasikan sebagai matriks kedekatan boolean. Baris / kolom ditambahkan dan dihapus seperlunya.

ngn
sumber
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)

Setiap node diberi id unik dan id tetangga dari setiap node dicatat. Ketika direktif adalah 0, daftar tetangga kosong ditambahkan untuk node baru. Ketika direktifnya adalah 1, id dari semua node yang ada menjadi daftar tetangga untuk simpul baru, dan semua daftar tetangga lainnya diperbarui untuk menyertakan id simpul baru. Untuk m> 1, node dengan daftar tetangga yang merupakan kelipatan m dihapus dari daftar simpul dan semua daftar tetangga. Terima kasih kepada @Optimizer karena menangkap bug di versi sebelumnya.

pengguna2487951
sumber
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

Implementasinya mudah, membaca setiap simbol dan melakukan tindakan yang sesuai.

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

Anda dapat menjalankan dari baris perintah sebagai f[0 0 1 1 0 0 1 1 2 5 7 0 1].

Ypnypn
sumber
2

Ruby 159 157 ( demo )

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}

Ini mendefinisikan fungsi yang disebut Gmenggunakan sintaks stabby-lambda. Gunakan G[[0, 1]]untuk memanggilnya dengan perintah 0dan1 .

Implementasinya cukup mudah: ada Nodestruktur (disebut di Natas) yang menyimpan referensi ke semua node yang terhubung melalui lproperti. Gmembuat simpul sesuai kebutuhan dan memanipulasi tautannya. Versi yang dapat dibaca tersedia di sini .

Cristian Lupascu
sumber
1

CJam, 99 97 byte

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

Masih banyak yang bisa dimainkan dalam golf ini. Algoritma ini didasarkan pada melacak matriks adjacency, tetapi mewakili matriks kosong tanpa harus memperlakukannya secara khusus membuat saya sakit kepala.

Uji di sini.

Input adalah larik gaya 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]

Anda dapat menggunakan test harness ini untuk menjalankan semua tes:

"[]
[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}/
Martin Ender
sumber
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)

Ini mungkin masih bisa banyak golf.

Saya menggunakan kamus g untuk mewakili grafik. Node diberi label oleh angka, dan mereka memetakan ke set node yang berdekatan. Ini berarti bahwa setiap pembaruan tepi perlu dieksekusi di kedua titik akhir.

Indeks simpul baru dibuat dengan menghitung n. Setiap kali, saya membuat simpul kosong baru n. Untuk perintah 0, tetap saja. Untuk perintah 1, terhubung ke setiap node lain melalui g[i]^={n};g[n]^={i}; menggunakan xor make-nya sehingga node tidak terhubung dengan dirinya sendiri. Untuk perintah> 1, segera dihapus.

Pemfilteran node-node yang derajatnya adalah kelipatan dilakukan dengan pertama-tama menemukan node-node yang tetap ( h), kemudian anddengan daftar node-node dan tetangga-tetangga dari masing-masing node.

Akhirnya, jumlah entri dalam kamus grafik adalah jawabannya.

Tidak
sumber
0

Mathematica, 223 byte

Wow, ini ternyata lebih lama dari yang saya harapkan.

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)&

Pemakaian:

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

Berikut adalah hasil dari kasus uji:

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}

Kurang golf:

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]
   ) &

Cara kerjanya adalah dengan menampilkan grafik sebagai daftar "daftar tetangga".
Untuk arahan 0 , saya hanya menambahkan daftar kosong.
Untuk arahan 1 , saya menambahkan daftar semua node sebelumnya, dan menambahkan node baru ke semua node sebelumnya.
Untuk arahan > 1 , saya menghapus node yang ditentukan dan memperbarui sisanya.

kukac67
sumber