Максимальна відстань Хеммінга серед списку прокладених струн


18

Відстань Хеммінга між двома струнами однакової довжини - це кількість позицій, на яких відповідні символи різні. Якщо струни не мають однакової довжини, відстань Хеммінга не визначається.

Виклик

Напишіть програму або функцію, яка знаходить найбільшу відстань Хеммінга серед усіх пар рядків зі списку рядків, підкладених відповідно до правил, описаних нижче.

Персонажі будуть зсередини a-zA-Z0-9.

Рядки можуть бути не однаковими за довжиною, тому для кожного порівняння коротша струна повинна бути прокладена так:

  • загортайте рядок спочатку стільки разів, скільки потрібно, щоб відповідати необхідній довжині
  • змінювати регістри букв щоразу, коли їх завершують (1-й, 3-й, 5-й тощо)
  • a-zA-Zпри обгортанні залишайте речі без змін

Наприклад, скажімо, вам потрібно прокладати рядок з 5 символів, ab9Cdщоб він закінчувався 18 символами. Ви закінчите:

ab9CdAB9cDab9CdAB9
     ^^^^^     ^^^

із ^додаванням під 1-й та 3-й обгортання, щоб виділити зміни в регістрі.

Введення-виведення

Формат вводу / виводу є гнучким. Можна припустити, що вхід має щонайменше два рядки, і що всі рядки матимуть щонайменше один символ.

Вихід - ціле число.

Правила

Це . Діють стандартні правила.

Тестові справи

[ "a", "b" ] => 1
[ "a", "b", "c" ] => 1
[ "a", "a", "c" ] => 1
[ "abc", "abcd" ] => 1
[ "abc12D5", "abC34d3", "ABC14dabc23DAbC89d"] => 17  
[ "a", "Aaa", "AaaA", "aAaAa", "aaaaaaaaaaaaaa", "AAaAA", "aAa" ] => 8
["AacaAc", "Aab"] => 2

Довідкова реалізація

Я перевірив приклади з (повністю без вольфу) R-кодом, який ви можете спробувати тут, щоб порівняти будь-які інші приклади, які ви можете спробувати зі своїм кодом.


1
міняйте регістри букв щоразу дивовижно, - хлопче, ця вимога буде болем для мого рішення ... Хоча мені подобається виклик, тому +1
Містер Xcoder

Схожий тест: ["AacaAc", "Aab"] => 2. Цілеспрямований гольф на мою відповідь «Джеллі» не зміг би цього випадку, але пройшов би всі інші.
Містер Xcoder

@ngm Відмінний виклик! +1
Дон Тисяча

Відповіді:


7

Желе , 20 байт

Не дуже задоволений цим. Має бути пограбованим, можливо, навіть до ~ 15 байт.

LÞŒcµṁ/sḢL$ŒsÐeFn)§Ṁ

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

або Перевірте тестовий набір!

Пояснення

