Construire un graphique

15

Dans ce défi, votre tâche consiste à construire un graphe non orienté à partir d'une séquence de directives. Il existe une directive pour chaque entier non négatif, et chacune transforme un graphique donné en un nouveau.

  • Directive 0: ajoutez un nouveau nœud déconnecté.
  • Directive 1: ajoutez un nouveau nœud et connectez-le à chaque nœud existant.
  • Directive m > 1: Supprimez tous les nœuds dont le degré (nombre de voisins) est divisible par m. Notez que cela 0est divisible par tous m, donc les nœuds déconnectés sont toujours supprimés.

Les directives sont appliquées une par une, de gauche à droite, en commençant par le graphique vide. Par exemple, la séquence [0,1,0,1,0,1,3]est traitée comme suit, expliquée à l'aide d'un superbe art ASCII. Nous commençons avec le graphique vide et ajoutons un seul sommet comme indiqué par 0:

a

Ensuite, ajoutez un autre sommet et connectez-le au premier, comme indiqué par 1:

a--b

Nous ajoutons un autre sommet déconnecté puis un sommet connecté, comme indiqué par 0et 1:

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

Nous répétons cette fois encore, comme dirigé par 0et 1:

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

Enfin, nous supprimons les sommets de degré 3 aet b, comme indiqué par 3:

f--e
|\
| c
|/
d

Il s'agit du graphique défini par la séquence [0,1,0,1,0,1,3].

Contribution

Une liste d'entiers non négatifs, représentant une séquence de directives.

Production

Le nombre de nœuds dans le graphique défini par la séquence.

Cas de 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

Règles détaillées

Vous pouvez écrire une fonction ou un programme complet. Le nombre d'octets le plus court gagne. Les failles standard ne sont pas autorisées. Veuillez expliquer votre algorithme dans votre réponse.


Cela fait une semaine, j'ai donc accepté la réponse la plus courte. Si une version encore plus courte arrive plus tard, je mettrai à jour mon choix. Une mention honorable va à la réponse de Peter Taylor , sur laquelle plusieurs autres étaient basés, y compris le gagnant.

Zgarb
la source
5
En lisant la question, en pensant que vous devez réellement dessiner le graphique - C'est super difficile , défile vers le bas - oh
Optimizer
@Optimizer Oui, je voulais poser la question pour que la représentation réelle du graphique ne soit pas importante, et la principale difficulté résiderait dans la mise en œuvre des directives. Le nombre de nœuds n'est qu'un moyen simple de vérifier l'exactitude.
Zgarb
1
J'aime vraiment ce défi! C'est comme concevoir une structure de données. Vous devez comprendre comment représenter le graphique car les formats d'entrée et de sortie ne lui sont pas liés.
xnor

Réponses:

4

Pyth , 37 31

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

Cette solution utilise une fonction de réduction ( u) pour créer une liste, où chaque entrée correspond à un nœud restant dans la liste, et la valeur de l'entrée correspondant à si le nœud a été initialement ajouté en vertu de la directive 0 ou 1.

Gest la variable d'accumulateur dans la fonction de réduction et contient la liste susmentionnée. Il est initialisé à la liste vide, Y.

Hprend la valeur de chaque membre de Q, l'entrée, un par un. Le résultat de l'expression est affecté à Gchaque fois, l'entrée suivante de Qest affectée à Het l'expression est réexécutée.

Pour une mise à jour Gcorrecte, il existe deux possibilités, une pour la directive 0 ou 1 et une pour les autres directives. Ces cas se distinguent avec le ternaire? ... <H2 ...

Si Hest 0 ou 1, alors tout ce que nous devons faire est append Hà G. +GHaccomplit cela.

Sinon, la première chose qui est nécessaire est de déterminer, pour chaque nœud du graphique, combien de voisins il a. Cela se fait en deux étapes:

