Encuentra el diámetro de un gráfico de palabras

12

Introducción

Un acertijo de palabras popular es convertir una palabra en otra a través de una serie de pasos que reemplazan solo una letra y que siempre resultan en una palabra válida. Por ejemplo, BAG se puede convertir a DOG a través de una ruta de cinco pasos:

BOLSA -> BAT -> CAT -> COT -> COG -> PERRO

También existen caminos más cortos en este caso; por ejemplo:

BOLSO -> BOG -> PERRO

Si uno dibujó un gráfico cuyos vértices fueron etiquetados por palabras, con un borde entre cualquier par de palabras que difieren en una letra, entonces la ruta más corta de "BOLSA" a "PERRO" consistiría en dos bordes.

Desafío

Debe escribir un programa que reciba como entrada un "diccionario" de palabras que tengan la misma longitud, que represente todas las palabras permitidas que pueden aparecer como pasos a lo largo de un camino. Debe generar al menos una "ruta más larga más corta", es decir, una ruta entre dos de las palabras que es:

  • no más que cualquier otro camino entre esas dos palabras;

  • al menos el mayor tiempo posible entre cualquier otro par de palabras en la lista.

En el contexto del gráfico descrito anteriormente, la longitud de dicha ruta es el diámetro del gráfico.

En el caso degenerado en el que ninguna de las palabras de entrada puede transformarse en ninguna de las otras, genera al menos una ruta de longitud cero, es decir, una sola palabra.

Ejemplos

  • La entrada ["bolsa", "murciélago", "gato", "cuna", "punto", "perro"] debería generar una ruta que atraviese las seis palabras en ese orden (u orden inverso), ya que la ruta más corta desde " la bolsa "to" dog "dentro de este diccionario es el más largo posible, cinco pasos

  • La entrada ["bolsa", "murciélago", "bot", "gato", "cuna", "punto", "perro"] debe proporcionar la ruta "bolsa, murciélago, bot, punto, perro" y / o su inversión.

  • La entrada ["código", "golf", "macho", "zumbido", "topo", "rol", "molde", "frío", "oro", "modo"] debería generar una ruta entre "código" y "golf".

  • La entrada ["uno", "dos", "seis", "diez"] corresponde a un gráfico sin bordes, por lo que genera una o más rutas de una sola palabra (longitud cero).

  • Si la entrada contiene dos palabras de longitud desigual, la salida no está definida.

Reglas

  • Aplican reglas estándar de golf de código
  • Habrá múltiples caminos "más cortos". Debe generar al menos uno, pero puede generar tantos como desee.
  • Usted es libre de decidir cómo se pasa el diccionario de entrada a su programa.
  • El código más corto en bytes gana.
jnfnt
fuente
3
¿Te importaría agregar algunos casos de prueba más?
Jonás
Hecho. También se agregó una discusión sobre el caso en el que el gráfico no contiene bordes.
jnfnt
¿Deberíamos aceptar una entrada vacía (la respuesta sería []o [[]])?
Erik the Outgolfer
Estoy feliz de que el comportamiento no esté definido en las entradas vacías.
jnfnt

Respuestas:

3

APL (Dyalog Classic) , 84 80 77 76 74 66 61 bytes

{⍵⌷⍨{⍵,⍨⊃⍋(1a⌷⍨⊃⍵),⍪⍺⌷a}⍣d/⊃⍸a=d←⌈/512|,a←⌊.+⍨⍣≡9*⍨2⌊⍵+.≠⍉⍵}

Pruébalo en línea!

entrada y salida son matrices de caracteres

⍵+.≠⍉⍵ matriz de distancias entre palabras similares a hamming

9*⍨2⌊deje 0s y 1s intactos, convierta 2+ en un número grande (512 = 2 9 , usado como "∞")

⌊.+⍨⍣≡ algoritmo de ruta más corta de floyd & warshall

  • ⌊.+como la multiplicación de matrices pero usando min( ) y en +lugar de +y ×respectivamente

  • usa la misma matriz a la izquierda y a la derecha

  • ⍣≡ repetir hasta la convergencia

