단어 체인저 접근성


13

단어 체인저는 단일 문자 편집을 통해 한 단어를 다른 단어로 바꾸려고하는 게임으로, 각 단계는 고유 한 단어입니다. 이 문제의 경우 편집은 교체, 삽입 또는 삭제 일 수 있습니다. 예를 들어,이 경로로 WINNER → LOSER를 수행 할 수 있습니다 (다른 경로가있을 수 있음).

WINNER
DINNER
DINER
DINE
LINE
LONE
LOSE
LOSER

다른 말로 표현하면, 매번 1의 Levenshtein 거리에서 다른 단어를 통해서만 다른 단어에서 한 단어에 도달 할 수 있어야합니다.

코딩

단어 목록과 두 단어가 제공되며 경로가 존재하는 경우 한 단어에서 다른 단어로 유효한 경로를 출력하거나 경로가 존재하지 않으면 고유 한 상수 값 또는 일관된 동작을 출력해야합니다.

  • 입력 단어가 모두 단어 목록에 있다고 가정 할 수 있습니다.
  • 단어 목록은 편리한 플랫 형식을 통해 가져올 수 있습니다.
    • 목록, 세트, ​​시도, 공백으로 구분 된 문자열 및 줄로 구분 된 파일은 모두 유효하지만 (예 :) 사전 계산 된 Levenshtein 인접성 그래프는 유효하지 않습니다.
  • 출력 경로에는 두 입력 단어가 모두 포함되어야하지만 시작 및 종료는 중요하지 않습니다.
  • 경로를 찾을 수 없으면 특정 상수, 잘못된 값, 빈 목록, 예외 발생, 0이 아닌 코드로 종료 또는 유한 시간 내에 발생하는 기타 동작을 출력 할 수 있습니다.
  • 경로가 최적 일 필요는 없으며 어떤 경로를 취해야 할 필요가 없습니다.
  • 계산 복잡성은 중요하지 않지만 프로그램이 유한 한 시간 안에 종료되도록 보장해야합니다. (우주의 열사를 뛰어 넘어도)
  • 모든 단어가 모두 같은 경우에 문자로 구성되어 있다고 가정 할 수 있습니다

테스트 사례 예

  • 고양이 → 개; [CAT, DOG, COG, COT, FROG, GROG, BOG]
    • CAT, COT, COG, DOG
  • 목욕 → 샤워기; [BATH, 샤워, HATH, HAT, BAT, SAT, SAW, SOW, SHOW, HOW]
    • 경로를 찾을 수 없습니다
  • BREAK → 수정; [BREAK, FIX, BEAK, BREAD, READ, BEAD, RED, BED, BAD, BID, FAD, FAX]
    • 브레이크, 빵, BEAD, 나쁜, FAD, 팩스, FIX
  • 건축 → 파괴; [빌드, 디스트로이, 빌트, GUILT, 길드, 길드, 길, 빌, 딜, 필, 대상, 구조, 건설]
    • 경로를 찾을 수 없습니다
  • 카드 → 보드; [카드, 보드, 카드]
    • 카드, 보드, 보드
  • 악마 → 천사; [앤젤, 악마]
    • 경로를 찾을 수 없습니다
  • 마지막 → 과거; [LAST, PAST, BLAST, CAST, BLACK, GHOST, POST, BOAST]
    • 마지막, 마지막
  • 삽입 → 삭제; 이 단어 목록
    • INSERT, INVERT, INVENT, INBENT, UNBENT, UNBEND, UNBIND, UNKIND, UNKING, INKING, IRKING, DIRKING, DARKING, DARLING, ARLING, AILING, SIRING, SERING, SERINE, NERINE, NERITE, CERITE, CERATE, DERATE, DELATE, 인버트 지우다


1
유효한 경로 목록을 출력 할 수 있습니까 아니면 하나의 경로 여야합니까?
Emigna

@Emigna는 모든 경로를 수행합니다. 내가 언급했듯이 "경로가 최적 일 필요는 없다"
Beefster

출력에 시작 및 끝 단어를 포함시켜야합니까? 경로는 항상 동일하게 시작하고 끝납니다!
Magic Octopus Urn

1
@MagicOctopusUrn "출력 경로는 두 입력 단어를 모두 포함해야하지만 시작과 끝은 중요하지 않습니다."
Beefster

답변:


5

05AB1E , 23 21 20 바이트

