Мені не подобаються зміни!


19

Вхід:

Два рядки без нових рядків або пробілів.

Вихід:

Обидва вхідних рядка в окремих рядках, з пробілами, де необхідно для одного з двох рядків. І третій рядок з символами A, R, Mі , що представляє собою додана , видалена , змінена , і без змін .

Ми додаємо пробіли у верхній або нижній рядок введення (якщо це потрібно). Мета цього виклику - вивести з найменшою ARMможливою кількістю змін ( ), також відомих як відстань Левенштейна .

Приклад:

Скажімо, вхідними рядками є ABCDEFі 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.
  • Формат введення та виведення є гнучким. Ви можете мати три окремі рядки, масив String, один рядок з новими рядками, двовимірний масив символів тощо.
  • Вам дозволяється використовувати щось інше замість 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 Так, лише один із можливих результатів - це дійсно призначений вихід (хоча виведення всіх доступних опцій також нормальне). Я поясню це в правилах виклику.
Кевін Кройсейсен

@Arnauld Я видалив правило про провідні пробіли, тому провідні та трейлінг простори є необов’язковими та дійсними у немодифікованому рядку. (Що означає, що останній тестовий випадок у вашій відповіді цілком справедливий.)
Кевін Круїссен

1
@Ferrybig Ну добре, дякую за пояснення. Але що стосується цього виклику, то лише підтримки ASCII для друку вже достатньо. Якщо ви хочете підтримати більше, будьте моїм гостем. Але поки це працює для тестових випадків, я даю нормальну поведінку для кластерів графена, що складаються з більш ніж 1 символу. :)
Кевін Круїссен

Відповіді:


5

Haskell , 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 до третього. Ми отримуємо
    ксиз
    тис
    RM
  • Додавання: випадання yз другого рядка та обчислення "xyz" & "w", що повертає результат ["xyz","w","MRR"]. Нам потрібно додати пробіл у першому рядку, yу другому таA третьому рядку:
     ксиз
    тис
    AMRR
  • Модифікований / Без змін: Ми можемо об'єднати ці два випадки , тому що обидва вимагають , щоб відкинути перший символ обох рядків і обчислити мінімальні зміни між іншими рядками: "yz" & "w". До результату["yz","w","MR"] додаємо xна першому і yна другому рядку. Тільки для останнього рядка нам потрібно розрізнити, чи є початкові символи однаковими. Якщо вони однакові, до третього рядка додається пробіл, інакше (як у цьому випадку тому, що x \= y)M додається:
    ксиз
    тис
    MMR

З цих трьох кандидатів нам потрібно знайти одного з найменшими модифікаціями. Це еквівалентно тому, що в третьому рядку є найбільше пробілів. Тому ми перетворюємо кожного кандидата s(список із трьох рядків) у кортеж ([1|' '<-s!!2],s), де sвідображається як другий компонент, а перший компонент - список із такою кількістю елементів, скільки є пробілів у третьому рядку s(s!!2 через 0-індексації). Як елемент списку 1використовується, але фактичний елемент не має значення, якщо він однаковий для всіх кандидатів.

Загалом це дає список кортежів

[([1], ["xyz", "yw", "RM"]), ([], ["xyz", "yw", "AMRR"]), ([], ["xyz", " yw "," MMR "])]
Вбудований maximumвибирає найбільший елемент з цього списку, в якому кортежі порівнюються лексикографічно, тобто покомпонентно зліва направо. Оскільки [1]більший за [], вибирається перший кортеж і sndповертає другий компонент, тобто список рядків кортежу.


1 +15 байт, щоб виправити помилку, де- Aзміни в кінці рядка відображатимуться у вигляді R-змін


lol, це змушує користувачів сценарію думати, що це 1 байт
HyperNeutrino

8

JavaScript (ES6), 413 ... 343 342 байт

Збережено 5 байт шляхом налаштування індексів циклу, як це запропонував @KevinCruijssen

Вводиться як 2 рядки в синтаксисі currying. Повертає масив з 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]]}
редакції

1
@KevinCruijssen Я врятував 5 байт, зробивши вашу ідею на крок далі. Спасибі!
Арнольд

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 '

Працює над створенням матриці Левенштейна, а потім переходом назад, щоб знайти операції . Тепер будується операційний рядок одночасно з матрицею Левенштейна, як у відповіді Арнальда JS

1: Більше байтів, оскільки це не спрацювало, якщо перший рядок був одним символом.

2: Переключився на побудову комбінацій у матриці Левенштейна.


+1 за зайняття менше ніж 60 секунд на 6 символьних слів, як моя перша (невдала) спроба лол
HyperNeutrino

Гарна відповідь! +1 від мене. Оскільки я ніколи не програмую в Python, я не можу реально допомогти тобі в гольфі, за винятком одного: m+i+1можна m-~i.
Кевін Кройсейсен

Ви можете використовувати вкладку замість подвійних пробілів у рядку 7.
Стівен

Ви можете дістатись до 463 байтів , зменшивши цикл 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 байт

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"
Кевін Круїссен

@KevinCruijssen thanx, я щойно це виправив ^ _ ^
mdahmoune

Приємно, гж! Але гмм .. третій тестовий випадок (і четвертий також) також, на жаль, невірний. Один з двох рядків має бути немодифікованим (за винятком проміжних / кінцевих пробілів). В даний час обидва рядки містять пробіли посередині.
Кевін Кройсейсен

@KevinCruijssen thanx знову, я це виправляю
mdahmoune

1

Математика, 250 256 259 384 байт

~ 0,00035 секунд для корпусу коду 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})&

Використання: f["ABCDE", "ABCDF"]

Спробуйте в Інтернеті!

Код заснований на тому, що SequenceAlignmentпрацює за замовчуванням на

За замовчуванням налаштування SličityRules-> Automatic, кожен збіг між двома елементами вносить 1 в загальний показник схожості, тоді як кожна невідповідність, вставлення чи видалення сприяє -1.

А саме, оцінка балів обчислюється, відповідно M, Aі R, відповідно.

Приклад:

приклад


2
Хм, я ніколи не запрограмований в Mathemetica, але не можливо змінити , i="";o="";p="";щоб i="";o=i;p=i;зменшити 2 байта?
Кевін Кройсейсен

2
Про що i=o=p=""?
DavidC

@DavidC Так, я це вже зрозумів і змінив. все одно дякую
Кейу Ган

1

D , 351 345 байт

-6 байт ніж в 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;}

Спробуйте в Інтернеті!


Ви можете пограти в шість байтів, видаливши останній break;. Хоча +1, вперше я бачу мову програмування D.
Кевін Круїссен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.