Étant donné un arbre générer son code Prüfer


10

En un code Prüfer est une séquence unique d'entiers qui dénote un arbre spécifique.

Vous pouvez trouver le code Prüfer d'un arbre avec l'algorithme suivant tiré de Wikipedia:

Considérons un arbre étiqueté T avec des sommets {1, 2, ..., n}. À l'étape i , retirez la feuille avec la plus petite étiquette et définissez le i ème élément de la séquence Prüfer comme étant l'étiquette du voisin de cette feuille.

(Notez que puisque c'est une feuille, elle n'aura qu'un seul voisin).

Vous devez arrêter l'itération lorsqu'il ne reste que deux sommets dans le graphique.

Tâche

Étant donné une arborescence étiquetée en sortie, son code Prüfer. Vous pouvez prendre connaissance de toute manière raisonnable. Comme une matrice d'adjacence ou la représentation graphique de votre langage intégré. ( Vous ne pouvez pas prendre la saisie comme un code Prüfer ).

Il s'agit de , vous devez donc viser à minimiser les octets dans votre source.

Cas de test

Voici quelques entrées en ASCII avec leurs sorties ci-dessous. Vous n'avez pas besoin de prendre en charge l'entrée ASCII comme ceci.

    3
    |
1---2---4---6
    |
    5

{2,2,2,4}

1---4---3
    |
5---2---6---7
|
8

{4,4,2,6,2,5}

5---1---4   6
    |       |
    2---7---3

{1,1,2,7,3}

Pouvons-nous prendre un arbre enraciné en entrée?
xnor

Pouvons-nous considérer l'entrée comme quelque chose comme [[2,1],[2,3],[2,5],[2,4,6]]dans le premier cas? (c'est-à-dire chaque branche)
HyperNeutrino

@xnor Oui, vous pouvez
Ad Hoc Garf Hunter

1
J'ai l'impression que prendre une entrée avec des bords ou des chemins dirigés vers une racine est un précalcul vers le code Prüfer. Quoi qu'il en soit, je pense que vous devriez être plus clair sur "Vous pouvez prendre les entrées de manière raisonnable (vous ne pouvez pas prendre les entrées comme un code Prüfer)."
xnor

@xnor Oh, je ne comprenais pas ce que demandait Hyper Neutrino.
Ad Hoc Garf Hunter

Réponses:


9

Mathematica, 34 octets

<<Combinatorica`
LabeledTreeToCode

Quelqu'un devait le faire....

Après avoir chargé le Combinatoricapackage, la fonction LabeledTreeToCodeattend une entrée d'arbre sous forme de graphique non orienté avec des arêtes et des sommets explicitement répertoriés; par exemple, l'entrée dans le deuxième cas de test pourrait être Graph[{{{1, 4}}, {{4, 3}}, {{4, 2}}, {{2, 5}}, {{2, 6}}, {{6, 7}}, {{5, 8}}}, {1, 2, 3, 4, 5, 6, 7, 8}].


5
Bien sûr, il y a une fonction intégrée pour ce faire. > _>
HyperNeutrino

4

Python 3, 136 131 127 127 octets

def f(t):
 while len(t)>2:
  m=min(x for x in t if len(t[x])<2);yield t[m][0];del t[m]
  for x in t:m in t[x]and t[x].remove(m)

Prend l'entrée comme une matrice d'adjacence. Premier exemple:

>>> [*f({1:[2],2:[1,3,4,5],3:[2],4:[2,6],5:[2],6:[4]})]
[2, 2, 2, 4]

eh bien j'ai échoué ...
HyperNeutrino

@HyperNeutrino Vous étiez environ 4 secondes plus rapide!
L3viathan

Hehe yup! Et environ 2,7 fois plus longtemps! : D gg
HyperNeutrino

1
delexiste? > _>
HyperNeutrino

1
@WheatWizard Vous avez raison sur les points-virgules, mais mélanger les tabulations et les espaces est une erreur dans Python 3.
L3viathan

2

Gelée , 31 octets

FĠLÞḢḢ
0ịµÇHĊṙ@µÇCịṪ,
WÇÐĿḢ€ṖṖḊ

Un lien monadique qui prend une liste de paires de nœuds (définissant les bords) dans n'importe quel ordre (et chacun dans n'importe quelle orientation) et renvoie le code Prüfer sous forme de liste.

Essayez-le en ligne!

Comment?

FĠLÞḢḢ - Link 1, find leaf location: list of edges (node pairs)
F      - flatten
 Ġ     - group indices by value (sorted smallest to largest by value)
  LÞ   - sort by length (stable sort, so equal lengths remain in prior order)
    ḢḢ - head head (get the first of the first group. If there are leaves this yields
       -   the index of the smallest leaf in the flattened version of the list of edges)

0ịµÇHĊṙ@µÇCịṪ, - Link 2, separate smallest leaf: list with last item a list of edges
0ị             - item at index zero - the list of edges
  µ            - monadic chain separation (call that g)
   Ç           - call last link (1) as a monad (index of smallest leaf if flattened)
    H          - halve
     Ċ         - ceiling (round up)
      ṙ@       - rotate g left by that amount (places the edge to remove at the right)
        µ      - monadic chain separation (call that h)
         Ç     - call last link (1) as a monad (again)
          C    - complement (1-x)
            Ṫ  - tail h (removes and yields the edge)
           ị   - index into, 1-based and modular (gets the other node of the edge)
             , - pair with the modified h
               -    (i.e. [otherNode, restOfTree], ready for the next iteration)

WÇÐĿḢ€ṖṖḊ - Main link: list of edges (node pairs)
W         - wrap in a list (this is so the first iteration works)
  ÐĿ      - loop and collect intermediate results until no more change:
 Ç        -   call last link (2) as a monad
    Ḣ€    - head €ach (get the otherNodes, although the original tree is also collected)
      ṖṖ  - discard the two last results (they are excess to requirements)
        Ḋ - discard the first result (the tree, leaving just the Prüfer Code)

1

05AB1E , 29 octets

[Dg#ÐD˜{γé¬`U\X.å©Ï`XK`ˆ®_Ï]¯

Essayez-le en ligne!

Explication

[Dg#                           # loop until only 1 link (2 vertices) remain
    ÐD                         # quadruple the current list of links
      ˜{                       # flatten and sort values
        γé                     # group by value and order by length of runs
          ¬`U                  # store the smallest leaf in X
             \X                # discard the sorted list and push X
               .å©             # check each link in the list if X is in that link
                  Ï`           # keep only that link
                    XK`ˆ       # add the value that isn't X to the global list
                        ®_Ï    # remove the handled link from the list of links
                           ]   # end loop
                            ¯  # output global list

1

Clojure, 111 octets

#(loop[r[]G %](if-let[i(first(sort(remove(set(vals G))(keys G))))](recur(conj r(G i))(dissoc G i))(butlast r)))

Nécessite que l'entrée soit une carte de hachage, ayant des étiquettes "en forme de feuille" comme clés et des étiquettes "en forme de racine" comme valeurs. Par exemple:

{1 2, 3 2, 5 2, 4 2, 6 4}
{1 4, 3 4, 4 2, 8 5, 5 2, 7 6, 6 2}

À chaque itération, il trouve la plus petite clé qui n'est référencée par aucun autre nœud, l'ajoute au résultat ret supprime le nœud de la définition du graphe G. if-letva dans le cas else quand Gest vide, comme firstretourne nil. Le dernier élément doit également être supprimé.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.