LÞŒcµṁ / sḢL $ ŒsÐeFn) §Ṁ Повна програма або монадичне посилання. N = вхід. | Приклад: ["abc12D5", "abC34d3", "ABC14dabc23DAbC89d"]
LÞ Сортувати N за довжиною. | [['a', 'b', 'c', '1', '2', 'D', '5'], ['a', 'b', 'C', '3', '4 ',' d ',' 3 '], [' A ',' B ',' C ',' 1 ',' 4 ',' d ',' a ',' b ',' c ',' 2 ',' 3 ',' D ',' A ',' b ',' C ',' 8 ',' 9 ',' d ']] (в Jelly рядки - це список символів)
  Œc Неупорядковані пари: [x, y] для всіх різних x, y в N. | [[['a', 'b', 'c', '1', '2', 'D', '5'], ['a', 'b', 'C', '3', ' 4 ',' d ',' 3 ']], [[' a ',' b ',' c ',' 1 ',' 2 ',' D ',' 5 '], [' A ',' B ',' C ',' 1 ',' 4 ',' d ',' a ',' b ',' c ',' 2 ',' 3 ',' D ',' A ',' b ' , 'C', '8', '9', 'd']], [['a', 'b', 'C', '3', '4', 'd', '3'], ['A', 'B', 'C', '1', '4', 'd', 'a', 'b', 'c', '2', '3', 'D',
                        Тут, явно кажучи, я маю на увазі різні позиції. |
    µ) Карта з монадичним посиланням. |
     ṁ / Цвіль x як у. Тобто цикл x, поки не досягне довжини y. | [['a', 'b', 'c', '1', '2', 'D', '5'], ['a', 'b', 'c', '1', '2 ',' D ',' 5 ',' a ',' b ',' c ',' 1 ',' 2 ',' D ',' 5 ',' a ',' b ',' c ', '1'], ['a', 'b', 'C', '3', '4', 'd', '3', 'a', 'b', 'C', '3', '4', 'd', '3', 'a', 'b', 'C', '3']]
       sḢL $ Розділіть на шматки довжини х. | [[['a', 'b', 'c', '1', '2', 'D', '5']], [['a', 'b', 'c', '1' , '2', 'D', '5'], ['a', 'b', 'c', '1', '2', 'D', '5'], ['a', ' b ',' c ',' 1 ']], [[' a ',' b ',' C ',' 3 ',' 4 ',' d ',' 3 '], [' a ',' b ',' C ',' 3 ',' 4 ',' d ',' 3 '], [' a ',' b ',' C ',' 3 ']]]
           ŒsÐe Обміняйте випадки парних індексованих фрагментів (1-індексований). | [[['a', 'b', 'c', '1', '2', 'D', '5']], [['a', 'b', 'c', '1' , '2', 'D', '5'], ['A', 'B', 'C', '1', '2', 'd', '5'], ['a', ' b ',' c ',' 1 ']], [[' a ',' b ',' C ',' 3 ',' 4 ',' d ',' 3 '], [' A ',' B ',' c ',' 3 ',' 4 ',' D ',' 3 '], [' a ',' b ',' C ',' 3 ']]]
               F Згладьте. | [['a', 'b', 'c', '1', '2', 'D', '5'], ['a', 'b', 'c', '1', '2 ',' D ',' 5 ',' A ',' B ',' C ',' 1 ',' 2 ',' d ',' 5 ',' a ',' b ',' c ', '1'], ['a', 'b', 'C', '3', '4', 'd', '3', 'A', 'B', 'c', '3', '4', 'D', '3', 'a', 'b', 'C', '3']]
                n Векторизована нерівність з у. | [[[0, 0, 1, 1, 1, 1, 1]], [[1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 , 1, 1, 1]], [[1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1]]]
                  § Після закінчення карти підсумовуйте кожен масив bool (0 або 1). | [[5], [17], [14]]
                   Ṁ Максимум. | 17

Я абсолютно не знайомий з Jelly, але я думаю, що ти можеш опустити і все-таки отримати той самий максимум наприкінці.
Час Браун

@ChasBrown Цьфу, ні, мені це потрібно. В іншому випадку, замість того, щоб прошивати найкоротший до довжини найдовший, ṁ/він замість цього обрізає найдовший на довжину найкоротший у деяких випадках, чого ми не хочемо .... Думаю, тестові випадки занадто вдало обрані (і це досить прикрий збіг) ...
Містер Xcoder

@ChasBrown Як приклад, спробуйте ["AacaAc", "Aab"].
Містер Xcoder

Ага так, я бачу ... Мені потрібно навчитися ще трохи Желе ... :)
Час Браун

5

Python 2 , 86 байт

lambda a:max(sum(x!=y for x,y in zip((s+s.swapcase())*len(t),t))for s in a for t in a)

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

Дано два рядки, s,t, zip((s+s.swapcase())*len(t),t))буде список кортежів довжини , len(t)так як zipскорочуються найкоротший ітерацію. Якщо len(s)<len(t), тоді це "вирівнюється" sз заміною потрібного випадку, і ми обчислюємо sumрізні символи.

