Tôi không thích thay đổi!


19

Đầu vào:

Hai chuỗi không có dòng mới hoặc khoảng trắng.

Đầu ra:

Cả hai chuỗi đầu vào trên các dòng riêng biệt, với khoảng trắng khi cần thiết cho một trong hai chuỗi. Và một dòng thứ ba với các nhân vật A, R, M, đại diện bổ sung , loại bỏ , sửa đổi , và không thay đổi .

Chúng tôi thêm không gian để một trong hai đỉnh hoặc chuỗi đầu vào đáy (nếu chúng ta phải). Mục tiêu của thử thách này là đầu ra với số lượng thay đổi ít nhất (ARM ) ít nhất có thể, còn được gọi là khoảng cách Levenshtein .

Thí dụ:

Giả sử các chuỗi đầu vào là ABCDEFAFBECDsau đó đầu ra sẽ là:

A B CDEF
AFBECD  
 A A  RR

Dưới đây là một số kết quả đầu ra không hợp lệ khác có thể làm ví dụ (và còn nhiều hơn nữa):

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

Tuy nhiên, không ai trong số này chỉ có bốn thay đổi, vì vậy chỉ A B CDEF\nAFBECD \n A A RRcó một đầu ra hợp lệ cho thử thách này.

Quy tắc thử thách:

  • Bạn có thể giả sử các chuỗi đầu vào sẽ không chứa bất kỳ dòng hoặc khoảng trắng mới nào.
  • Hai chuỗi đầu vào có thể có độ dài khác nhau.
  • Một trong hai chuỗi đầu vào vẫn giữ nguyên, ngoại trừ các khoảng trắng ở đầu / cuối tùy chọn.
  • Nếu ngôn ngữ của bạn không hỗ trợ bất cứ điều gì ngoài ASCII, bạn có thể cho rằng đầu vào sẽ chỉ chứa các ký tự ASCII có thể in được.
  • Các định dạng đầu vào và đầu ra là linh hoạt. Bạn có thể có ba Chuỗi riêng biệt, một chuỗi Chuỗi, một Chuỗi đơn với các dòng mới, mảng ký tự 2D, v.v.
  • Bạn được phép sử dụng một cái gì đó khác thay vì ARM, nhưng nói rõ những gì bạn đã sử dụng (nghĩa là 123, hoặcabc. , v.v.)
  • Nếu có nhiều hơn một đầu ra hợp lệ có thể có cùng số lượng thay đổi (ARM ), bạn có thể chọn đầu ra một trong những đầu ra có thể hoặc tất cả các đầu ra có thể.
  • Không gian hàng đầu và dấu là tùy chọn:

    A B CDEF
    AFBECD
     A A  RR
    

    hoặc là

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

Quy tắc chung:

  • Đây là , vì vậy câu trả lời ngắn nhất bằng byte thắng.
    Đừng để ngôn ngữ mã-golf ngăn cản bạn đăng câu trả lời với các ngôn ngữ không mã hóa. Cố gắng đưa ra một câu trả lời càng ngắn càng tốt cho ngôn ngữ lập trình 'bất kỳ'.
  • Áp dụng quy tắc chuẩn cho câu trả lời của bạn, vì vậy bạn được phép sử dụng STDIN / STDOUT, các hàm / phương thức với các tham số thích hợp, các chương trình đầy đủ. Cuộc gọi của bạn.
  • Lỗ hổng mặc định bị cấm.
  • Nếu có thể, vui lòng thêm một liên kết với một bài kiểm tra cho mã của bạn.
  • Ngoài ra, xin vui lòng thêm một lời giải thích nếu cần thiết.

Các trường hợp thử nghiệm:

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 


Nếu có nhiều cách sắp xếp có cùng khoảng cách, bạn có thể chỉ xuất một trong số chúng không?
admBorkBork

@AdmBorkBork Có, chỉ một trong những đầu ra có thể thực sự là đầu ra dự định (mặc dù xuất ra tất cả các tùy chọn có sẵn cũng tốt). Tôi sẽ làm rõ điều này trong các quy tắc thách thức.
Kevin Cruijssen

@Arnauld Tôi đã xóa quy tắc về khoảng trắng hàng đầu, vì vậy khoảng trắng ở đầu và cuối là cả hai tùy chọn và hợp lệ trên dòng không được sửa đổi. (Có nghĩa là trường hợp thử nghiệm cuối cùng trong câu trả lời của bạn là hoàn toàn hợp lệ.)
Kevin Cruijssen

