Trouver le diamètre d'un graphique de mots

12

introduction

Un puzzle de mots populaire consiste à convertir un mot en un autre via une série d'étapes qui remplacent une seule lettre et qui aboutissent toujours à un mot valide. Par exemple, BAG peut être converti en DOG via un chemin de cinq étapes:

SAC -> BAT -> CAT -> COT -> COG -> DOG

Des chemins plus courts existent également dans ce cas; par exemple:

SAC -> BOG -> CHIEN

Si l'on dessinait un graphique dont les sommets étaient étiquetés par des mots, avec un bord entre n'importe quelle paire de mots qui diffèrent par une lettre, alors le chemin le plus court de "BAG" à "DOG" serait composé de deux bords.

Défi

Vous devez écrire un programme qui reçoit en entrée un "dictionnaire" de mots qui ont tous la même longueur, représentant tous les mots autorisés qui peuvent apparaître comme des étapes le long d'un chemin. Il doit produire au moins un "plus long chemin le plus court", c'est-à-dire un chemin entre deux des mots qui est:

  • pas plus que tout autre chemin entre ces deux mots;

  • au moins aussi long que le chemin le plus court possible entre toute autre paire de mots de la liste.

Dans le cadre du graphique décrit ci-dessus, la longueur d'un tel chemin est le diamètre du graphique.

Dans le cas dégénéré où aucun des mots d'entrée ne peut être transformé en aucun des autres, sortez au moins un chemin de longueur zéro, c'est-à-dire un seul mot.

Exemples

  • L'entrée ["bag", "bat", "cat", "cot", "dot", "dog"] devrait donner un chemin traversant les six mots dans cet ordre (ou ordre inverse), car le chemin le plus court de " sac "à" chien "dans ce dictionnaire est la plus longue réalisable, cinq étapes.

  • L'entrée ["sac", "chauve-souris", "bot", "chat", "lit", "point", "chien"] doit donner le chemin "sac, chauve-souris, bot, point, chien" et / ou son renversement.

  • L'entrée ["code", "golf", "mâle", "buzz", "taupe", "rôle", "moule", "froid", "or", "mode"] devrait donner un chemin entre "code" et "golf".

  • L'entrée ["un", "deux", "six", "dix"] correspond à un graphique sans arêtes, donc sortez un ou plusieurs chemins d'un mot (longueur nulle).

  • Si l'entrée contient deux mots de longueur inégale, la sortie n'est pas définie.

Règles

  • Les règles de golf à code standard s'appliquent
  • Il y aura plusieurs chemins "plus courts". Vous devez en générer au moins un, mais vous êtes libre d'en générer autant que vous le souhaitez.
  • Vous êtes libre de décider comment le dictionnaire d'entrée est transmis à votre programme.
  • Le code le plus court en octets gagne.
jnfnt
la source
3
Vous voulez ajouter quelques cas de test supplémentaires?
Jonah
Terminé. Ajout d'une discussion sur le cas où le graphique ne contient aucun bord.
jnfnt
Faut-il accepter une entrée vide (la réponse serait []ou [[]])?
Erik the Outgolfer
Je suis heureux que le comportement ne soit pas défini sur les entrées vides.
jnfnt

Réponses:

3

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

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

Essayez-le en ligne!

l'entrée et la sortie sont des matrices de caractères

⍵+.≠⍉⍵ matrice de distances de type hamming entre les mots

9*⍨2⌊laissez les 0 et les 1 intacts, transformez 2+ en un grand nombre (512 = 2 9 , utilisé comme "∞")

⌊.+⍨⍣≡ l' algorithme de chemin le plus court de floyd & warshall

  • ⌊.+comme la multiplication matricielle mais en utilisant min( ) et +au lieu de +et ×respectivement

  • utiliser la même matrice à gauche et à droite

  • ⍣≡ répéter jusqu'à convergence

d←⌈/512|, longueur du chemin le plus long (pas "∞"), attribué à d

⊃⍸a=quels sont les deux nœuds connectés, appelons-les i et j

{⍵,⍨⊃⍋(1≠a⌷⍨⊃⍵),⍪⍺⌷a}⍣d/ reconstruire le chemin

  • { }⍣d/évaluer les temps de { }fonction d. l'argument de gauche est toujours i . l'argument droit commence par j et accumule progressivement les nœuds internes du chemin

  • (1≠a⌷⍨⊃⍵),⍪⍺⌷a construire une matrice à 2 colonnes de ces deux vecteurs:

    • 1≠a⌷⍨⊃⍵ booléens (0 ou 1) indiquant quels nœuds sont à la distance 1 du premier

    • ⍺⌷a distances de tous les nœuds du graphique à

  • ⊃⍋ index de la plus petite rangée lexicographiquement

  • ⍵,⍨ ajouter à

⍵⌷⍨ indexer les mots originaux avec le chemin

ngn
la source
2

Python 3 , 225 octets

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]

Essayez-le en ligne!

Fondamentalement, prenez tous les chemins possibles, ne gardez que ceux qui sont valides, puis parcourez chaque combinaison début-fin, trouvez la distance de chemin minimale et trouvez le maximum de celle-ci.

HyperNeutrino
la source
1

JavaScript (ES6),  195  194 octets

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

Essayez-le en ligne!

Comment?

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]

(ce code est exécuté à chaque profondeur de récursivité, mais seul le niveau racine compte vraiment)

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

Python 3, 228 octets.

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)

Implémente l'algorithme Floyd-Warshall pour les chemins les plus courts toutes paires, puis prend le maximum sur les chemins trouvés.

16 des caractères de cette implémentation sont des onglets, ce qui est regrettable :(

rikhavshah
la source
2
Cela semble rompre lorsqu'un sommet sans arêtes incidentes existe, par exemple, "imprimer G (['sac', 'chauve-souris,' lit '])"
jnfnt
Astuce de golf pour l'indentation Python: utilisez un espace pour le premier niveau, un onglet pour le deuxième, un onglet et un espace pour le troisième, deux onglets pour le quatrième, etc.
Peter Taylor
1
@PeterTaylor Bon conseil, mais ne fonctionne que pour Python 2. Python 3 ne permet pas de mélanger les tabulations avec des espaces.
OOBalance
1
Ah, bonne prise @jnfnt. Maintenant que j'y pense, cela ne fonctionne que lorsque le graphique est connecté.
rikhavshah