Якщо len(t)<=len(s)тоді результат sumбуде меншим або рівним тому, sumякби ми оцінювали t,s; тому це не впливає на результат, maxщо виникає в цьому випадку.


Ви можете використовувати y!=замість цього, !=yщоб зберегти 1 байт
Містер Xcoder

@Містер. Xcoder: Thx, але я закінчив кардинально переробляти своє рішення ...
Chas Brown


3

Желе , 19 байт

WṁŒsÐeF=ċ0
LÞŒcç/€Ṁ

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

LÞŒcç/€Ṁ
LÞ         Sort by length
  Œc       unordered pairs
      €    to each of the pairs
    ç/     find the hamming distance with molding and swapping case (helper link)
       Ṁ   maximum

WṁŒsÐeF=ċ0
W            wrap the shorter string
 ṁ           repeat this string once for each character in the second string
    Ðe       for every other repeated string
  Œs         swap case
      F      flatten
       =     characterwise equality check between the two strings. If the first
             string is longer, the leftover characters are appended to the result.
             e.g. 'abABab' and 'xbA' give [0,1,1,'B','a','b']
        ċ0   count the number of 0s, giving the Hamming distance.

2

Рубі , 89 82 байт

Створює поперечний добуток списку введення проти себе перед обчисленням відстані Хеммінга кожної пари, використовуючи метод дублювання, подібний до відповіді Часа Брауна . Ruby не може поєднувати рядки разом або додавати булі без додаткових накладних витрат, тому для цього стає необхідним повторне введення пари рядків вручну.

-7 байт від ГБ.

->a{a.product(a).map{|s,t|(0...w=t.size).count{|i|(s+s.swapcase)[i%w]!=t[i]}}.max}

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



2

Java 10 ,748 740 667 666 616 байт

Це має бути найгустішим і нечитабельним, але все ж найдовшим гольфом, який я коли-небудь придумав.

Метод виклику h(String[])з явним масивом (без var args): наприклад,

h(new String[] {"a", "b", "c"});

повертає 1.

char e(boolean w,char c){return(char)(w&(64<c&c<91|96<c&c<123)?c^32:c);}String p(String s,int l){var p="";int m=s.length(),n=l/m,r=l%m,i=0,j=0;var w=1<0;for(;i<n;++i,w=!w)for(char c:s.toCharArray())p+=e(w,c);for(;j<r;)p+=e(w,s.charAt(j++));return p;}int d(String s,String t){int l=s.length(),n=0,i=0;for(;i<l;)if(s.charAt(i)!=t.charAt(i++))++n;return n;}int h(String s,String t){int l=s.length(),m=t.length();return l>m?d(s,p(t,l)):l<m?d(p(s,m),t):d(s,t);}int h(String[]s){int l=s.length,i=0,j;int[]n=new int[l*l];for(;i<l;++i)for(j=i;++j<l;)n[i*l+j]=h(s[i],s[j]);return java.util.Arrays.stream(n).max().getAsInt();}

Ви можете спробувати онлайн !

Негольфірованний і прокоментував:

// Encode the character (swap case)
char e(boolean w, char c) {
    return (char) (w & (64 < c & c < 91 | 96 < c & c < 123) ? c ^ 32 : c);
}

// Pad the string to desired length
String p(String s, int l) {
    var p = "";
    int m = s.length(), n = l / m, r = l % m, i = 0, j = 0;
    var w = 1 < 0;
    for (; i < n; ++i, w = !w)
        for (char c : s.toCharArray())
            p += e(w, c);
    for (; j < r;)
        p += e(w, s.charAt(j++));
    return p;
}