Tout d'abord, s>GTcompte le nombre de nœuds au niveau ou après le nœud d'entrée qui sont 1s. Ceux-ci sont tous connectés au nœud d'entrée, sauf que nous comptons plus que 1 si le nœud d'entrée est un 1.

Deuxièmement, nous avons besoin du nombre de nœuds avant le nœud d'entrée qui lui sont connectés. Il s'agit de 0 si le nœud d'entrée est un 0, et l'indice du nœud d'entrée,, Tsi le nœud d'entrée est un 1. Cette valeur serait donnée par *@GTT. Cependant, il reste le dépassement de la première section qui doit être corrigé. Ainsi, nous calculons à la *@GTtTplace, qui est 1 de moins si le nœud d'entrée est un 1. Ces valeurs sont additionnées, pour donner le nombre de nœuds connectés au nœud d'entrée.

% ... Hdonnera 0 est ce nombre est divisible par H, et doit donc être supprimé, et ne donnera pas 0 sinon.

f ... UGdonnera donc les indices de l'entrée qui ne doivent pas être supprimés, car fest un filtre, et 0 est faux.

m@Gd convertit ces indices en 0 et 1 des nœuds correspondants.

Enfin, une fois que la liste résultante des nœuds étiquetés 0 et 1 est trouvée, sa longueur est calculée (l ) et imprimée (implicite).

Idée large grâce à @PeterTaylor.

isaacg
la source
12

GolfScript (53 octets)

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

Démo en ligne

Je n'ai pas encore joué au golf, mais j'ai découvert qu'il n'est pas très facile d'éliminer le HetT variables donc cela pourrait être un minimum local.

Prend entrée sur stdin au format [0 1 2 3] . Laisse la sortie sur la sortie standard.

Non golfé:

])~{
  :^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
la source
4

CJam, 129 75 73 68 61 46 42 octets

Solution basée sur l'algorithme de Peter:

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

Expansion du code à suivre.


Solution précédente (61 octets):

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

Prend l'entrée de STDIN comme:

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

La sortie est le nombre sur STDOUT:

8

Algorithme :

  • Conserver une variable d'incrémentation U qui stocke l'ID du nœud à ajouter.
  • Maintenir une liste de liste dans laquelle, chaque liste est un nœud avec un identifiant unique constitué par le premier élément de la liste et les éléments restants étant les identifiants des nœuds connectés.
  • À chaque itération (lors de la lecture des directives d'entrée),
    • Si la directive est 0, ajoutez[U] à une liste de liste
    • Si la directive est 1, ajoutez Uà chaque liste dans la liste de liste et ajoutez une autre liste composée du premier élément de chacune de la liste de liste etU
    • Pour supprimer la directive, je filtre toutes les listes de length - 1divisible par met je continue de noter le premier élément de ces listes. Après le filtrage, je supprime tous les identifiants supprimés de la liste restante des identifiants.

Expansion du code :

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

Essayez-le ici

Optimiseur
la source
3

Pyth, 88 80 75 caractères

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

J'ai fini. Peut-être que quelqu'un d'autre a des conseils sur le golf.

Yest la liste d'adjacence du graphe. Pour des raisons de golf, je garde également un nœud dans cette liste, même après la suppression du nœud (sinon je devrais mettre à jour tous les index). Chaque nœud a lui-même comme voisin. La liste Jconserve la trace des nœuds supprimés.

Je montre les changements de la liste d'adjacence sur l'exemple d'entrée [0,1,0,1,0,1,3] :

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

L'algorithme est alors assez simple: itérer sur toutes les entrées, si entrée == 0: ajouter un nouveau nœud avec lui-même comme voisin, si entrée == 1: ajouter un nouveau nœud avec tous les nœuds comme voisins (également les supprimés) et ajouter ce nœud à la liste d'adjacence de tous les nœuds, si entrée> 1: déterminez les nœuds avec # voisin-1% entrée == 0 et ajoutez-les pour J, dans chaque cas, mettre à jour les voisins de chaque nœud en utilisant J. À la fin, imprimez la longueur de Ymoins la longueur de (l'ensemble de) 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))

Usage

Appelez simplement le script et donnez comme entrée [0,1,0,1,0,1,3]ou un autre cas de test.

Jakube
la source
3

APL, 71 65 55 caractères

{⍬≡⍺:≢⍵⋄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,⍵}

Le graphique est représenté comme une matrice de contiguïté booléenne. Des lignes / colonnes sont ajoutées et supprimées si nécessaire.

ngn
la source
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)

Chaque nœud reçoit un identifiant unique et les identifiants voisins de chaque nœud sont enregistrés. Lorsque la directive vaut 0, une liste de voisins vide est ajoutée pour le nouveau nœud. Lorsque la directive est 1, les identifiants de tous les nœuds existants deviennent la liste de voisins du nouveau nœud et toutes les autres listes de voisins sont mises à jour pour inclure le nouvel identifiant de nœud. Pour m> 1, les nœuds dont les listes de voisins sont multiples de m sont supprimés de la liste des nœuds et de toutes les listes de voisins. Merci à @Optimizer d'avoir attrapé un bogue dans une version antérieure.

user2487951
la source
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

La mise en œuvre est simple, lisant chaque symbole et effectuant l'action appropriée.

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

Vous pouvez exécuter à partir de la ligne de commande en tant que f[0 0 1 1 0 0 1 1 2 5 7 0 1].

Ypnypn
la source
2

Ruby 159157 ( démo )

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}

