나는 변화를 좋아하지 않는다!


19

입력:

줄 바꿈 또는 공백이없는 두 개의 문자열

산출:

두 개의 입력 문자열은 별도의 줄 에 있으며 두 문자열 중 하나에 필요한 공간이있는 경우 입니다. 그리고 문자가 세 번째 행은 A, R, M대표 추가 , 삭제 , 수정변경 .

상단 또는 하단 입력 문자열 에 공백을 추가 합니다 (필요한 경우). 이 도전의 목표 ARM는 레 벤슈 테인 거리 (Levenshtein distance) 라고도하는 가능한 한 적은 양의 변화 ( ) 로 출력하는 것 입니다.

예:

입력 문자열이 ABCDEFand 라고 가정 AFBECD하면 출력은 다음 과 같습니다.

A B CDEF
AFBECD  
 A A  RR

다음은 다른 가능한 무효 출력 예입니다 (더 많은 것이 있습니다).

ABCDEF
AFBECD
 MMMMM

A BCDEF
AFBECD 
 A MMMR

AB CDEF
AFBECD 
 MAMMMR

ABC DEF
AFBECD 
 MMAMMR

ABC  DEF
AFBECD  
 MMAA RR

ABCDEF 
AFB ECD
 MMR MA

 AB CDEF   // This doesn't make much sense,
AFBECD     // but it's to show leading spaces are also allowed
AM A  RR

그러나이 중 네 가지만 변경 A B CDEF\nAFBECD \n A A RR한 것은 없으므로이 문제에 대한 올바른 결과 만 있습니다.

도전 규칙 :

  • 입력 문자열에 줄 바꿈이나 공백이 없다고 가정 할 수 있습니다.
  • 두 개의 입력 문자열은 길이가 다를 수 있습니다.
  • 선택적인 선행 / 트레일 공간을 제외하고 두 입력 문자열 중 하나는 그대로 유지해야합니다.
  • 언어가 ASCII 이외의 언어를 지원하지 않는 경우 입력에 인쇄 가능한 ASCII 문자 만 포함되어 있다고 가정 할 수 있습니다.
  • 입력 및 출력 형식이 유연합니다. 문자열 배열, 줄 바꾸기가 포함 된 단일 문자열, 2D 문자 배열 등 세 개의 개별 문자열을 가질 수 있습니다.
  • 대신에 다른 것을 사용할 수 있지만 사용한 것을 ARM명시하십시오 (예 : 123, 또는 abc.등).
  • 동일한 양의 변경 ( ARM)으로 둘 이상의 유효한 출력이 가능한 경우 가능한 출력 중 하나를 출력할지 또는 모두 출력 할지를 선택할 수 있습니다.
  • 선행 및 후행 공백은 선택 사항입니다.

    A B CDEF
    AFBECD
     A A  RR
    

    또는

    "A B CDEF\nAFBECD\n A A  RR"
                     ^
                     Note there are no spaces here
    

일반 규칙:

  • 이것은 이므로 바이트 단위의 최단 답변이 이깁니다.
    코드 골프 언어가 코드 골프 언어 이외의 언어로 답변을 게시하지 못하게하지 마십시오. '모든'프로그래밍 언어에 대한 가능한 한 짧은 대답을 생각해보십시오.
  • 표준 규칙이 답변에 적용 되므로 STDIN / STDOUT, 적절한 매개 변수가있는 기능 / 방법, 전체 프로그램을 사용할 수 있습니다. 당신의 전화.
  • 기본 허점 은 금지되어 있습니다.
  • 가능하면 코드 테스트 링크를 추가하십시오.
  • 또한 필요한 경우 설명을 추가하십시오.

테스트 사례 :

In: "ABCDEF" & "AFBECD"

Output (4 changes):
A B CDEF
AFBECD  
 A A  RR                  

In: "This_is_an_example_text" & "This_is_a_test_as_example"

Possible output (13 changes):
This_is_an       _example_text
This_is_a_test_as_example     
         MAAAAAAA        RRRRR

In: "AaAaABBbBBcCcCc" & "abcABCabcABC"