1
@Ferrybig Ah ok, cảm ơn đã giải thích. Nhưng đối với thách thức này, chỉ cần hỗ trợ ASCII có thể in được là thực sự đủ. Nếu bạn muốn hỗ trợ nhiều hơn, hãy là khách của tôi. Nhưng miễn là nó hoạt động cho các trường hợp thử nghiệm được đưa ra thì tôi ổn với hành vi không xác định đối với các cụm graphene bao gồm hơn 1 ký tự như vậy. :)
Kevin Cruijssen

Câu trả lời:


5

Haskell , 192 181 174 161 158 150 147 143 158 1 byte

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

Hãy thử trực tuyến! Ví dụ sử dụng : "ABCDEF" & "AFBECD". Trả về một danh sách ba chuỗi. Đây là một phần mở rộng của giải pháp đệ quy của tôi cho câu hỏi khoảng cách Levenshtein thông thường .

Giải trình:

Để tính toán điều chỉnh tối thiểu để có được từ "xyz"đến "yw", chúng tôi tập trung vào những ký tự đầu tiên của cả hai chuỗi. Có ba khả năng:

  • Xóa: Thả xtừ chuỗi đầu tiên và tính toán đệ quy các sửa đổi để có được từ "yz"đến "yw". Điều này mang lại ba dòng ["yz","yw"," M"]. Thêm xvào cái thứ nhất, một khoảng trắng cho cái thứ hai và Rcái thứ ba. Chúng tôi nhận được
    XYZ
    vâng
    RM
  • Thêm: Thả ytừ chuỗi thứ hai và tính toán "xyz" & "w", trả về kết quả ["xyz","w","MRR"]. Chúng ta cần thêm một khoảng trắng trên dòng đầu tiên, yvào dòng thứ hai vàA dòng thứ ba:
     XYZ
    vâng
    AMRR
  • Đã sửa đổi / không thay đổi: Chúng ta có thể kết hợp hai trường hợp đó vì cả hai đều yêu cầu bỏ ký tự đầu tiên của cả hai chuỗi và tính toán các sửa đổi tối thiểu giữa các chuỗi còn lại : "yz" & "w". Để kết quả ["yz","w","MR"], chúng tôi thêm xvào anh ta đầu tiên và ytrên dòng thứ hai. Chỉ cho dòng cuối cùng, chúng ta cần phân biệt xem các ký tự ban đầu có giống nhau không. Nếu chúng giống nhau, một khoảng trắng được thêm vào dòng thứ ba, nếu không (như trong trường hợp này vì x \= y) an Mđược thêm vào:
    XYZ
    vâng
    MMR

Từ ba ứng cử viên đó, chúng tôi cần tìm ra người có ít sửa đổi nhất. Điều này tương đương với việc có nhiều không gian nhất trên dòng thứ ba. Do đó, chúng tôi chuyển đổi từng ứng cử viên s(một danh sách gồm ba chuỗi) thành một tuple ([1|' '<-s!!2],s), trong đó sxuất hiện dưới dạng thành phần thứ hai và thành phần đầu tiên là một danh sách có nhiều phần tử như có khoảng trắng trong dòng thứ ba s( s!!2vì chỉ mục 0). Là phần tử danh sách 1được sử dụng, nhưng phần tử thực tế không liên quan miễn là nó giống nhau cho tất cả các ứng cử viên.

Nhìn chung, điều này mang lại danh sách các bộ dữ liệu

[([1], ["xyz", "yw", "RM"]), ([], ["xyz", "yw", "AMRR"]), ([], ["xyz", " yw "," MMR "])]
Xây dựng-in maximumChọn phần tử lớn nhất trong danh sách này, nơi các bộ được so sánh thứ tự từ điển, đó là thành phần khôn ngoan từ trái sang phải. Khi [1]lớn hơn [], bộ dữ liệu đầu tiên được chọn và sndtrả về thành phần thứ hai, đó là danh sách các dòng, của bộ dữ liệu.


1 +15 byte để sửa lỗi trong đó A-changes ở cuối chuỗi sẽ được hiển thị dưới dạng R-changes


lol điều này làm cho mô tả người dùng nghĩ rằng đây là 1 byte
HyperNeutrino

8

JavaScript (ES6), 413 ... 343 342 byte

Đã lưu 5 byte bằng cách điều chỉnh các chỉ số vòng lặp, như được đề xuất bởi @KevinCruijssen

