填充字符串列表之间的最大汉明距离


18

长的两个字符串之间的汉明距离是相应字符不同的位置数。如果弦的长度不相等,则汉明距离未定义。

挑战

编写一个程序或函数,该程序或函数从字符串列表中的所有字符串对中找出最大汉明距离,并根据下文所述的规则进行填充。

字符将来自内部a-zA-Z0-9

字符串的长度可能不相等,因此对于每个比较而言,较短的字符串都必须按以下方式填充:

  • 从头开始将字符串包装多次,以匹配所需的长度
  • 每次奇数换行(第1,第3,第5等)更改字母的大小写
  • a-zA-Z包装时,将外部物品保持不变

例如,假设您需要填充5个字符串ab9Cd,以使其最终以18个字符结尾。您最终将得到:

ab9CdAB9cDab9CdAB9
     ^^^^^     ^^^

^第一和第三包裹下加入到亮点的情况下更改。

输入输出

输入/输出格式灵活。您可以假定输入至少包含两个字符串,并且所有字符串都将至少包含一个字符。

输出为整数。

规则

这是。适用标准规则。

测试用例

[ "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
每次换
行时都要

建议的测试用例:["AacaAc", "Aab"] => 2。我的果冻答案是有目的的高尔夫运动,在那种情况下会失败,但在其他所有情况下都会通过。
Xcoder先生18年

@ngm极好的挑战!+1
Don Thousand

Answers:


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]对于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',
                        在这里,我的意思是在不同的位置。|
    µ)使用单子链接进行映射。|
     Mold /将x像y一样模制。即,循环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$分成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']]]
           交换偶数索引的块(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,0,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1]]]]
                  §结束映射后,对每个布尔(0或1)数组求和。| [[5],[17],[14]]
                   Ṁ最大。| 17

我完全不熟悉Jelly,但我认为您可以省略,但最终仍能获得相同的最大值。
Chas Brown

@ChasBrown呃,不,我应该需要一个。否则,ṁ/在某些情况下,不是将最短的填充到最长的一个的长度,而是将最长的修剪到最短的一个的长度,这不是我们想要的...。我想测试用例选择得太好了(这是一个不幸的巧合)……
Xcoder先生,18年

@ChasBrown例如,尝试["AacaAc", "Aab"]
Xcoder先生18年

啊,是的,我知道了……我需要向我进一步学习果冻... :)
Chas Brown,

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截断到最短可迭代。如果为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字节

使用类似于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[])带有显式数组的调用方法(无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();
}

知道可以实现更好的解决方案,尤其是对于字符串配对部分。

编辑:通过将int数组的大小更改为hammingDistance()给定字符串数的平方来减少8个字节。它还修复了ArrayIndexOutOfBounds其中一个测试用例中抛出的异常。

编辑2:由于凯文·克鲁伊森(Kevin Cruijssen)的评论,节省了33个字节:删除了类声明,名称缩短为1个字符,更改了运算符,等等。

编辑3:保存1个字节并通过将var-arg更改为array的方法来达到Satan认可的分数。

编辑4:再次感谢Kevin 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);中,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

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在操纵字符串方面不是很熟练:


我敢打赌,这可能是150字节以下,但我不确定如何。
朱塞佩

@Giuseppe:我也怀疑...但是我在编写短字符串操作代码方面不是很出色,R也对我没有太大帮助:D
digEmAll

@digEmAll我不会尝试解决自己的挑战,但是几乎没有什么可能包括outer获得所有组合以及对代码点进行模块化算术来代替chartr
ngm

@ngm:可能...我放弃了算术方法,因为我找不到一个简短的解决方案/公式来更改字母的大小写而又不触及数字...
digEmAll
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.