Possible output (10 changes):
AaAaABBbBBcCcCc
 abcABCab cABC 
R MM  MMMR MM R

In: "intf(){longr=java.util.concurrent.ThreadLocalRandom.current().nextLong(10000000000L);returnr>0?r%2:2;}" & "intf(){intr=(int)(Math.random()*10);returnr>0?r%2:2;}"

Possible output (60 changes):
intf(){longr=java.util.concurrent.ThreadLocalRandom.current().nextLong(10000000000L);returnr>0?r%2:2;}
intf(){i ntr=(      i    n      t)(M  ath.r   andom        ()*         10          );returnr>0?r%2:2;}
       MR M  MRRRRRR RRRR RRRRRR MMMRR MMMMRRR     RRRRRRRR  MRRRRRRRRR  RRRRRRRRRR 

In: "ABCDEF" & "XABCDF"

Output (2 changes):
 ABCDEF
XABCD F 
A    R 

In: "abC" & "ABC"

Output (2 changes):
abC
ABC
MM 


거리가 같은 여러 배열이있는 경우 그 중 하나만 출력해도됩니까?
AdmBorkBork

@AdmBorkBork 예, 가능한 출력 중 하나만 실제로 의도 된 출력입니다 (사용 가능한 모든 옵션을 출력하는 것도 괜찮음). 나는 도전 규칙에서 이것을 명확히 할 것이다.
Kevin Cruijssen

@Arnauld 선행 공백에 대한 규칙을 제거 했으므로 선행 및 후행 공백은 수정되지 않은 행에서 선택적이고 유효합니다. (응답의 마지막 테스트 사례가 완전히 유효 함을 의미합니다.)
Kevin Cruijssen

1
@Ferrybig Ah 알겠습니다. 설명해 주셔서 감사합니다. 그러나이 문제는 실제로 인쇄 가능한 ASCII 만 지원하면 충분합니다. 더 많은 것을 지원하려면 내 손님이 되십시오. 그러나 주어진 테스트 사례에서 작동하는 한 1 개 이상의 문자로 구성된 그래 핀 클러스터에 대해서는 정의되지 않은 동작이 좋습니다. :)
Kevin Cruijssen

답변:


5

하스켈 , 192 181 174 161 158 150 147 143 158 1 바이트

e@(a:r)&f@(b:s)=snd$maximum[([1|' '<-s!!2],s)|s<-z(z(:))[a:" R",' ':b:"A",a:b:last("M":[" "|a==b])][r&f,e&s,r&s]]
x&y=[x,y,"RA"!!(0^length x)<$x++y]
z=zipWith

온라인으로 사용해보십시오! 사용법 예 : "ABCDEF" & "AFBECD". 세 개의 문자열 목록을 반환합니다. 이것은 일반적인 레 벤슈 테인 거리 질문에 대한 재귀 솔루션의 확장입니다 .

설명:

에서 얻을 수있는 최소한의 수정을 계산하기 "xyz"에를 "yw", 우리는 두 문자열의 첫 번째 문자에 초점을 맞 춥니 다. 세 가지 가능성이 있습니다.

  • : 제거 드롭을 x첫 번째 문자열에서 재귀에서 얻을 수있는 수정 계산 "yz"에를 "yw". 이것은 세 줄을 산출합니다 ["yz","yw"," M"]. x첫 번째, 두 번째 및 R세 번째에 공백을 추가하십시오 . 우리는 얻는다
    xyz
    yw
    RM
  • 추가 :y 두 번째 문자열에서 삭제 하고 계산 "xyz" & "w"하여 결과를 반환합니다 ["xyz","w","MRR"]. 첫 번째 줄, y두 번째 및 A세 번째 줄에 공백을 추가해야합니다 .
     xyz
    yw
    AMRR
  • 수정 / 변경되지 않음 : 두 문자열의 첫 문자를 삭제하고 나머지 문자열 간의 최소 수정을 계산해야하기 때문에이 두 경우를 결합 할 수 있습니다 "yz" & "w". 결과적으로 ["yz","w","MR"], 우리 x는 그를 먼저 추가 y하고 두 번째 줄에 추가 합니다. 마지막 줄에 대해서만 초기 문자가 같은지 구별해야합니다. 동일하면 공백이 세 번째 줄에 추가되고 그렇지 않으면 (이 경우와 같이 x \= y) a M가 추가됩니다.
    xyz
    yw
    MMR

