Jarak Hamming maksimum di antara daftar string berlapis

18

Jarak Hamming antara dua string dengan panjang yang sama adalah jumlah posisi di mana karakter yang sesuai berbeda. Jika string tidak memiliki panjang yang sama, jarak Hamming tidak ditentukan.

Tantangan

Tulis program atau fungsi yang menemukan jarak Hamming terbesar dari semua pasangan string dari daftar string, diisi seperti yang dipersyaratkan sesuai dengan aturan yang dijelaskan di bawah ini.

Karakter akan berasal dari dalam a-zA-Z0-9.

Panjang string mungkin tidak sama, jadi untuk setiap perbandingan, string yang lebih pendek harus diisi sebagai berikut:

  • bungkus tali dari awal sebanyak yang diperlukan untuk mencocokkan panjang yang dibutuhkan
  • mengubah huruf-huruf setiap pembungkus waktu ganjil (1, 3, 5, dll.)
  • biarkan barang-barang di luar a-zA-Ztidak berubah saat dibungkus

Misalnya, Anda perlu membuat string 5 karakter ab9Cdagar berakhir dengan 18 karakter. Anda akan berakhir dengan:

ab9CdAB9cDab9CdAB9
     ^^^^^     ^^^

dengan ^menambahkan di bawah wraps 1 dan 3 untuk menyoroti perubahan huruf.

Input output

Format input / output fleksibel. Anda dapat mengasumsikan input memiliki setidaknya dua string, dan bahwa semua string memiliki setidaknya satu karakter.

Outputnya adalah integer.

Aturan

Ini adalah . Aturan standar berlaku.

Uji kasus

[ "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

Implementasi referensi

Saya menguji contoh-contoh dengan kode R (yang sama sekali tidak dikenali) yang dapat Anda coba di sini untuk membandingkan contoh lain yang mungkin Anda coba dengan kode Anda.

ngm
sumber
1
ubah kasus huruf setiap kali dibungkus aneh - Oh nak, persyaratan ini akan
menyulitkan
Kasus uji yang disarankan: ["AacaAc", "Aab"] => 2. Sebuah golf bertujuan untuk jawaban Jelly saya akan gagal dalam kasus itu, tetapi akan melewati semua yang lain.
Tn. Xcoder
@ ngm Tantangan luar biasa! +1
Don Thousand

Jawaban:

7

Jelly , 20 byte

Tidak begitu senang dengannya. Harus bisa golf, bahkan hingga ~ 15 byte.

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

Cobalah online!

atau Lihatlah test suite!

Penjelasan

LÞŒcμṁ / sḢL $ ŒsÐeFn) §Ṁ Program penuh atau tautan monadik. N = input. | Contoh: ["abc12D5", "abC34d3", "ABC14dabc23DAbC89d"]
LÞ Sortir N berdasarkan panjangnya. | [['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 ']] (dalam Jelly, string adalah daftar karakter)
  Œc Pasangan tidak berurutan: [x, y] untuk semua x yang berbeda, y dalam 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',
                        Di sini, secara berbeda, maksud saya di posisi yang berbeda. |
    µ) Peta dengan tautan monadik. |
     ṁ / Cetakan x seperti y. Yaitu, siklus x sampai mencapai panjang 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 $ Membagi menjadi potongan dengan panjang x. | [[['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 ']]]
           SwsÐe Tukar kasus potongan yang diindeks secara merata (1-diindeks). | [[['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 ']]]
               Ratakan. | [['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 Ketidaksetaraan vektor dengan y. | [[[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, 1]], [[1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1]]]
                  § Setelah mengakhiri peta, jumlah setiap bool (0 atau 1) array. | [[5], [17], [14]]
                   Ṁ Maksimum. | 17
Tuan Xcoder
sumber
Saya benar-benar tidak terbiasa dengan Jelly, tapi saya pikir Anda bisa menghilangkan dan masih mendapatkan hasil maksimal yang sama di akhir.
Chas Brown
@ ChasBrown Ugh, tidak, aku harus butuh itu. Kalau tidak, alih-alih mengisi yang terpendek dengan panjang yang terpanjang, ṁ/sebaliknya akan memotong terpanjang ke panjang yang terpendek dalam beberapa kasus, yang bukan apa yang kita inginkan .... Saya kira kasus uji terlalu baik dipilih (dan ini kebetulan yang agak disayangkan) ...
Tn. Xcoder
@ ChasBrown Sebagai contoh, coba ["AacaAc", "Aab"].
Tn. Xcoder
Ah ya, saya mengerti ... Saya perlu belajar saya lebih banyak tentang Jelly ... :)
Chas Brown
5

Python 2 , 86 byte

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)

Cobalah online!

Mengingat dua string, s,t, zip((s+s.swapcase())*len(t),t))akan menjadi daftar tupel panjang len(t)sejak zipmemotong ke terpendek iterable. Jika len(s)<len(t), maka ini "pad out" sdengan swap kasus yang diinginkan dan kami menghitung sumkarakter yang berbeda.

Jika len(t)<=len(s), maka hasilnya sumakan kurang dari atau sama dengan sumjika kita mengevaluasi t,s; sehingga tidak berpengaruh pada hasil maxdalam kasus itu.

Chas Brown
sumber
Anda dapat menggunakan y!=alih-alih !=ymenyimpan 1 byte
Mr. Xcoder
@Pak. Xcoder: Thx, tapi akhirnya saya mengerjakan ulang solusi saya ...
Chas Brown
3

Jelly , 19 byte

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

Cobalah online!

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.
dylnan
sumber
2

Ruby , 89 82 byte