유효한 경로 목록을 인쇄합니다. Kevin Cruijssen
덕분에 2 바이트를 절약했습니다 .

怜€`ʒü.LP}ʒ¬²Qsθ³Q*

온라인으로 사용해보십시오!


로 변경 Dævyœ«}하여 2 바이트를 절약 할 수 있습니다 怜€` . (두 맵이 개별적으로 제대로 작동하는 이유는 확실 æεœ`}하지 않지만 btw는 아니지만 어쨌든 동일한 바이트 수입니다.)
Kevin Cruijssen

너무 나쁜의 제품 []입니다 1대신 0(너무 놀라운 일이 아니다,하지만) 또는 빈 목록과 동등한 검사가 빈 목록에서 분명히 결과 대신 0(I 버그로 볼이 하나 ..) .. 그렇지 않으면 당신은 결합 수 있었다 필터와 find_first는 다른 바이트를 저장합니다 :怜€`.Δü.LPy¬²Qsθ³QP
Kevin Cruijssen

@ KevinCruijssen : 감사합니다! 내가을 사용하지 않은 이유를 잘 모르겠습니다 . 벡터화로 인해 동일한 검사로 인해 빈 목록이 생성됩니다. 빈 목록에는 특별한 경우가있을 수 있지만 다른 경우에는 예상치 못한 결과 일 수 있습니다.
Emigna

1
17에 대해 이와 같은 작업을 수행합니다 : 온라인으로 사용해보십시오!
Magic Octopus Urn

1
@MagicOctopusUrn : 불행히도, 경로에 모든 단어를 출력에 포함시켜야합니다.
Emigna

4

자바 스크립트 (V8) ,  177  176 바이트

로 입력을 (target)(source, list)받습니다. 가능한 모든 경로를 인쇄합니다. 또는 해결책이 없으면 아무것도 인쇄하지 않습니다.

t=>F=(s,l,p=[],d)=>s==t?print(p):l.map((S,i)=>(g=(m,n)=>m*n?1+Math.min(g(m-1,n),g(m,--n),g(--m,n)-(S[m]==s[n])):m+n)(S.length,s.length)^d||F(S,L=[...l],[...p,L.splice(i,1)],1))

온라인으로 사용해보십시오!

댓글

t =>                            // t = target string
F = (                           // F is a recursive function taking:
  s,                            //   s = source string
  l,                            //   l[] = list of words
  p = [],                       //   p[] = path
  d                             //   d = expected Levenshtein distance between s and the
) =>                            //       next word (initially undefined, so coerced to 0)
  s == t ?                      // if s is equal to t:
    print(p)                    //   stop recursion and print the path
  :                             // else:
    l.map((S, i) =>             //   for each word S at index i in l[]:
      ( g =                     //     g = recursive function computing the Levenshtein
        (m, n) =>               //         distance between S and s
        m * n ?                 //       if both m and n are not equal to 0:
          1 + Math.min(         //         add 1 to the result + the minimum of:
            g(m - 1, n),        //           g(m - 1, n)
            g(m, --n),          //           g(m, n - 1)
            g(--m, n) -         //           g(m - 1, n - 1), minus 1 if ...
            (S[m] == s[n])      //           ... S[m - 1] is equal to s[n - 1]
          )                     //         end of Math.min()
        :                       //       else:
          m + n                 //         return either m or n
      )(S.length, s.length)     //     initial call to g with m = S.length, n = s.length
      ^ d ||                    //     unless the distance is not equal to d,
      F(                        //     do a recursive call to F with:
        S,                      //       the new source string S
        L = [...l],             //       a copy L[] of l[]
        [...p, L.splice(i, 1)], //       the updated path (removes S from L[])
        1                       //       an expected distance of 1
      )                         //     end of recursive call
    )                           //   end of map()


3

파이썬 2 , 155 바이트

f=lambda a,b,W,r=[]:a==b and r+[a]or reduce(lambda q,w:q or any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))and f(w,b,W-{a},r+[a]),W-{a},0)

온라인으로 사용해보십시오!

두 단어와 단어 세트를 입력으로 사용합니다. 문자열 목록으로 존재하는 경우 (최적이 아닌) 경로를 반환하고, 그렇지 않으면 False를 반환합니다.

이 조각 :

any({a,a[:i]+a[i+1:]}&{w,w[:i]+w[i+1:]}for i in range(len(a+w)))

