Costruisci un grafico


15

In questa sfida, il tuo compito è costruire un grafico non orientato da una sequenza di direttive. Esiste una direttiva per ogni numero intero non negativo e ognuno trasforma un dato grafico in uno nuovo.

  • Direttiva 0: aggiungere un nuovo nodo disconnesso.
  • Direttiva 1: aggiungere un nuovo nodo e collegarlo a ogni nodo esistente.
  • Direttiva m > 1: rimuovere tutti i nodi il cui grado (numero di vicini) è divisibile per m. Nota che 0è divisibile per tutti m, quindi i nodi disconnessi vengono sempre rimossi.

Le direttive vengono applicate una ad una, da sinistra a destra, a partire dal grafico vuoto. Ad esempio, la sequenza [0,1,0,1,0,1,3]viene elaborata come segue, spiegata usando la straordinaria arte ASCII. Iniziamo con il grafico vuoto e aggiungiamo un singolo vertice come diretto da 0:

a

Quindi, aggiungi un altro vertice e collegalo al primo, come indicato da 1:

a--b

Aggiungiamo un altro vertice disconnesso e poi uno collegato, come indicato da 0e 1:

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

Lo ripetiamo ancora una volta, come indicato da 0e 1:

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

Infine, rimuoviamo i vertici di grado 3 ae b, come indicato da 3:

f--e
|\
| c
|/
d

Questo è il grafico definito dalla sequenza [0,1,0,1,0,1,3].

Ingresso

Un elenco di numeri interi non negativi, che rappresentano una sequenza di direttive.

Produzione

Il numero di nodi nel grafico definito dalla sequenza.

Casi test

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

Regole dettagliate

È possibile scrivere una funzione o un programma completo. Vince il conteggio dei byte più corto. Le scappatoie standard non sono ammesse. Spiega l'algoritmo nella tua risposta.


È passata una settimana, quindi ho accettato la risposta più breve. Se ne arriva uno ancora più corto, aggiornerò la mia scelta. Una menzione d'onore va alla risposta di Peter Taylor , su cui si basavano molti altri, incluso il vincitore.


5
Mentre leggo la domanda, pensando che devi effettivamente disegnare il grafico - Questo è super duro , scorre verso il basso - oh
Ottimizzatore,

@Optimizer Sì, volevo porre la domanda in modo che la rappresentazione effettiva del grafico non fosse importante e la principale difficoltà risiedesse nell'attuazione delle direttive. Il numero di nodi è solo un modo semplice per verificare la correttezza.
Zgarb,

1
Mi piace molto questa sfida! È come progettare una struttura di dati. Devi capire come rappresentare il grafico perché i formati di input e output non sono legati ad esso.
xnor

Risposte:


4

Pyth , 37 31

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

Questa soluzione utilizza una funzione di riduzione ( u) per creare un elenco, in cui ogni voce corrisponde a un nodo rimanente nell'elenco e il valore della voce corrisponde al fatto che il nodo sia stato originariamente aggiunto ai sensi della direttiva 0 o 1.

Gè la variabile accumulatore nella funzione di riduzione e contiene l'elenco di cui sopra. Esso viene inizializzato alla lista vuota, Y.

Hprende il valore di ciascun membro di Q, l'input, uno per uno. Il risultato dell'espressione viene assegnato Gogni volta e Qviene assegnata la voce successiva di H, e l'espressione viene rieseguita.

Per un Gcorretto aggiornamento , esistono due possibilità, una per la direttiva 0 o 1 e una per le altre direttive. Questi casi si distinguono con il ternario? ... <H2 ...

Se Hè 0 o 1, quindi tutto quello che dobbiamo fare è append Ha G. +GHcompie questo.

Altrimenti, la prima cosa che è necessaria è determinare, per ogni nodo nel grafico, quanti vicini ha. Ciò si ottiene in due passaggi:

Innanzitutto, s>GTconta il numero di nodi sul o dopo il nodo di input che sono 1s. Questi sono tutti collegati al nodo di input, tranne per il fatto che conterremo oltre 1 se il nodo di input è 1.

In secondo luogo, abbiamo bisogno del numero di nodi precedenti al nodo di input a cui sono collegati. Questo è 0 se il nodo di input è 0 e l'indice del nodo di input T, se il nodo di input è 1. Questo valore sarebbe dato da *@GTT. Tuttavia, esiste ancora il conteggio in eccesso della prima sezione che deve essere corretto. Pertanto, calcoliamo *@GTtTinvece, che è 1 in meno se il nodo di input è un 1. Questi valori sono sommati, per fornire il numero di nodi collegati al nodo di input.

% ... Hdarà 0 è quel numero è divisibile per H, e quindi dovrebbe essere rimosso, e non darà 0 altrimenti.

f ... UGfornirà quindi gli indici dell'input che non devono essere rimossi, poiché fè un filtro e 0 è errato.

m@Gd converte questi indici negli 0 e 1 dei nodi corrispondenti.

Infine, una volta trovato l'elenco risultante di nodi etichettati 0 e 1, la sua lunghezza viene calcolata ( l) e stampata (implicita).

Grande idea grazie a @PeterTaylor.


12

GolfScript (53 byte)

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

Demo online

In realtà non l'ho ancora giocato a golf, ma ho scoperto che non è molto facile eliminare le variabili He Tquindi questo potrebbe essere un minimo locale.

Accetta input su stdin nel formato [0 1 2 3]. Lascia l'output su stdout.