이 세 후보 중에서 수정이 가장 적은 후보를 찾아야합니다. 이것은 세 번째 줄에서 가장 많은 공백을 갖는 것과 같습니다. 따라서 각 후보 s(세 개의 문자열 목록)를 튜플 로 변환합니다 ([1|' '<-s!!2],s). 여기서 s두 번째 구성 요소 로 표시되고 첫 번째 구성 요소는 세 번째 줄에 공백이있는 수 s( s!!20- 인덱싱으로 인해) 만큼 많은 요소가 포함 된 목록입니다 . list 요소 1가 사용되었지만 실제 요소는 모든 후보자에 대해 동일한 한 관련이 없습니다.

전체적으로 이것은 튜플 목록을 생성합니다

[([1], [ "xyz", "yw", "RM"]), ([], [ "xyz", "yw", "AMRR"]), ([], [ "xyz", " yw ","MMR "])]
빌드에서 maximum선택 왼쪽에서 오른쪽 성분 현명 튜플 전적으로 비교리스트의 가장 큰 소자. 마찬가지로 [1]보다 큰 []제 투플이 선택되어, 및 snd라인들의리스트의 튜플 인 성분의 초를 반환한다.


A문자열 끝에 R-changes가 -changes 로 표시 되는 버그를 수정하는 1 +15 바이트


lol 이것은 사용자 스크립트가 이것이 1 바이트라고 생각하게합니다
HyperNeutrino

8

자바 스크립트 (ES6), 413 ... 343 342 바이트

@KevinCruijssen이 제안한대로 루프 인덱스를 조정하여 5 바이트를 절약했습니다.

카레 구문에서 2 개의 문자열로 입력을받습니다. 3 개의 문자열 배열을 반환합니다.

b=>a=>{m=[];x=a.length;y=b.length;for(i=j=0,c=d='';i<=y;c+=R='R')m[i]=[[c,i++]];for(;j++<x;)m[i=0][j]=[d+=A='A',j];for(;i<y;i++)for(j=0;j<x;)[C]=m[[X,S]=m[i][j],[Y,I]=m[i+1][j],[Z,D]=m[i][++j],Q=[Z+R,D+1],i+1][j]=b[i]==a[j-1]?[X+' ',S]:S<I?D<S?Q:[X+'M',S+1]:D<I?Q:[Y+A,I+1];return[(g=s=>C.replace(/./g,c=>c==s?' ':b[i++],i=0))(A),g(R,b=a),C]}

테스트 사례

덜 골프

b => a => {
  m = []; x = a.length; y = b.length;

  // initialize the leftmost column and the topmost row
  for(i = j = 0, c = d = ''; i <= y; c += R = 'R')
    m[i] = [[c, i++]];
  for(; j++ < x;)
    m[i = 0][j] = [d += A = 'A', j];

  // walk through the Levenshtein matrix
  for(; i < y; i++)
    for(j = 0; j < x;)
      [C] = m[                                // C = current string, once updated
        [X, S] = m[i][j],                     // substitution
        [Y, I] = m[i + 1][j],                 // insertion
        [Z, D] = m[i][++j],                   // deletion
        Q = [Z + R, D + 1],                   // precomputed update for deletion
        i + 1
      ][j] =
        b[i] == a[j - 1] ?
          [X + ' ', S]                        // unchanged character
        :
          S < I ?
            D < S ? Q : [X + 'M', S + 1]      // deletion or substitution
          :
            D < I ? Q : [Y + A, I + 1];       // deletion or insertion

  return [
    // g = helper function to format the output strings by inserting spaces
    (g = s => C.replace(/./g, c => c == s ? ' ' : b[i++], i = 0))(A),
    g(R, b = a),

    // final modification string, picked from the last visited cell
    C
  ]
}

