私は変化が好きではありません!


19

入力:

改行または空白なしの2つの文字列。

出力:

両方の入力文字列は別々の行にあり、必要に応じてスペースを使用して、2つの文字列のいずれかに追加します。文字と三行目はARM表す追加除去改変、及び不変

上部または下部の入力文字列にスペースを追加します(必要な場合)。このチャレンジの目標は、ARM可能な限り少ない変化()で出力することです。これは、レーベンシュタイン距離とも呼ばれます。

例:

入力文字列がABCDEFAFBECDであるとすると、出力は次のようになります。

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

ただし、これらの変更には4つの変更しかないA B CDEF\nAFBECD \n A A RRため、このチャレンジの有効な出力のみです。

チャレンジルール:

  • 入力文字列には改行やスペースが含まれないと想定できます。
  • 2つの入力文字列の長さは異なっていてもかまいません。
  • 2つの入力文字列のいずれかは、オプションの先頭/末尾のスペースを除いて、そのままにしておく必要があります。
  • ご使用の言語がASCII以外をサポートしていない場合、入力には印刷可能なASCII文字のみが含まれると想定できます。
  • 入力および出力形式は柔軟です。3つの個別の文字列、文字列配列、改行を含む単一の文字列、2D文字配列などを持つことができます。
  • の代わりに別のものを使用することは許可されていますが、使用したものARM(つまり123、またはabc.など)を明記してください。
  • 同じ量の変更で複数の有効な出力が可能な場合(ARM)、可能な出力の1つを出力するか、すべてを出力するかを選択できます。
  • 先頭と末尾のスペースはオプションです。

    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 


同じ距離の配置が複数ある場合、そのうちの1つだけを出力しても問題ありませんか?
AdmBorkBork

@AdmBorkBorkはい、可能な出力の1つだけが実際に意図された出力です(ただし、利用可能なすべてのオプションを出力することもできます)。これをチャレンジルールで明確にします。
ケビンCruijssen

@Arnauld先行スペースに関する規則を削除したため、先行スペースと後続スペースはオプションであり、変更されていない行で有効です。(これは、回答の最後のテストケースが完全に有効であることを意味します。)
ケビンCruijssen

1
@Ferrybigあぁ、説明ありがとう。しかし、この課題に関しては、印刷可能なASCIIをサポートするだけで十分です。さらにサポートしたい場合は、ゲストになってください。しかし、与えられたテストケースで機能する限り、そのような複数の文字で構成されるグラフェンクラスターの未定義の動作で問題ありません。:)
ケビン・クルーッセン

回答:


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"。3つの文字列のリストを返します。これは普通のレーベンシュタイン距離問題に対する私の再帰的解法の拡張です。

説明:

取得するために最小限の変更を計算するため"xyz""yw"、我々は両方の文字列の最初の文字に焦点を当てます。次の3つの可能性があります。

  • 削除:ドロップx最初の文字列から再帰的に取得するための修正を計算"yz"します"yw"。これにより、3行が生成され["yz","yw"," M"]ます。x最初のものに、2番目とR3 番目にスペースを追加します。我々が得る
    xyz
    yw
    RM
  • 追加:y 2番目の文字列からドロップしてcomputeを実行する"xyz" & "w"と、結果が返されます["xyz","w","MRR"]。1行y目、2 A行目、3行目にスペースを追加する必要があります。
     xyz
    yw
    AMRR
  • 変更/変更なし:両方の文字列の最初の文字を削除し、残りの文字列間の最小限の変更を計算する必要があるため、これら2つのケースを組み合わせることができます"yz" & "w"。結果に["yz","w","MR"]x最初yに2行目を追加します。最後の行についてのみ、最初の文字が同じかどうかを区別する必要があります。同じ場合、3行目にスペースが追加されます。それ以外の場合(この場合のようにx \= y)、Mが追加されます。
    xyz
    yw
    MMR

これらの3つの候補から、変更が最も少ないものを見つける必要があります。これは、3行目に最も多くのスペースがあることに相当します。したがって、各候補s(3つの文字列のリスト)をtuple に変換します([1|' '<-s!!2],s)。ここでs、2番目のコンポーネントとして表示され、最初のコンポーネントはss!!20-indexingのため)3番目の行のスペースと同じ数の要素を持つリストです。リスト要素1が使用されますが、実際の要素は、すべての候補に対して同じである限り無関係です。

全体として、これはタプルのリストを生成します

[([1]、["xyz"、 "yw"、 "RM"])、([]、["xyz"、 "yw"、 "AMRR"])、([]、["xyz"、 " yw "、" MMR "])]
ビルドでmaximum選択し、左から右に成分ごとであるタプルは辞書的に比較して、このリストの最大の要素、、。[1]大きい[]最初のタプルが選択され、そしてsndラインのリストはタプルの、ある成分の第二を返します。


1 +15バイトAは、文字列の最後のR-changesが-changes として表示されるバグを修正します


笑これにより、ユーザースクリプトはこれが1バイトであると考えるようになります
-HyperNeutrino

8

JavaScript(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'

最終的な修正文字列は、レーベンシュタイン距離とともに右下のセルに保存されます。


同じ私はに関する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バイト節約しました。ありがとう!
アーナウルド

4

Python 2548 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 '

レーベンシュタインマトリックスを作成し、逆方向に走査して操作を見つけますArnauldのJSの回答のように、Levenshteinマトリックスと同時にoperation-stringを作成します

1:最初の文字列が単一の文字である場合は機能しなかったため、より多くのバイト。

2:レーベンシュタイン行列の組み合わせの構築に切り替えました。


私の最初の(失敗した)試みのような6文字の単語に対して60秒未満かかった+1
HyperNeutrino

いい答えだ!私から+1。Pythonの私で私は決してプログラムが本当にゴルフであなたを助けることができないので、一つのことを除いて:m+i+1可能m-~i
ケビンクルーッセン

あなたは、7行目のタブの代わりに、二重のスペースを使用することができます
スティーブン

あなたはに取得することができます463バイトの 1行に誘い込むループを減らすことによって: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
OVS

1

Python 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て、2つの文字列間のアライメントを計算します


これにより、他のテストケースの一部に対して誤った結果が得られるようです。その他の特定:"This_is_an_example_text","This_is_a_test_as_example"
ケビンCruijssen

@KevinCruijssen thanx、私はそれを修正しました^ _ ^
mdahmoune

いいね、gj!しかし残念ながら、3番目のテストケース(および4番目のテストケース)も間違っています。2行のうちの1行は変更しないでください(先頭/末尾のスペースを除く)。現在、両方の行の中央にスペースが含まれています。
ケビンCruijssen

@KevinCruijssenもう一度、私はそれを修正しています
-mdahmoune

1

Mathematica、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では、2つの要素間の各一致が合計類似度スコアに1を提供し、各不一致、挿入、または削除が-1を提供します。

つまり、スコアリングはMAおよびによって計算されRます。

例:

例


2
うーん、私は数学でプログラミングしたことはありませんが、2バイトを減らすために変更i="";o="";p="";することはできませんi="";o=i;p=i;か?
ケビンCruijssen

2
どうi=o=p=""
DavidC

@DavidCはい、私はそれを認識し、すでに変更していました。とにかくありがとう
Keyuガン

1

D351 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を見ている最初の時間
ケビンCruijssen
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.