Lấy đầu vào là 2 chuỗi trong cú pháp currying. Trả về một mảng gồm 3 chuỗi.

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]}

Các trường hợp thử nghiệm

Ít chơi gôn

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
  ]
}

Thí dụ

Dưới đây là ma trận ban đầu cho 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'

và đây là ma trận cuối cùng sau tất cả các lần lặp:

//                     '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'

Chuỗi sửa đổi cuối cùng cùng với khoảng cách Levenshtein được lưu trữ trong ô dưới cùng bên phải.


Thay đổi tương tự tôi đã đề xuất để lưu 1 byte liên quan đến -1 / + 1 jxvẫn áp dụng cho lần chỉnh sửa mới nhất của bạn: 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]]}:)
Kevin Cruijssen

1
@KevinCruijssen Tôi đã lưu 5 byte bằng cách đưa ý tưởng của bạn tiến thêm một bước. Cảm ơn!
Arnauld

4

Python 2 , 548 536 484 500 1 488 447 381 2 373 371 357 350 byte

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

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

Sử dụng 'ARM_'thay vì'ARM '

Hoạt động bằng cách xây dựng ma trận Levenshtein, và sau đó di chuyển ngược để tìm các hoạt động . Bây giờ xây dựng chuỗi hoạt động cùng lúc với ma trận Levenshtein, như trong câu trả lời JS của Arnauld

1: Nhiều byte hơn, vì nó không hoạt động nếu chuỗi đầu tiên là một ký tự.

2: Chuyển sang xây dựng các kết hợp trong ma trận Levenshtein.


+1 khi mất ít hơn 60 giây cho 6 từ ký tự như lần thử đầu tiên (thất bại) của tôi lol
HyperNeutrino

Câu trả lời tốt đẹp! +1 từ tôi. Vì tôi không bao giờ lập trình bằng Python, tôi thực sự không thể giúp bạn chơi gôn, ngoại trừ một điều: m+i+1có thể m-~i.
Kevin Cruijssen

Bạn có thể sử dụng tab thay vì dấu cách kép trên dòng 7.
Stephen

Bạn có thể nhận được tới 463 byte bằng cách giảm vòng lặp 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

Python 2 , 310 byte

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])

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

Sử dụng difflib.SequenceMatchertính toán căn chỉnh giữa hai chuỗi


Điều này dường như cung cấp một số kết quả không chính xác cho một số trường hợp thử nghiệm khác. Cụ thể hơn:"This_is_an_example_text","This_is_a_test_as_example"
Kevin Cruijssen

@KevinCruijssen thanx, tôi vừa sửa nó ^ _ ^
mdahmoune

Hay đấy, gj! Nhưng umm .. trường hợp thử nghiệm thứ ba (và thứ tư là tốt) cũng không may là không chính xác. Một trong hai dòng nên không được sửa đổi (ngoại trừ khoảng trắng ở đầu / cuối). Cả hai dòng hiện chứa khoảng trắng ở giữa.
Kevin Cruijssen

@KevinCruijssen thanx một lần nữa, tôi đang sửa nó
mdahmoune

1

Toán học, 250 256 259 384 byte

~ 0,00035 giây cho trường hợp mã java.

(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})&

Sử dụng: f["ABCDE", "ABCDF"]

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

Mã này dựa trên một thực tế SequenceAlignmenthoạt động theo mặc định trên

Với cài đặt mặc định SameityRules-> Automatic, mỗi trận đấu giữa hai yếu tố đóng góp 1 vào tổng điểm tương tự, trong khi mỗi điểm không khớp, chèn hoặc xóa đều đóng góp -1.

Cụ thể, việc tính điểm được tính theo M, AR, theo đó.

Thí dụ:

thí dụ


2
Hmm, tôi đã không bao giờ được lập trình trong Mathemetica, nhưng không cho nó có thể thay đổi i="";o="";p="";để i="";o=i;p=i;giảm 2 byte?
Kevin Cruijssen

2
Thế còn i=o=p=""?
DavidC

@DavidC Có tôi đã nhận ra điều đó và đã thay đổi nó. dù sao cũng cảm ơn bạn
Keyu Gan

1

D , 351 345 byte

-6 byte sox đến KevinCruijssen

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;}

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


Bạn có thể đánh gôn sáu byte bằng cách loại bỏ cái cuối cùng break;. Mặc dù +1, lần đầu tiên tôi thấy ngôn ngữ lập trình D.
Kevin Cruijssen
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.