Tìm đường kính của đồ thị từ


12

Giới thiệu

Một câu đố từ phổ biến là chuyển đổi một từ thành một từ khác thông qua một loạt các bước chỉ thay thế một chữ cái và luôn luôn dẫn đến một từ hợp lệ. Ví dụ: BAG có thể được chuyển đổi thành DOG thông qua đường dẫn gồm năm bước:

TÚI -> BAT -> CAT -> COT -> COG -> DOG

Đường dẫn ngắn hơn cũng tồn tại trong trường hợp này; ví dụ:

TÚI -> BOG -> DOG

Nếu người ta vẽ một biểu đồ có các đỉnh được gắn nhãn bằng các từ, với một cạnh giữa bất kỳ cặp từ nào khác nhau bởi một chữ cái, thì con đường ngắn nhất từ ​​"BAG" đến "DOG" sẽ bao gồm hai cạnh.

Thử thách

Bạn phải viết một chương trình nhận đầu vào là "từ điển" các từ có cùng độ dài, đại diện cho tất cả các từ được phép có thể xuất hiện dưới dạng các bước trên một đường dẫn. Nó sẽ xuất ra ít nhất một "con đường ngắn nhất dài nhất", nghĩa là một đường dẫn giữa hai từ đó là:

  • không dài hơn bất kỳ con đường nào khác giữa hai từ đó;

  • ít nhất là chừng nào con đường ngắn nhất có thể giữa bất kỳ cặp từ nào khác trong danh sách.

Trong ngữ cảnh của biểu đồ được mô tả ở trên, độ dài của đường dẫn như vậy là đường kính của biểu đồ.

Trong trường hợp suy biến trong đó không có từ nào trong số các từ đầu vào có thể được chuyển đổi thành bất kỳ từ nào khác, xuất ra ít nhất một đường dẫn có độ dài bằng 0, nghĩa là một từ duy nhất.

Ví dụ

  • Đầu vào ["bag", "bat", "cat", "cot", "dot", "dog"] sẽ mang lại một đường dẫn đi qua tất cả sáu từ theo thứ tự đó (hoặc thứ tự ngược lại), vì đường đi ngắn nhất từ ​​" túi "to" dog "trong từ điển này là dài nhất có thể đạt được, năm bước.

  • Đầu vào ["bag", "bat", "bot", "cat", "cot", "dot", "dog"] sẽ mang lại đường dẫn "bag, bat, bot, dot, dog" và / hoặc của nó đảo ngược.

  • Đầu vào ["mã", "golf", "nam", "buzz", "nốt ruồi", "vai trò", "khuôn", "lạnh", "vàng", "chế độ"] sẽ tạo ra một đường dẫn giữa "mã và "golf".

  • Đầu vào ["một", "hai", "sáu", "mười"] tương ứng với một biểu đồ không có cạnh, do đó, xuất ra một hoặc nhiều đường dẫn một từ (độ dài bằng không).

  • Nếu đầu vào chứa bất kỳ hai từ có độ dài không bằng nhau, đầu ra không được xác định.

Quy tắc

  • Luật golf tiêu chuẩn được áp dụng
  • Sẽ có nhiều con đường "ngắn nhất". Bạn phải xuất ít nhất một, nhưng được tự do xuất bao nhiêu tùy ý.
  • Bạn được tự do quyết định cách từ điển đầu vào được truyền vào chương trình của bạn.
  • Mã ngắn nhất trong byte thắng.

3
Tâm thêm một vài trường hợp thử nghiệm?
Giô-na

Làm xong. Cũng thêm thảo luận về trường hợp đồ thị không có cạnh.
jnfnt


Chúng ta có nên chấp nhận một đầu vào trống (câu trả lời sẽ là []hoặc [[]])?
Erik the Outgolfer

Tôi rất vui vì hành vi không được xác định trên các đầu vào trống.
jnfnt

Câu trả lời:



3

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

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

Hãy thử trực tuyến!

đầu vào và đầu ra là ma trận ký tự

⍵+.≠⍉⍵ ma trận khoảng cách giống như hamming giữa các từ