Menciptakan produk silang dari daftar input terhadap dirinya sendiri sebelum menghitung jarak Hamming masing-masing pasangan, menggunakan metode duplikasi yang mirip dengan jawaban Chas Brown . Namun, Ruby tidak dapat mengaitkan string atau menambahkan boolean tanpa overhead tambahan, sehingga menjadi perlu untuk mengulangi melalui string secara manual sebagai gantinya.

-7 byte dari GB.

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

Cobalah online!

Nilai Tinta
sumber
1
82 byte
GB
2

Java 10 ,748 740 667 666 616 byte

Ini harus menjadi yang paling padat dan tidak dapat dibaca, namun golf terpanjang yang pernah saya miliki.

Metode panggilan h(String[])dengan array eksplisit (tanpa argumen): misalnya,

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

kembali 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();}

Anda dapat mencobanya secara online !

Tidak dikumpulkan dan berkomentar:

// 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();
}

Saya tahu solusi yang lebih baik dapat dicapai, terutama untuk bagian pemasangan string.

EDIT : mencukur 8 byte dengan mengubah ukuran array int hammingDistance()ke kuadrat dari jumlah string yang diberikan. Ini juga memperbaiki yang ArrayIndexOutOfBoundsdilemparkan ke dalam salah satu kasus uji.

EDIT 2 : Disimpan 33 byte berkat komentar Kevin Cruijssen : deklarasi kelas dihapus, nama disingkat menjadi 1 char, operator berubah, dll.

EDIT 3 : Simpan 1 byte dan raih skor Setan yang disetujui dengan mengubah metode dengan var-arg ke array.

EDIT 4 : Simpan 50 byte lagi berkat Kevin Cruijssen , lagi: perbarui versi Java dari 8 hingga 10 untuk menggunakan varkata kunci, StringBuildercontoh yang dihapus , dll.

joH1
sumber
1
Saya tidak punya banyak waktu, tetapi beberapa hal mendasar untuk bermain golf: Jatuhkan kelas, hanya metode yang cukup. Ubah semua nama metode dan variabel menjadi satu byte. Jadi, alih-alih hammingDistancegunakan datau variabel lain yang tidak digunakan. Sebagian besar dari Anda &&bisa &dan ||bisa |. c^' 'bisa c^32. boolean w = false;bisa boolean w=0>1;. i=0inisialisasi loop dapat dihapus dan mengubah ,i,jke ,i=0,j. ++jdapat dihapus dan ++dapat ditambahkan ke .charAt(j++). .toString()bisa +"". for(j=i+1;j<l;++j)bisa for(j=0;++j<l;). Dll.
Kevin Cruijssen
1
Tips untuk bermain golf di Jawa dan Tips untuk bermain golf di <semua bahasa> mungkin juga menarik untuk dibaca. :)
Kevin Cruijssen
Terima kasih! Itu beberapa byte-lifting yang bagus. Terima kasih atas tautannya, saya melihatnya dan akan mengedit secepatnya!
joH1
1
Terpilih untuk skor Setan yang disetujui. xD Beberapa hal yang lebih kecil: StringBuilderbisa StringBuffer(jika Anda beralih ke Jawa 10 bisa var b=new StringBuffer(l);The. booleandan charkemudian juga menjadi varJika Anda tidak memiliki Java 10 lokal,. itu tersedia di TIO ). Selain itu, for(;i<n;++i){for(char c:s.toCharArray())b.append(e(w,c));w=!w;}bisa jadi for(;i++<n;w=!w)for(char c:s.toCharArray())b.append(e(w,c));. Dan saya cukup yakin Anda dapat menghapus StringBuffersepenuhnya dan hanya menggunakan Stringdan +=bukan append.
Kevin Cruijssen
Sobat, beberapa bulan kode bersih dan praktik pengkodean yang baik membuat saya lupa bagaimana bahkan golf! Saya akan memperbarui jawaban saya dan memasukkan TIO.
joH1
1

05AB1E , 33 29 byte

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

Cobalah secara online atau verifikasi semua kasus uji .

Kemungkinan besar dapat dibelah dua dalam byte-count, tetapi berfungsi ..

Penjelasan:

Ć           # 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
Kevin Cruijssen
sumber
1

Java 11, 387 byte

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

Cobalah online. (CATATAN: Karena Java 11 belum menggunakan TIO, String.repeat(int)telah ditiru repeat(String,int)untuk byte-count yang sama.)

Penjelasan:

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
Kevin Cruijssen
sumber
1

R , 173 byte

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

Cobalah online!

@ ngm: Saya mencoba yang terbaik untuk golf kode Anda (dengan kustomisasi berat saya tentu saja) tetapi, seperti yang Anda ketahui, R tidak terlalu golf dalam memanipulasi string: P

menggali semua
sumber
Saya yakin ini bisa sub 150 byte, tapi saya belum yakin bagaimana.
Giuseppe
@ Giuseppe: Saya curiga juga ... tapi saya tidak terlalu baik dalam menulis kode manipulasi string pendek dan R juga tidak banyak membantu saya: D
digEmAll
@digEmAll Saya tidak akan mencoba untuk menyelesaikan tantangan saya sendiri, tetapi beberapa kemungkinan mungkin termasuk outer untuk mendapatkan semua kombinasi, dan melakukan aritmatika modular pada poin kode sebagai penggantichartr .
ngm
@ ngm: mungkin ... Saya membuang pendekatan aritmatika karena saya tidak dapat menemukan solusi / rumus pendek untuk mengubah huruf untuk huruf tanpa menyentuh angka ...
digEmAll