Dado un árbol genera su código de Prüfer


10

En un código Prüfer es una secuencia única de enteros que denota un árbol específico.

Puede encontrar el código Prüfer de un árbol con el siguiente algoritmo tomado de Wikipedia:

Considere un árbol etiquetado T con vértices {1, 2, ..., n}. En el paso i , retire la hoja con la etiqueta más pequeña y configure el elemento i de la secuencia de Prüfer para que sea la etiqueta del vecino de esta hoja.

(Tenga en cuenta que, dado que es una hoja, solo tendrá un vecino).

Debe detener la iteración cuando solo quedan dos vértices en el gráfico.

Tarea

Dado un árbol etiquetado como entrada, salida, su código Prüfer. Puede tomar aportes de cualquier manera razonable. Como una matriz de adyacencia o la representación gráfica de sus idiomas. ( No puede tomar la entrada como un código Prüfer ).

Este es el por lo que debe intentar minimizar los bytes en su fuente.

Casos de prueba

Aquí hay algunas entradas en ASCII con sus salidas a continuación. No necesita admitir entradas ASCII como esta.

    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}

¿Podemos tomar un árbol enraizado como entrada?
xnor

¿Podemos tomar la entrada como algo [[2,1],[2,3],[2,5],[2,4,6]]para el primer caso? (es decir, cada rama)
HyperNeutrino

@xnor Sí puedes
Ad Hoc Garf Hunter

1
Siento que tomar una entrada con bordes o caminos dirigidos hacia una raíz es una precomputación hacia el Código Prüfer. De cualquier manera, creo que debería ser más claro en "Puede tomar información de manera razonable (no puede tomar información como un código Prüfer)".
xnor

@xnor Oh, no entendí lo que Hyper Neutrino estaba preguntando.
Ad Hoc Garf Hunter

Respuestas:


9

Mathematica, 34 bytes

<<Combinatorica`
LabeledTreeToCode

Alguien tuvo que hacerlo ...

Después de cargar el Combinatoricapaquete, la función LabeledTreeToCodeespera una entrada de árbol como un gráfico no dirigido con bordes y vértices explícitamente listados; por ejemplo, la entrada en el segundo caso de prueba podría ser Graph[{{{1, 4}}, {{4, 3}}, {{4, 2}}, {{2, 5}}, {{2, 6}}, {{6, 7}}, {{5, 8}}}, {1, 2, 3, 4, 5, 6, 7, 8}].


55
Por supuesto, hay una función integrada para hacer esto. > _>
HyperNeutrino

4

Python 3, 136 131 127 bytes

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)

Toma datos como una matriz de adyacencia. Primer ejemplo:

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

bueno, fallé ...
HyperNeutrino

@HyperNeutrino ¡Fuiste aproximadamente 4 segundos más rápido!
L3viathan

Jeje sí! ¡Y unas 2,7 veces más! : D gg
HyperNeutrino

1
delexiste? > _>
HyperNeutrino

1
@WheatWizard Tienes razón sobre los puntos y comas, pero mezclar pestañas y espacios es un error en Python 3.
L3viathan

2

Jalea , 31 bytes

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

Un enlace monádico que toma una lista de pares de nodos (que definen los bordes) en cualquier orden (y cada uno en cualquier orientación) y devuelve el Código Prüfer como una lista.

Pruébalo en línea!

¿Cómo?

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 bytes

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

Pruébalo en línea!

Explicación

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

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

Requiere que la entrada sea un mapa hash, que tenga etiquetas "en forma de hoja" como claves y etiquetas "en forma de raíz" como valores. Por ejemplo:

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

En cada iteración encuentra la clave más pequeña a la que ningún otro nodo hace referencia, la agrega al resultado ry elimina el nodo de la definición del gráfico G. if-letva al caso más cuando Gestá vacío, como firstdevuelve nil. También se debe descartar el último elemento.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.