다음은 b = "foo"a = "ok" 의 초기 행렬입니다 .

//                     'o'           'k'
[ [ [ '',    0 ], [ 'A',   1 ], [ 'AA',  2 ] ],
  [ [ 'R',   1 ],  (undefined),  (undefined) ],  // 'f'
  [ [ 'RR',  2 ],  (undefined),  (undefined) ],  // 'o'
  [ [ 'RRR', 3 ],  (undefined),  (undefined) ] ] // 'o'

모든 반복 후의 최종 행렬은 다음과 같습니다.

//                     'o'           'k'
[ [ [ '',    0 ], [ 'A',   1 ], [ 'AA',  2 ] ],
  [ [ 'R',   1 ], [ 'M',   1 ], [ 'MA',  2 ] ],  // 'f'
  [ [ 'RR',  2 ], [ 'R ',  1 ], [ 'R A', 2 ] ],  // 'o'
  [ [ 'RRR', 3 ], [ 'RR ', 2 ], [ 'R M', 2 ] ] ] // 'o'

Levenshtein 거리와 함께 최종 수정 문자열은 오른쪽 아래 셀에 저장됩니다.


같은 변화 나에 대한 -1 / + 1 1 바이트 저장 제안 j하고 x여전히를 최신 편집에 적용됩니다 b=>a=>{m=[];x=a.length;y=b.length+1;for(i=y;i--;)m[i]=[[i,'R'.repeat(i)]];for(j=x+1;j--;)m[i=0][j]=[j,'A'.repeat(j)];for(;++i<y;)for(j=-1;++j<x;)R=m[S=(X=m[i-1][j])[0],I=(Y=m[i][j])[0],D=(Z=m[i-1][j+1])[0],Q=[D+1,Z[1]+'R'],i][j+1]=b[i-1]==a[j]?[S,X[1]+' ']:S<I?D<S?Q:[S+1,X[1]+'M']:D<I?Q:[I+1,Y[1]+'A'];return[(g=s=>R[1].replace(/./g,c=>c==s?' ':b[i++],i=0))('A'),g('R',b=a),R[1]]}:
케빈 Cruijssen

1
@KevinCruijssen 나는 당신의 아이디어를 한 단계 더 발전시켜 5 바이트를 절약했습니다. 감사!
Arnauld

4

파이썬 2 , 548 536 484 500 1 488 447 381 2 373 371 357 350 바이트

s,t=input()
n,m=len(s),len(t)
r=range
L=[[(j,'RA'[i<1]*j)for j in r(i,m-~i)]for i in r(n+1)]
for i in r(n):
 for j in r(m):M,R=L[i][j:j+2];A=L[i+1][j];v,V=min(A,R,M);x=('AR'[v in R],'M_'[s[i]==t[j]])[v in M];_=M;X=eval(x)[1]+x;L[i+1][j+1]=v+(x<'_'),X
for i in r(len(X)):s=s[:i]+' '*('B'>X[i])+s[i:];t=t[:i]+' '*('R'==X[i])+t[i:]
print s+'\n'+t+'\n'+X

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

'ARM_'대신에 사용'ARM '

Levenshtein 매트릭스를 구축 한 다음 뒤로 탐색하여 연산을 찾습니다 . Arnauld의 JS 답변 에서와 같이 Levenshtein 행렬과 동시에 operation-string을 빌드합니다.

1 : 첫 번째 문자열이 단일 문자 인 경우 작동하지 않으므로 더 많은 바이트.

2 : Levenshtein 매트릭스에서 조합을 빌드하도록 전환했습니다.


내 초기 (실패한) 시도와 같은 6 개의 문자 단어에 대해 60 초 미만의 시간에 +1 lol
HyperNeutrino

좋은 대답입니다! 나에게서 +1 파이썬 I에서 나는 결코 프로그램이 정말 골프와 함께 당신을 도울 수 없기 때문에, 한 가지를 제외하고 : m+i+1할 수 있습니다 m-~i.
Kevin Cruijssen

7 행에서 이중 공백 대신 탭을 사용할 수 있습니다.
Stephen

