単語グラフの直径を見つける


12

前書き

人気のある単語パズルは、1つの文字だけを置き換え、常に有効な単語を生成する一連のステップを介して、ある単語を別の単語に変換することです。たとえば、BAGは5つのステップのパスを介してDOGに変換できます。

BAG-> BAT-> CAT-> COT-> COG-> DOG

この場合、短いパスも存在します。例えば:

BAG-> BOG-> DOG

頂点が単語でラベル付けされたグラフを描いた場合、単語のペア間のエッジが1文字だけ異なる場合、「BAG」から「DOG」への最短パスは2つのエッジで構成されます。

チャレンジ

パスに沿ったステップとして現れる可能性のあるすべての単語を表す、すべて同じ長さの単語の「辞書」を入力として受け取るプログラムを作成します。少なくとも1つの「最長最短パス」、つまり、次の2つの単語間のパスを出力する必要があります。

  • これら2つの単語間の他のどのパスよりも長くありません。

  • 少なくとも、リスト内の他の単語のペア間の最短パスと同じ長さ。

上記のグラフのコンテキストでは、このようなパスの長さはグラフの直径です。

入力語のいずれも他の語に変換できない縮退の場合、長さゼロの少なくとも1つのパス、つまり1つの語を出力します。

  • 入力["bag"、 "bat"、 "cat"、 "cot"、 "dot"、 "dog"]は、6つの単語すべてをその順序(または逆順)で通過するパスを生成する必要があります。この辞書内の「バッグ」から「犬」は、達成可能な最長の5つのステップです。

  • 入力["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"]はエッジのないグラフに対応するため、1つ以上の単一ワード(長さゼロ)のパスを出力します。

  • 入力に長さが等しくない2つのワードが含まれる場合、出力は未定義です。

ルール

  • 標準コードのゴルフ規則が適用されます
  • 複数の「最短」パスがあります。少なくとも1つ出力する必要がありますが、必要な数だけ自由に出力できます。
  • 入力辞書をプログラムに渡す方法は自由に決めることができます。
  • バイト単位の最短コードが優先されます。

3
さらにいくつかのテストケースを追加しますか?
ジョナ

できた また、グラフにエッジが含まれない場合の説明も追加されました。
jnfnt


空の入力を受け入れる必要があります(答えは[]または[[]])。
エリックアウトゴルファー

入力が空の場合、動作が未定義であることを嬉しく思います。
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 = 2 9、「∞」として使用)

⌊.+⍨⍣≡ floyd&warshallの最短経路アルゴリズム

  • ⌊.+行列の乗算と似ていますが、minおよび)を+使用し+×それぞれとの代わりに

  • 左右に同じ行列を使用します

  • ⍣≡ 収束するまで繰り返す

d←⌈/512|, 割り当てられた最長パス(「∞」ではない)の長さ d

⊃⍸a=どの2つのノードが接続するか、それらをiおよびjと呼びましょう

{⍵,⍨⊃⍋(1≠a⌷⍨⊃⍵),⍪⍺⌷a}⍣d/ パスを再構築する

  • { }⍣d/{ }関数のd時間を評価します。左引数は常にiです。正しい引数jから始まり、徐々にパスの内部ノードを蓄積します

  • (1≠a⌷⍨⊃⍵),⍪⍺⌷a これら2つのベクトルの2列の行列を作成します。

    • 1≠a⌷⍨⊃⍵ 最初のノードから距離1にあるノードを示すブール値(0または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]

オンラインでお試しください!

基本的に、すべての可能なパスを取り、有効なパスのみを保持してから、各開始/終了の組み合わせを調べて、最小パス距離を見つけ、その最大値を見つけます。



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]

オンラインでお試しください!

どうやって?

再帰関数を使用します f オブジェクトを構築します o キーが単語のペアで構成されている w0 そして w1 カンマで区切られ、その値は次のように定義されます [lp]、 どこ p 間の最短経路です w0 そして w1 そして l このパスの長さです。

与えられたパス p 長さの l そして最後の言葉 w に追加 po で更新されます:

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

最終的に格納されている最長パスを返します o

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

(このコードは再帰の深さごとに実行されますが、実際に重要なのはルートレベルのみです)

次のテストを使用して、単語が v 最後の単語と1文字だけ異なる w

[...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
)                     //


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)

すべてのペアの最短パスに対してFloyd-Warshallアルゴリズムを実装し、見つかったパスで最大値を取ります。

この実装の16個の文字はタブですが、残念ながら:(


2
これはない入射エッジを有する頂点が存在する場合に破壊すると思われる、例えば、「Gを印刷([ 『バッグ』、 『バット』、 『COT』])」
jnfnt

Pythonのインデントのためにチップをゴルフ:最初のレベルのための空間、第二のタブ、タブ及び第三のためのスペースなど、第四のための2つのタブを使用
ピーター・テイラー

1
@PeterTaylor良いヒントですが、Python 2でのみ機能します。Python3では、タブとスペースを混在させることはできません。
OOBalance

1
ああ、キャッチ@jnfnt。考えてみると、グラフが接続されている場合にのみ機能します。
リカヴシャ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.