Побудуйте графік


15

У цьому виклику ваше завдання - побудувати непрямий графік із послідовності директив. Для кожного негативного цілого числа існує одна директива, і кожна перетворює заданий графік у новий.

  • Директива 0: Додайте новий відключений вузол.
  • Директива 1: Додайте новий вузол і підключіть його до кожного існуючого вузла.
  • Директива m > 1: Видаліть усі вузли, ступінь яких (кількість сусідів) ділиться на m. Зверніть увагу, що 0всі mподіляються, тому відключені вузли завжди видаляються.

Директиви застосовуються по черзі зліва направо, починаючи з порожнього графіка. Наприклад, послідовність [0,1,0,1,0,1,3]обробляється наступним чином, пояснюється за допомогою чудового мистецтва ASCII. Почнемо з порожнього графа і додаємо одну вершину, як вказано 0:

a

Потім додайте іншу вершину і підключіть її до першої, як вказує 1:

a--b

Додаємо ще одну відключену вершину, а потім підключену, як вказує 0та 1:

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

Повторюємо це ще раз, як вказує 0та 1:

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

Нарешті, ми видаляємо вершини 3 ступеня aі b, як вказує 3:

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

Детальні правила

Ви можете написати функцію або повну програму. Виграє найкоротший байт. Стандартні лазівки заборонені. Поясніть, будь ласка, свій алгоритм у відповіді.


Минув тиждень, тому я прийняв найкоротшу відповідь. Якщо пізніше з’явиться ще коротша, я обновлю свій вибір. Почесна згадка стосується відповіді Пітера Тейлора , на якій базувалося кілька інших, зокрема переможець.


5
Коли я читаю питання, думаючи, що вам потрібно насправді намалювати графік - Це супер важко , прокручується вниз - о
Оптимізатор

@Optimizer Так, я хотів поставити питання, щоб фактичне представлення графіка не було важливим, а основна складність полягала б у виконанні директив. Кількість вузлів - це просто простий спосіб перевірити правильність.
Згарб

1
Мені дуже подобається цей виклик! Це як проектування структури даних. Ви повинні з'ясувати, як представити графік, оскільки формати введення та виведення не прив'язані до нього.
xnor

Відповіді:


4

Піта , 37 31

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

Це рішення використовує функцію зменшення ( u) для складання списку, де кожному запису відповідає вузол, що залишився у списку, і значення запису, що відповідає тому, чи був вузол спочатку доданий відповідно до директив 0 або 1.

Gє змінною акумулятора у функції зменшення і містить вищезгаданий список. Він инициализируется порожнім списком Y.

Hприймає значення кожного члена Q, вхідного, по одному. Результат виразу присвоюється Gкожному разу, а наступний запис Qпозначається H, і вираз повторюється.

Щоб Gправильно оновити , є дві можливості: одна для директив 0 або 1 та одна для інших директив. Ці випадки розрізняють з трійкою? ... <H2 ...

Якщо H це 0 або 1, то все , що нам потрібно зробити , це Append Hдо G. +GHвиконує це.

В іншому випадку, перше, що потрібно, це визначити для кожного вузла в графіку, скільки у нього сусідів. Це здійснюється в два етапи:

По-перше, s>GTпідраховує кількість вузлів на вхідному вузлі або після нього, який дорівнює 1s. Усі вони підключені до вхідного вузла, за винятком того, що ми перерахуємо кількість на 1, якщо вхідний вузол - 1.

По-друге, нам потрібна кількість вузлів раніше, ніж вхідний вузол, який підключений до нього. Це 0, якщо вузол входу 0, а індекс вхідного вузла T, якщо вузол входу дорівнює 1. Це значення буде задано *@GTT. Однак у першому розділі все ще є кількість перерахунків, яку потрібно виправити. Таким чином, ми обчислюємо *@GTtTнатомість, що на 1 менше, якщо вузол введення дорівнює 1. Ці значення підсумовуються, щоб дати кількість вузлів, підключених до вхідного вузла.

% ... Hдасть 0, це число ділиться на H, і, таким чином, його слід видалити, а не дасть 0 в іншому випадку.

f ... UG таким чином, дадуть показники вхідних даних, які не слід вилучати, оскільки f це фільтр, а 0 - помилковий.

m@Gd перетворює ці індекси на 0s та 1s відповідних вузлів.

Нарешті, після виявлення результативного списку вузлів, позначених 0 та 1, обчислюється його довжина (l ) та друкується (неявно).

Широка ідея завдяки @PeterTaylor.


12

GolfScript (53 байти)

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

Демонстрація в Інтернеті

Я ще не займався цим гольфом, але я виявив, що усунути HтаT змінні не так просто, тому це може бути локальним мінімумом.

Здійснює введення на stdin у форматі [0 1 2 3]. Залишає вихід на stdout.

Безголівки:

])~{
  :^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яка зберігає ідентифікатор вузла, який потрібно додати.
  • Підтримуйте список списку, в якому кожен список - це вузол з унікальним ідентифікатором, складеним першим елементом списку, а решта елементів - ідентифікаторами підключених вузлів.
  • У кожній ітерації (читаючи вхідні директиви),
    • Якщо директива є 0, додайте [U]до списку список
    • Якщо директива є 1, додайте Uдо кожного списку список і додайте інший список, що складається з першого елемента кожного списку списку таU
    • Щоб видалити директиву, я фільтрую всі списки, що length - 1поділяються, mі продовжую відзначати перший елемент цих списків. Після фільтрування я видаляю весь видалений ідентифікатор із залишку списку ідентифікаторів.

Розширення коду :

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

Піта, 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 Дж = []
вхід 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]

Алгоритм тоді досить простий: повторити всі входи, якщо введення == 0: додати новий вузол із собою як сусід, якщо вхід == 1: додати новий вузол з усіма вузлами як сусідів (також видалені) та додати цей вузол до списку суміжності всіх вузлів, якщо вхід> 1: визначте вузли за допомогою # сусіда-1% введення == 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

Пітон 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)

Кожному вузлу надається унікальний ідентифікатор і записуються сусідські ідентифікатори кожного вузла. Коли директива дорівнює 0, для нового вузла додається порожній список сусідів. Коли директива дорівнює 1, ідентифікатори всіх існуючих вузлів стають списком сусідів для нового вузла, а всі інші списки сусідів оновлюються, включаючи новий ідентифікатор вузла. Для 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}

Це визначає функцію, яка називається Gза допомогою синтаксису стаб-лямбда. Використовуйте 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

Пітон 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. Для команди 0це просто залишається. Для команди 1він з'єднаний між собою вузлом черезg[i]^={n};g[n]^={i} ; за допомогою xor зробіть це так, що вузол не підключений до себе. Для команд> 1 вона негайно видаляється.

Фільтрація вузлів, ступінь яких кратна, здійснюється спочатку пошуку вузлів, які залишаються ( h), потімand з використанням списку вузлів та сусідів кожного вузла.

Нарешті, кількість записів у графічному словнику є відповіддю.


0

Математика, 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 я видалив вказані вузли та оновив решту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.