while i+j<n+m:v,A=(L[i]+[m,m])[j:j+2];R,M=(L[i+1]+[m,m])[j:j+2];d=min(A,R,M);q=M==d or(R==d)*2;r+=' '*(d==v==M)or'AMR'[q];i+=q>0;j+=q<2
wile

1

파이썬 2 , 310 바이트

from difflib import*
a,b=input()
U,j=[],' '
for g,s,t,x,y in SequenceMatcher(0,a,b).get_opcodes():
	g,Y,T=g[0],y-x,t-s
	z,A,B=Y-T,a[s:t],b[x:y]
	if'q'<g:U+=[A+z*j,B+j*-z,'M'*min(T,Y)+'A'*z+'R'*-z]
	if'e'==g:U+=[A,B,j*Y]
	if'i'==g:U+=[j*Y,B,'A'*Y]
	if'e'>g:U+=[A,j*T,'R'*T]
for e in[0,1,2]:print''.join(U[e::3])

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

이를 사용하여 difflib.SequenceMatcher두 문자열 사이의 정렬을 계산합니다.


이것은 다른 테스트 사례 중 일부에 대해 잘못된 결과를 제공하는 것 같습니다. 더 구체적 :"This_is_an_example_text","This_is_a_test_as_example"
Kevin Cruijssen

@KevinCruijssen 고맙습니다, 방금 수정 ^ _ ^
mdahmoune

잘 지내! 그러나 음 .. 세 번째 테스트 사례 (및 네 번째 테스트 사례) 도 불행히도 잘못되었습니다. 두 줄 중 하나는 수정하지 않아야합니다 (앞 / 뒤 공간 제외). 두 줄 모두 현재 가운데에 공백이 있습니다.
Kevin Cruijssen

@KevinCruijssen 고맙습니다 다시 고쳐 요
mdahmoune

1

매스 매 티카, 250 256 259 384 바이트

Java 코드 케이스의 경우 ~ 0.00035 초

(i=o=p="";a=Array;r=StringLength;If[Length@#>0,g=#&@@#;h=#[[2]];u=r@g;v=r@h;i=i<>g;o=o<>h;w=Abs[v-u];k=a[" "&,w];If[u<v,i=i<>k,o=o<>k];p=p<>a["M"&,u~Min~v];p=p<>a[If[u>v,"R","A"]&,w],i=i<>#;o=o<>#;p=p<>a[" "&,r@#]]&/@SequenceAlignment[#,#2];{i,o,p})&

용법: f["ABCDE", "ABCDF"]

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

코드는 SequenceAlignment기본적으로 작동 하는 사실을 기반으로합니다 .

기본 설정 SimilarityRules-> Automatic을 사용하면 두 요소 사이의 각 일치가 총 유사성 점수에 1을 기여하는 반면 각 불일치, 삽입 또는 삭제는 -1을 제공합니다.

즉, 점수가 계산된다 M, A그리고 R따라서.

예:

예


2
흠, 나는 Mathemetica에서 프로그래밍 한 적이 없지만 2 바이트를 줄 이도록 변경할 i="";o="";p="";i="";o=i;p=i;없습니까?
Kevin Cruijssen

2
무엇에 대해 i=o=p=""?
DavidC

@DavidC 그래 나는 그것을 깨달았고 이미 그것을 바꿨다. 어쨌든 감사합니다
Keyu Gan

1

D , 351 345 바이트

KevinCruijssen에 -6 바이트의 감사

string f(string a,string b){import std.algorithm;string x,y,z;size_t i,j,k;foreach(c;levenshteinDistanceAndPath(a,b)[1]){final switch(c)with(EditOp){case none:x~=a[i++];y~=b[j++];z~=" ";break;case substitute:x~=a[i++];y~=b[j++];z~="M";break;case insert:x~=" ";y~=b[j++];z~="A";break;case remove:x~=a[i++];y~=" ";z~="R";}}return x~"\n"~y~"\n"~z;}

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


마지막을 제거하여 6 바이트를 골프화 할 수 있습니다 break;. +1이지만 프로그래밍 언어 D를
처음봤을 때
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.