// Calculate the actual hamming distance between two same-length strings
int d(String s, String t) {
    int l = s.length(), n = 0, i = 0;
    for (; i < l;)
        if (s.charAt(i) != t.charAt(i++))
            ++n;
    return n;
}
// Pad the strings as needed and return their hamming distance
int h(String s, String t) {
    int l = s.length(), m = t.length();
    return l > m ? d(s, p(t, l)) : l < m ? d(p(s, m), t) : d(s, t);
}

    // Dispatch the strings and gather their hamming distances, return the max
int h(String[] s) {
    int l = s.length, i = 0, j;
    int[] n = new int[l * l];
    for (; i < l; ++i)
        for (j = i; ++j < l;)
            n[i * l + j] = h(s[i], s[j]);
    return java.util.Arrays.stream(n).max().getAsInt();
}

Я знаю, що кращого рішення можна досягти, особливо це стосується частини спарювання струн.

EDIT : обріжте 8 байт, змінивши розмір масиву int hammingDistance()на квадрат заданої кількості рядків. Він також фіксує ArrayIndexOutOfBoundsкинуте в одному з тестових випадків.

EDIT 2 : Збережено 33 байти завдяки коментарям Кевіна Круїссена : декларація класу видалено, імена скорочено до 1 знака, змінено операторів тощо.

EDIT 3 : Збережіть 1 байт і дістаньте затверджений Сатаною рахунок, змінивши метод з var-arg для масиву.

EDIT 4 : Збережіть ще 50 байт завдяки Kevin Cruijssen , знову: оновіть версію Java з 8 на 10, щоб використовувати varключове слово, видалений StringBuilderекземпляр тощо.


1
У мене не так багато часу, але деякі основні речі для гри в гольф: Кинь клас, достатньо лише методів. Змініть всі назви методу та змінних на одиничні байти. Тож замість hammingDistanceвикористання dчи іншої невикористаної змінної. Більшість ваших &&може бути &і ||може бути |. c^' 'може бути c^32. boolean w = false;може бути boolean w=0>1;. i=0в циклі ініціалізацію можна видалити і змінити ,i,jна ,i=0,j. ++jїх можна видалити та ++додати до .charAt(j++). .toString()може бути +"". for(j=i+1;j<l;++j)може бути for(j=0;++j<l;). І т. Д.
Кевін Кройсейсен

1
Поради щодо гольфу на Яві та Поради щодо гольфу на <всіх мовах> можуть також бути цікавими для прочитання. :)
Кевін Круїссен

Спасибі! Це якийсь приємний підйом на байт. Дякую за посилання, я також розглядаю його та редагую якнайшвидше!
joH1

1
Оголошено за схвалення сатани. xD Ще кілька дрібниць: StringBuilderможе бути StringBuffer(якщо ви переходите на Java 10, це може бути var b=new StringBuffer(l);. Можливо, booleanа charтакож може бути var. Якщо у вас немає Java 10 локально, вона доступна в TIO ). Крім того, for(;i<n;++i){for(char c:s.toCharArray())b.append(e(w,c));w=!w;}можна for(;i++<n;w=!w)for(char c:s.toCharArray())b.append(e(w,c));. І я впевнений, що ви можете видалити StringBufferповністю і просто використовувати Stringі +=замість цього append.
Кевін Кройсейсен

Людина, кілька місяців чистого коду та хороших методів кодування змусили мене забути, як навіть гольф! Я оновлю свою відповідь і включу TIO.
joH1

1

05AB1E , 33 29 байт

