パディングされた文字列のリスト間の最大ハミング距離


18

等しい長さの2つのストリング間のハミング距離は、対応する文字が異なる位置の数です。文字列の長さが等しくない場合、ハミング距離は定義されません。

チャレンジ

文字列のリストからすべての文字列のペアの中で最大のハミング距離を見つけるプログラムまたは関数を作成し、以下で説明する規則に従って必要に応じてパディングします。

文字は内からになりますa-zA-Z0-9

文字列の長さが等しくない場合があるため、比較ごとに次のように短い文字列をパディングする必要があります。

  • 必要な長さに合わせて、必要な回数だけ文字列を先頭から折り返します
  • 奇数回の折り返しごとに文字の大文字小文字を変更します(1番目、3番目、5番目など)
  • a-zA-Z包装するときは外の物をそのままにしておく

たとえばab9Cd、18 文字になるように5文字の文字列を埋め込む必要があるとしましょう。次のようになります。

ab9CdAB9cDab9CdAB9
     ^^^^^     ^^^

^ケースの変更を強調するために、1番目と3番目のラップの下に追加されます。

入出力

入出力形式は柔軟です。入力に少なくとも2つの文字列があり、すべての文字列に少なくとも1つの文字があると仮定できます。

出力は整数です。

ルール

これはです。標準ルールが適用されます。

テストケース

[ "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
Mr. Xcoder

推奨されるテストケース:["AacaAc", "Aab"] => 2。私のゼリーの答えに対する意図的なゴルフはその場合失敗しますが、他のすべてをパスします。
Mr 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 ']](ゼリーでは、文字列は文字のリストです)
  Œc順序付けられていないペア:[x、y] Nのすべての個別のx、y。[[['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がyのようになります。つまり、長さyに達するまで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」]]
       sḢL$ 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 ']]]
           Œ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 yによるベクトル化された不等式。| [[[0、0、1、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、0、1、0、0、1、1、1、1、0、1、1、1、1、1、1、1、1]]]
                  §マップの終了後、各ブール(0または1)配列を合計します。| [[5]、[17]、[14]]
                   Ṁ最大。| 17

私はゼリーに完全に精通していませんが、最後に省略しても同じ最大値を取得できると思います。
チャスブラウン

@ChasBrownうーん、いや、それ必要なんだ。そうしないと、最短の長さを最短の長さにパディングする代わりに、場合によっては最長ṁ/の長さを最短の長さまでトリミングしますが、これは私たちが望んでいないものです... ...(これは、むしろ不幸な偶然です)
ミスターXcoder

@ChasBrown例として、を試してください["AacaAc", "Aab"]
Mr 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,tzip((s+s.swapcase())*len(t),t))長さのタプルのリストになりますlen(t)ので、zip最短のiterableに切り捨てられます。の場合len(s)<len(t)、これsは目的の大文字と小文字を交換して「パディング」し、sum異なる文字を計算します。

ifの場合len(t)<=len(s)、結果は評価中のif sum以下になります。そのため、その場合の結果には影響しません。sumt,smax


あなたは使用することができますy!=の代わりに!=y1つのバイトを保存する
氏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バイト

Chas Brownの答えと同様の複製方法を使用して、各ペアのハミング距離を計算する前に、入力リストとそれ自体の外積を作成します。ただし、Rubyは文字列を一緒に圧縮したり、オーバーヘッドを追加せずにブール値を追加したりすることはできません。そのため、代わりに文字列のペアを手動で繰り返す必要があります。

GBから-7バイト。

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

オンラインでお試しください!



2

Java 10748 740 667 666 616バイト

これは、最も高密度で読みにくいものである必要がありますが、私が思いついた最長のゴルフでなければなりません。

h(String[])明示的な配列(変数引数なし)でメソッドを呼び出します。たとえば、

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

特に文字列のペアリング部分については、より良い解決策を達成できることを知っています。

編集:int配列のサイズを指定さhammingDistance()れた文字列の数の2乗に変更することにより、8バイトを削ります。またArrayIndexOutOfBounds、テストケースの1つでスローされた問題も修正します。

編集2Kevin Cruijssenのコメントのおかげで33バイト節約されました:クラス宣言の削除、名前の1文字への短縮、演算子の変更など

編集3:1バイトを保存し、var-argを使用してメソッドを配列に変更することにより、サタン承認のスコアに到達します。

編集4Kevin Cruijssenのおかげで、さらに50バイト節約できます。Javaバージョンを8から10に更新して、varキーワードや削除されたStringBuilderインスタンスなどを使用します。


1
あまり時間はありませんが、ゴルフの基本的なことはいくつかあります。クラスをドロップし、メソッドだけで十分です。すべてのメソッド名と変数名をシングルバイトに変更します。したがって、hammingDistance使用dまたは他の未使用変数の代わりに。あなたのほとんど&&がそう&である||ことができます|c^' 'することができますc^32boolean 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;)。等など
ケビンクルーッセン


ありがとう!これは素晴らしいバイトリフティングです。リンクもありがとう、私はそれを見て、できるだけ早く編集します!
joH1

1
サタン承認のスコアに賛成。xDいくつかの小さなこと:StringBuilder可能StringBuffer(Java 10に切り替える場合は可能var b=new StringBuffer(l);です。またbooleanchar可能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

05AB1E33 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バイトになる可能性がありますが、まだどのくらいかはわかりません。
ジュゼッペ

@ジュゼッペ:私もそれを疑います...しかし、私は短い文字列操作コードを書くのはあまり得意ではなく、Rもあまり私を助けません:D
digEmAll

@digEmAll私は自分の課題を解決しようとはouterしませんが、すべての組み合わせを取得し、コードポイントでモジュラー演算を実行する代わりに、いくつかの可能性がありますchartr
ngm

@ngm:可能性...数字に触れずに文字の大文字小文字を変更する短い解決策/式が見つからなかったため、算術アプローチを破棄しました...
digEmAll
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.