9*⍨2⌊giữ nguyên 0 và 1, biến 2+ thành một số lớn (512 = 2 9 , được sử dụng là "")

⌊.+⍨⍣≡ Thuật toán đường đi ngắn nhất của floyd & warshall

  • ⌊.+như nhân ma trận nhưng sử dụng min( ) và +thay vì +×tương ứng

  • sử dụng cùng một ma trận ở bên trái và bên phải

  • ⍣≡ lặp lại cho đến khi hội tụ

d←⌈/512|, độ dài của đường dẫn dài nhất (không phải ""), được gán cho d

⊃⍸a=Nó kết nối với hai nút nào, hãy gọi chúng là ij

{⍵,⍨⊃⍋(1≠a⌷⍨⊃⍵),⍪⍺⌷a}⍣d/ xây dựng lại con đường

  • { }⍣d/đánh giá thời gian { }chức năng d. các đối số bên trái luôn luôn là tôi . arg bên phải bắt đầu như j và dần dần tích lũy các nút bên trong của đường dẫn

  • (1≠a⌷⍨⊃⍵),⍪⍺⌷a xây dựng ma trận 2 cột của hai vectơ này:

    • 1≠a⌷⍨⊃⍵ booleans (0 hoặc 1) cho biết các nút nào ở khoảng cách 1 đến đầu tiên của

    • ⍺⌷a khoảng cách của tất cả các nút đồ thị đến

  • ⊃⍋ chỉ số của hàng nhỏ nhất từ ​​vựng

  • ⍵,⍨ chuẩn bị

⍵⌷⍨ lập chỉ mục các từ gốc với đường dẫn


2

Python 3 , 225 byte

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]

Hãy thử trực tuyến!

Về cơ bản, lấy tất cả các đường dẫn có thể, chỉ giữ những đường dẫn hợp lệ, sau đó đi qua từng kết hợp bắt đầu, tìm khoảng cách đường dẫn tối thiểu và tìm mức tối đa của đường dẫn đó.



1

JavaScript (ES6),  195  194 byte

Trả về [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]

Hãy thử trực tuyến!

Làm sao?

Chúng tôi sử dụng một hàm đệ quy f mà xây dựng một đối tượng o có khóa bao gồm một cặp từ w0w1 cách nhau bởi dấu phẩy và có giá trị được xác định là [tôi,p], Ở đâu p là con đường ngắn nhất giữa w0w1tôi là chiều dài của con đường này.

Đưa ra một con đường p chiều dài tôi và từ cuối cùng w thêm vào p, o được cập nhật với:

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

Cuối cùng chúng tôi trả lại con đường dài nhất được lưu trữ trong o:

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

(mã này được thực thi ở mỗi độ sâu đệ quy, nhưng chỉ mức gốc mới thực sự quan trọng)

Chúng tôi sử dụng bài kiểm tra sau để biết liệu một từ v khác nhau bởi chính xác một chữ cái với từ cuối cùng w:

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

Cho mỗi từ v có thể được thêm vào đường dẫn, chúng tôi xử lý một cuộc gọi đệ quy như sau:

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 byte.

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)

Triển khai thuật toán Floyd-Warshall cho tất cả các cặp đường đi ngắn nhất, sau đó lấy tối đa trên các đường dẫn tìm thấy.

16 trong số các ký tự trong triển khai này là các tab, điều không may :(


2
Điều này dường như bị phá vỡ khi một đỉnh không có cạnh sự cố tồn tại, ví dụ: "in G (['bag', 'bat', 'cot'])"
jnfnt

Mẹo chơi gôn để thụt Python: sử dụng khoảng trắng cho cấp độ đầu tiên, tab cho cấp thứ hai, tab và không gian cho cấp ba, hai tab cho cấp bốn, v.v.
Peter Taylor

1
@PeterTaylor Mẹo hay, nhưng chỉ hoạt động với Python 2. Python 3 không cho phép trộn các tab với khoảng trắng.
OOBalance

1
À, bắt tốt @jnfnt. Bây giờ tôi nghĩ về nó, nó chỉ hoạt động khi biểu đồ được kết nối.
rikhavshah
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.