Ćü)€é©εćDš«s`g∍}®€¤‚ø€ζ€€Ë_Oà

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Можна, швидше за все, вдвічі зменшити кількість байтів, але це працює.

Пояснення:

Ć           # Enclose the input-list (adding the first item to the end of the list)
            #  i.e. ['ABC1','abcD','abCd32e'] → ['ABC1','abcD','abCd32e','ABC1']
 ü)         # Pair-vectorize each of them
            #  i.e. ['ABC1','abcD','abCd32e','ABC1']
            #   → [['ABC1','abcD'],['abcD','abCd32e'],['abCd32e','ABC1']]
   ێ       # Sort each pair by length
            #  i.e. [['ABC1','abcD'],['abcD','abCd32e'],['abCd32e','ABC1']]
            #   → [['ABC1','abcD'],['abcD','abCd32e'],['ABC1','abCd32e']]
     ©      # Store this list in the register to re-use later on
ε        }  # Map each inner list in this list to:
 ć          # Head extracted
            #  i.e. ['abcD','abCd32e'] → 'abcD' and ['abCd32e']
  Dš        # Duplicate it, and swap the capitalization of the copy
            #  i.e. 'abcD' → 'ABCd'
    «       # Then merge it together
            #  i.e. 'abcD' and 'ABCd' → 'abcDABCd'
     s`     # Swap so the tail-list is at the top of the stack, and get it's single item
            #  i.e. ['abCd32e'] → 'abCd32e'
       g    # Get the length of that
            #  i.e. 'abCd32e' → 7
           # Extend/shorten the string to that length
            #  i.e. 'abcDABCd' and 7 → 'abcDABC'
®           # Get the saved list from the register again
 €¤         # Get the tail from each
            #  i.e. [['ABC1','abcD'],['abcD','abCd32e'],['abCd32e','ABC1']]
            #   → ['abcD','abCd32e','abCd32e']
           # Pair it with the other list
            #  i.e. ['ABC1','abcDABC','ABC1abc'] and ['abcD','abCd32e','abCd32e']
            #   → [['ABC1','abcDABC','ABC1abc'],['abcD','abCd32e','abCd32e']]
    ø       # Zip it, swapping rows / columns
            #  i.e. [['ABC1','abcDABC','ABC1abc'],['abcD','abCd32e','abCd32e']]
            #   → [['ABC1','abcD'],['abcDABC','abCd32e'],['ABC1abc','abCd32e']]
     €ζ     # And then zip each pair again
            #  i.e. [['ABC1','abcD'],['abcDABC','abCd32e'],['ABC1abc','abCd32e']]
            #   → [['Aa','Bb','Cc','1D'],['aa','bb','cC','Dd','A3','B2','Ce'],['Aa','Bb','CC','1d','a3','b2','ce']]
           # Then for each inner list
           #  And for each inner string
  Ë         #   Check if all characters are the same
            #    i.e. 'aa' → 1
            #    i.e. 'cC' → 0
   _        # And inverse the booleans
            #  i.e. [['Aa','Bb','Cc','1D'],['aa','bb','cC','Dd','A3','B2','Ce'],['Aa','Bb','CC','1d','a3','b2','ce']]
            #   → [[1,1,1,1],[0,0,1,1,1,1,1],[1,1,0,1,1,1,1]]
O           # Then sum each inner list
            #  i.e. [[1,1,1,1],[0,0,1,1,1,1,1],[1,1,0,1,1,1,1]] → [4,5,6]
 à          # And take the max as result
            #  i.e. [4,5,6] → 6

1

Java 11, 387 байт

a->{int l=a.length,i=l,t,j=0,C[]=new int[l];var p=new String[l][2];for(;i-->0;p[i][0]=a[t>0?i:j],p[i][1]=a[t>0?j:i])t=a[i].length()<a[j=-~i%l].length()?1:0;i=0;for(var P:p){var s="";for(var x:P[0].getBytes())s+=(char)(x>64&x<91|x>96&x<123?x^32:x);for(P[0]=repeat(P[0]+s,t=P[1].length()).substring(0,t);t-->0;)if(P[0].charAt(t)!=P[1].charAt(t))C[i]++;i++;}for(int c:C)j=c>j?c:j;return j;}