d←⌈/512|, longitud de la ruta más larga (no "∞"), asignada a d

⊃⍸a=qué dos nodos conecta, llamémoslos i y j

{⍵,⍨⊃⍋(1≠a⌷⍨⊃⍵),⍪⍺⌷a}⍣d/ reconstruir el camino

  • { }⍣d/evaluar los tiempos de { }función d. el argumento izquierdo es siempre i . el argumento derecho comienza como j y gradualmente acumula los nodos internos de la ruta

  • (1≠a⌷⍨⊃⍵),⍪⍺⌷a construya una matriz de 2 columnas de estos dos vectores:

    • 1≠a⌷⍨⊃⍵ booleanos (0 o 1) que indican qué nodos están a distancia 1 al primero de

    • ⍺⌷a distancias de todos los nodos del gráfico a

  • ⊃⍋ índice de la fila lexicográficamente más pequeña

  • ⍵,⍨ anteponer a

⍵⌷⍨ indexar las palabras originales con la ruta

ngn
fuente
2

Python 3 , 225 bytes

from itertools import*
def f(a):b=[((p[0],p[-1]),(len(p),p))for i in range(len(a))for p in permutations(a,i+1)if all(sum(q!=r for q,r in zip(*x))<2for x in zip(p,p[1:]))];return max(min(r for q,r in b if x==q)for x,y in b)[1]

Pruébalo en línea!

Básicamente, tome todas las rutas posibles, solo mantenga las que sean válidas, luego revise cada combinación de inicio-fin, encuentre la distancia mínima de la ruta y encuentre la máxima de eso.

Hiperneutrino
fuente
1

JavaScript (ES6),  195  194 bytes

Las devoluciones [optimal_length, [optimal_path]].

f=(a,p=[],w=o=[],l=0)=>Object.values(o,o[k=[w,p[0]]]=(o[k]||0)[0]<l?o[k]:[l,p],a.map((v,i)=>w+w&&[...v].map((c,i)=>s-=c!=w[i],s=1)|s||f(a.filter(_=>i--),[...p,v],v,l+1))).sort(([a],[b])=>b-a)[0]

Pruébalo en línea!

¿Cómo?

fow0w1[l,p]pw0w1l

plwpo

o[k = [w, p[0]]] = (o[k] || 0)[0] < l ? o[k] : [l, p]

o

Object.values(o).sort(([a], [b]) => b - a)[0]

(este código se ejecuta en cada profundidad de recursión, pero solo el nivel raíz realmente importa)

vw

[...v].map((c, i) => s -= c != w[i], s = 1) | s

v

f(                    //
  a.filter(_ => i--), // remove the i-th word from a[]
  [...p, v],          // append v to p[]
  v,                  // pass v as the last word
  l + 1               // increment the length of the path
)                     //
Arnauld
fuente
0

Python 3, 228 bytes.

def G(w):
    D={A+B:[A,B]if sum(a!=b for a,b in zip(A,B))<2else[0,0]*len(w)for A in w for B in w}
    for k in w:
        for i in w:
            for j in w:
                p=D[i+k]+D[k+j][1:]
                if len(p)<len(D[i+j]):D[i+j]=p
    return max(D.values(),key=len)

Implementa el algoritmo Floyd-Warshall para todos los pares de rutas más cortas, luego toma el máximo sobre las rutas encontradas.

16 de los caracteres en esta implementación son pestañas, lo cual es lamentable :(

rikhavshah
fuente
2
Esto parece romperse cuando existe un vértice sin bordes incidentes, por ejemplo, "print G (['bag', 'bat', 'cot'])"
jnfnt
Consejo de golf para la sangría de Python: use un espacio para el primer nivel, una pestaña para el segundo, una pestaña y un espacio para el tercero, dos pestañas para el cuarto, etc.
Peter Taylor
1
@PeterTaylor Buen consejo, pero solo funciona para Python 2. Python 3 no permite mezclar pestañas con espacios.
OOBalance
1
Ah, buena captura @jnfnt. Ahora que lo pienso, solo funciona cuando el gráfico está conectado.
rikhavshah