Найти диаметр слова графа

12

Вступление

Популярная головоломка состоит в том, чтобы преобразовать одно слово в другое с помощью последовательности шагов, которые заменяют только одну букву и которые всегда приводят к правильному слову. Например, BAG может быть преобразован в DOG через путь из пяти шагов:

СУМКА -> BAT -> CAT -> COT -> COG -> СОБАКА

Более короткие пути также существуют в этом случае; например:

СУМКА -> БОГ -> СОБАКА

Если нарисовать граф, вершины которого были помечены словами, с ребром между любой парой слов, отличающихся на одну букву, то кратчайший путь от «BAG» до «DOG» будет состоять из двух ребер.

Вызов

Вы должны написать программу, которая получает в качестве входных данных «словарь» слов, имеющих одинаковую длину, представляющих все допустимые слова, которые могут появляться как шаги по пути. Он должен вывести хотя бы один «самый длинный кратчайший путь», то есть путь между двумя словами:

  • не длиннее любого другого пути между этими двумя словами;

  • по крайней мере, до максимально короткого пути между любой другой парой слов в списке.

В контексте графика, описанного выше, длина такого пути - это диаметр графика.

В вырожденном случае, когда ни одно из входных слов не может быть преобразовано ни в одно из других, выведите хотя бы один путь нулевой длины, то есть одно слово.

Примеры

  • Ввод ["bag", "bat", "cat", "cot", "dot", "dog"] должен давать путь, пересекающий все шесть слов в этом порядке (или обратном порядке), поскольку самый короткий путь из " Сумка "для" собаки "в этом словаре самая длинная, достижимая, пять шагов.

  • Ввод ["bag", "bat", "bot", "cat", "cot", "dot", "dog"] должен давать путь "bag, bat, bot, dot, dog" и / или его разворот.

  • Ввод ["code", "golf", "male", "buzz", "mole", "role", "mold", "cold", "gold", "mode"] должен давать путь между "code" и "гольф".

  • Входные данные ["one", "two", "six", "ten"] соответствуют графу без ребер, поэтому выведите один или несколько путей из одного слова (нулевой длины).

  • Если входные данные содержат любые два слова неравной длины, выходные данные не определены.

правила

  • Применяются стандартные правила игры в гольф
  • Там будет несколько «кратчайших» путей. Вы должны вывести хотя бы один, но можете вывести столько, сколько пожелаете.
  • Вы можете сами решать, как вводить словарь в вашу программу.
  • Самый короткий код в байтах побеждает.
jnfnt
источник
3
Не могли бы вы добавить еще несколько тестов?
Иона
Выполнено. Также добавлено обсуждение случая, когда граф не содержит ребер.
Jnfnt
Должны ли мы принять пустой ввод (ответ будет []или [[]])?
Эрик Outgolfer
Я рад, что поведение не определено на пустых входах.
Jnfnt

Ответы:

3

APL (Dyalog Classic) , 84 80 77 76 74 66 61 байт

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

Попробуйте онлайн!

вход и выход являются символьными матрицами

⍵+.≠⍉⍵ матрица расстояний Хэмминга между словами

9*⍨2⌊оставить 0 и 1 без изменений, превратить 2+ в некоторое большое число (512 = 29 , используется как «∞»)

⌊.+⍨⍣≡ алгоритм кратчайшего пути floyd & warshall

  • ⌊.+как матричное умножение, но с использованием min( ) и +вместо +и ×соответственно

  • используйте одну и ту же матрицу слева и справа

  • ⍣≡ повторить до схождения

d←⌈/512|, длина самого длинного (не "∞") пути, назначенного d

⊃⍸a=с какими двумя узлами он соединяется, давайте назовем их i и j

{⍵,⍨⊃⍋(1≠a⌷⍨⊃⍵),⍪⍺⌷a}⍣d/ реконструировать путь

  • { }⍣d/оцените время { }функции d. левый аргумент всегда i . правый аргумент начинается как j и постепенно накапливает внутренние узлы пути

  • (1≠a⌷⍨⊃⍵),⍪⍺⌷a построить матрицу из двух столбцов этих двух векторов:

    • 1≠a⌷⍨⊃⍵ логическое значение (0 или 1), указывающее, какие узлы находятся на расстоянии 1 до первого из

    • ⍺⌷a расстояния всех узлов графа до

  • ⊃⍋ указатель лексикографически наименьшего ряда

  • ⍵,⍨ готовиться к

⍵⌷⍨ индексировать оригинальные слова с путем

СПП
источник
2

Python 3 , 225 байт

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]

Попробуйте онлайн!

По сути, возьмите все возможные пути, оставьте только те, которые являются действительными, затем просмотрите каждую комбинацию начала и конца, найдите минимальное расстояние пути и найдите максимум этого.

HyperNeutrino
источник
1

JavaScript (ES6),  195  194 байта

Возвращает [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]

Попробуйте онлайн!

Как?

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]

(этот код выполняется на каждой глубине рекурсии, но на самом деле имеет значение только корневой уровень)

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
источник
0

Python 3, 228 байт.

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)

Реализует алгоритм Флойда-Варшалла для всех пар кратчайших путей, затем берет максимум по найденным путям.

16 из символов в этой реализации являются вкладками, что вызывает сожаление :(

rikhavshah
источник
2
Кажется, что это нарушается, когда существует вершина без инцидентных ребер, например, "print G (['bag', 'bat', 'cot'])"
jnfnt
Совет по игре в гольф для отступов в Python: используйте пробел для первого уровня, табуляцию для второго, табуляцию и пробел для третьего, две табуляции для четвертого и т. Д.
Питер Тейлор
1
@PeterTaylor Хороший совет, но работает только для Python 2. Python 3 не позволяет смешивать табуляции с пробелами.
OOBalance
1
Ах, хороший улов @jnfnt. Теперь, когда я думаю об этом, он работает только тогда, когда граф подключен.
Рихавшах