Спробуйте в Інтернеті. (ПРИМІТКА. Оскільки Java 11 ще не є TIO, String.repeat(int)емулюється як repeat(String,int)для того ж числа байтів.)

Пояснення:

a->{                      // Method with String-array parameter and integer return-type
  int l=a.length,         //  Length of the input-array
      i=l,                //  Index-integer, starting at the length
      t,j=0,              //  Temp-integers
      C[]=new int[l];     //  Count-array the same size as the input
  var p=new String[l][2]; //  String-pairs array the same size as the input
  for(;i-->0              //  Loop `i` in the range [`l`, 0)
      ;                   //    After every iteration:
       p[i][0]=           //     Set the first String of the pair at index `i` to:
               a[t>0?i:j],//      The smallest of the `i`'th or `j`'th Strings of the input-array
       p[i][1]=           //     And set the second String of the pair at index `i` to:
               a[t>0?j:i])//      The largest of the `i`'th or `j`'th Strings of the input-array
    t=a[i].length()<      //    If the length of the `i`'th item is smaller than
      a[j=-~i%l].length()?//    the length of the `i+1`'th item
                          //    (and set `j` to this `i+1` with wrap-around to 0 for the last item
       1                  //     Set `t` to 1 as flag
      :                   //    Else:
       0;                 //     Set `t` to 0 as flag
                          //  We've now created the String pairs, where each pair is sorted by length
  i=0;                    //  Reset `i` to 0
  for(var P:p){           //  Loop over the pairs
    var s="";             //   Temp-String starting empty
    for(var x:P[0].getBytes())
                          //   Loop over the characters of the first String of the pair
      s+=                 //    Append the temp-String with:
         (char)(x>64&x<91|x>96&x<123?
                         //      If the current character is a letter:
           x^32          //       Swap it's case before appending it to `s`
         :               //      Else (not a letter):
          x);            //       Append it to `s` as is
    for(P[0]=            //    Now replace the first String with:
        repeat(P[0]+s,   //     The first String appended with the case-swapped first String
               t=P[1].length())
                         //     Repeated `t` amount of times,
                         //     where `t` is the length of the second String of the pair
        .substring(0,t); //     And then shorten it to length `t`
        t-->0;)          //    Inner loop over the character of the now same-length Pairs
      if(P[0].charAt(t)!=P[1].charAt(t))
                         //     If the characters at the same indices in the pair are not equal
        C[i]++;          //      Increase the counter for this pair by 1
    i++;}                //    After every iteration of the outer loop,
                         //    increase `i` by 1 for the next iteration
  for(int c:C)           //  Now loop over the calculated counts
    j=c>j?c:j;           //   And set `j` to the maximum
  return j;}             //  And finally return this maximum `j` as result

1

R , 173 байт

function(x,U=utf8ToInt,N=nchar)max(combn(x,2,function(z,v=z[order(N(z))])sum(U(substr(Reduce(paste0,rep(c(v[1],chartr('A-Za-z','a-zA-Z',v[1])),n<-N(v[2]))),1,n))!=U(v[2]))))

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

@ngm: Я спробував усе, щоб пограти у ваш код (з моїми важкими налаштуваннями, звичайно), але, як ви добре знаєте, R не дуже голий у маніпулюванні струнами: P


Б'юсь об заклад, що це може бути нижче 150 байт, але я не впевнений, наскільки це ще.
Джузеппе

@Giuseppe: Я підозрюю, що це теж…, але я не дуже добре пишу маніпуляційні коди з короткими рядками, і R мені не дуже допомагає: D
digEmAll

@digEmAll Я не збираюся намагатися вирішити власну проблему, але мало можливостей, outerщоб отримати всі комбінації та робити модульну арифметику на кодових точках замість chartr.
ngm

@ngm: можливо ... Я відкинув арифметичний підхід, оскільки не зміг знайти коротке рішення / формулу, щоб змінити регістр літер, не торкаючись цифр ...
digEmAll
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.