Ungolfed:

])~{
  :^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 byte

Soluzione basata sull'algoritmo di Peter:

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

Seguirà l'espansione del codice.


Soluzione precedente (61 byte):

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

Prende input da STDIN come:

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

L'output è il numero su STDOUT:

8

Algoritmo :

  • Mantenere una variabile incrementale Uche memorizza l'id del nodo da aggiungere.
  • Mantenere un elenco di elenchi in cui ogni elenco è un nodo con un ID univoco costituito dal primo elemento dell'elenco e gli elementi rimanenti sono gli ID dei nodi connessi.
  • In ogni iterazione (durante la lettura delle direttive di input),
    • Se la direttiva è 0, aggiungere [U]a un elenco di elenco
    • Se la direttiva è 1, aggiungi Ua ciascun elenco nell'elenco di elenchi e aggiungi un altro elenco composto dal primo elemento di ciascun elenco di elenchi eU
    • Per rimuovere la direttiva, filtrare tutti gli elenchi di length - 1divisibili per me continuo a notare il primo elemento di tali elenchi. Dopo aver filtrato, rimuovo tutti gli ID rimossi dall'elenco rimanente di ID.

Espansione del codice :

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

Provalo qui


3

Pyth, 88 80 75 caratteri

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

Ho finito. Forse qualcun altro ha alcuni consigli sul golf.

Yè l'elenco di adiacenza del grafico. Per motivi di golf, mantengo anche un nodo in questo elenco, anche dopo che il nodo è stato eliminato (altrimenti dovrei aggiornare tutti gli indici). Ogni nodo ha se stesso come vicino. L'elenco Jtiene traccia dei nodi eliminati.

Mostro le modifiche dell'elenco di adiacenza sull'input di esempio [0,1,0,1,0,1,3]:

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

L'algoritmo quindi è piuttosto semplice: scorrere su tutti gli input, se input == 0: aggiungere un nuovo nodo con se stesso come vicino, se input == 1: aggiungere un nuovo nodo con tutti i nodi come vicini (anche quelli eliminati) e aggiungere questo nodo all'elenco di adiacenza di tutti i nodi, se input> 1: determinare i nodi con # neighbour-1% input == 0 e aggiungerli J, in ogni caso, aggiornare i vicini di ciascun nodo usando J. Alla fine stampa la lunghezza di Ymeno la lunghezza di (il set di) 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))

uso

Basta chiamare lo script e dare come input [0,1,0,1,0,1,3]o qualche altro test-case.


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)

A ciascun nodo viene assegnato un ID univoco e vengono registrati gli ID vicini di ciascun nodo. Quando la direttiva è 0, viene aggiunto un elenco di vicini vuoto per il nuovo nodo. Quando la direttiva è 1, gli ID di tutti i nodi esistenti diventano l'elenco vicino per il nuovo nodo e tutti gli altri elenchi vicini vengono aggiornati per includere il nuovo ID nodo. Per m> 1, i nodi con elenchi adiacenti che sono multipli di m vengono rimossi dall'elenco dei nodi e da tutti gli elenchi adiacenti. Grazie a @Optimizer per aver rilevato un bug in una versione precedente.


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

L'implementazione è semplice, leggendo ogni simbolo e facendo l'azione appropriata.

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

È possibile eseguire dalla riga di comando come f[0 0 1 1 0 0 1 1 2 5 7 0 1].


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}

Questo definisce una funzione chiamata Gusando la sintassi stabby-lambda. Utilizzare G[[0, 1]]per chiamarlo con comandi 0e 1.

L'implementazione è piuttosto semplice: esiste una Nodestruttura (chiamata Nsopra) che contiene riferimenti a tutti i nodi collegati tramite la lproprietà. Gcrea nodi secondo necessità e manipola i loro collegamenti. Una versione leggibile è disponibile qui .


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=,

C'è ancora molto da giocare in questo. L'algoritmo si basa sul tenere traccia della matrice di adiacenza, ma rappresentare la matrice vuota senza doverla trattare in modo particolare mi dà mal di testa.

Provalo qui.

L'input è un array in stile 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]

È possibile utilizzare questo cablaggio di prova per eseguire tutti i test:

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

Probabilmente questo può ancora essere giocato molto.

Ho usato un dizionario g per rappresentare il grafico. I nodi sono etichettati da numeri e si associano all'insieme di nodi adiacenti. Ciò significa che ogni aggiornamento di un bordo deve essere eseguito su entrambi i suoi endpoint.

Gli indici dei nodi freschi vengono creati contando n. Ogni volta, creo un nuovo nodo vuoto n. Per comando 0, rimane solo. Per il comando 1, è collegato all'altro nodo tramite g[i]^={n};g[n]^={i}; usando xor si fa in modo che il nodo non sia connesso a se stesso. Per i comandi> 1, viene immediatamente eliminato.

Il filtraggio dei nodi il cui grado è un multiplo viene effettuato prima trovando i nodi che restano ( h), quindi andinserendolo con l'elenco dei nodi e dei vicini di ciascun nodo.

Infine, il numero di voci nel dizionario grafico è la risposta.


0

Mathematica, 223 byte

Wow, questo è risultato più lungo di quanto mi aspettassi.

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

Uso:

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

Ecco i risultati dei casi di test:

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}

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

Il modo in cui funziona è rappresentando il grafico come elenco di "elenchi di vicini".
Per la direttiva 0 , ho appena aggiunto un elenco vuoto.
Per la direttiva 1 , aggiungo un elenco di tutti i nodi precedenti e aggiungo il nuovo nodo a tutti i nodi precedenti.
Per una direttiva > 1 , ho rimosso i nodi specificati e ho aggiornato il resto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.