True경우에만, a==w또는 a의 Levenshtein 거리가 1에서를 w.



2

파이썬 2 , 163 바이트

라우트가 발견되면 stderr로 출력되고 프로그램은 종료 코드 1로 종료됩니다.
라우트가 없으면 출력이없고 프로그램은 종료 코드 0으로 종료됩니다.

s,e,d=input();r=[[s]]
for x in r:t=x[-1];t==e>exit(x);r+=[x+[w]for w in d-set(x)for a,b in(t,w),(w,t)for i in range(len(b)*2)if a==b[:i/2]+a[i/2:][:i%2]+b[i/2+1:]]

온라인으로 사용해보십시오!


1

파이썬 (3) , 217 (214) 212 201 바이트

xnor의 힌트에 -11 바이트의 고맙습니다

d=lambda a,b:min(d(a[1:],b[1:])+(a[0]!=b[0]),d(a[1:],b)+1,d(a,b[1:])+1)if b>""<a else len(a+b)
def g(a,b,l,p=[]):
	if a==b:yield[a]+p
	for c in(a!=b)*l:
		if(c in p)+d(a,c)==1:yield from g(c,b,l,[a]+p)

온라인으로 사용해보십시오!


0

젤리 , 38 바이트

⁵ḟ,€0ị$ṭ¹-Ƥ$€e€/ẸƊƇḢ€
Wṭ@ⱮÇßƊe@⁴oṆƲ?€Ẏ

온라인으로 사용해보십시오!

세 가지 주장을 받아들이는 완전한 프로그램. 첫 번째는 시작 단어이며로 제공됩니다 [["START"]]. 두 번째 인수는로 최종 단어 "END"입니다. 세 번째 인수는 쉼표로 구분 된 따옴표로 제공된 단어 목록입니다.

프로그램은 목록의 목록을 리턴하며 각 목록은 시작부터 끝까지 유효한 경로를 나타냅니다. 유효한 경로가 없으면 응답은 빈 목록입니다.

TIO 링크에는 각 단어를 공백으로 구분하고 각 단어 목록을 개행 문자로 구분하여 결과를 멋지게 표시하는 바닥 글 텍스트가 있습니다. 출력 기본 목록 표현을 선호하는 경우 다음과 같이 수행 할 수 있습니다 ÇŒṘ.

05ABIE와 달리 Levenshtein 거리에 대한 내장 기능이 없으므로이 프로그램은 Jelly 트위스트가 있지만 @ChasBrown의 솔루션 과 다소 유사한 단일 문자 누락과 접두사를 비교합니다 .

설명

도우미 링크 : 단어 목록을 가져와 가능한 확장 목록의 목록을 반환하는 모나드 링크 또는 추가 확장이 불가능한 경우 빈 목록

⁵ḟ                      | Filter the word list to remove words already used
  ,€0ị$                 | Pair each word with the last word in the current path
                  ƊƇ    | Filter these pairs such that
              e€/Ẹ      |   there exists any
       ṭ¹-Ƥ$€           |   match between the original words or any outfix with a single character removed
                    Ḣ€  | Take the first word of each of these pairs (i.e. the possible extensions of the route)

메인 링크

              €         | For each of the current paths
            Ʋ?          | If:
       e@⁴              |   The path contains the end word
          oṆ            |   Or the path is empty (i.e. could not be extended)
W                       | Return the path wrapped in a list (which will be stripped by the final Ẏ)
 ṭ@ⱮÇ                   | Otherwise, look for possible extensions using the helper link, and add onto the end of the path
     ßƊ                 | And then feed all of these paths back through this link
               Ẏ        | Strip back one layer of lists (needed because each recursion nests the path one list deeper)

0

스위프트 4.2 / Xcode 10.2.1 , 387 바이트

func d(l:String,m:String)->Bool{return (0..<l.count).contains{var c=l;c.remove(at:c.index(c.startIndex,offsetBy:$0));return c==m}};func f(r:[String])->[String]{if b==r.last!{return r};return w.lazy.map{!r.contains($0)&&(d(l:r.last!,m:$0)||d(l:$0,m:r.last!)||(r.last!.count==$0.count&&zip(r.last!,$0).filter{$0 != $1}.count==1)) ? f(r:r+[$0]):[]}.first{!$0.isEmpty} ?? []};return f(r:[a])

온라인으로 사용해보십시오!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.