Ceci définit une fonction appelée à l' Gaide de la syntaxe stabby-lambda. UtilisationG[[0, 1]] pour l'appeler avec les commandes 0et 1.

L'implémentation est assez simple: il existe une Nodestructure (appelée Nci-dessus) qui contient des références à tous les nœuds liés via la lpropriété. Gcrée des nœuds au besoin et manipule leurs liens. Une version lisible est disponible ici .

Cristian Lupascu
la source
1

CJam, 99 97 octets

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

Il y a encore beaucoup à jouer dans ce domaine. L'algorithme est basé sur le suivi de la matrice d'adjacence, mais représenter la matrice vide sans avoir à la traiter spécialement me donne des maux de tête.

Testez-le ici.

L'entrée est un tableau de style 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]

Vous pouvez utiliser ce faisceau de tests pour exécuter tous les tests:

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

Cela peut probablement encore être joué beaucoup.

J'ai utilisé un dictionnaire g pour représenter le graphique. Les nœuds sont étiquetés par des nombres et ils sont mappés à l'ensemble de nœuds adjacents. Cela signifie que chaque mise à jour d'un front doit être exécutée sur ses deux points de terminaison.

De nouveaux indices de nœuds sont créés en comptant n. Chaque fois, je crée un nouveau nœud vide n. Pour le commandement 0, il reste juste. Pour la commande 1, il est connecté à chaque autre nœud viag[i]^={n};g[n]^={i} ; utiliser xor fait en sorte que le nœud ne soit pas connecté à lui-même. Pour les commandes> 1, il est immédiatement supprimé.

Le filtrage des nœuds dont le degré est multiple se fait en trouvant d'abord les nœuds qui restent ( h), puisand intégrant avec la liste des nœuds et les voisins de chaque nœud.

Enfin, le nombre d'entrées dans le dictionnaire graphique est la réponse.

xnor
la source
0

Mathematica, 223 octets

Wow, cela s'est avéré plus long que prévu.

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

Usage:

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

Voici les résultats des cas de 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}

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

La façon dont cela fonctionne consiste à représenter le graphique comme une liste de "listes de voisins".
Pour la directive 0 , j'ajoute simplement une liste vide.
Pour la directive 1 , j'ajoute une liste de tous les nœuds précédents et j'ajoute le nouveau nœud à tous les nœuds précédents.
Pour une directive > 1 , j'ai supprimé les nœuds spécifiés et mis à jour le reste.

kukac67
la source