Maximale Hamming-Distanz zwischen einer Liste gepolsterter Saiten

18

Der Hamming-Abstand zwischen zwei Saiten gleicher Länge ist die Anzahl der Positionen, an denen sich die entsprechenden Zeichen unterscheiden. Wenn die Saiten nicht gleich lang sind, ist die Hamming-Distanz nicht definiert.

Herausforderung

Schreiben Sie ein Programm oder eine Funktion, die aus einer Liste von Zeichenfolgen den größten Hamming-Abstand unter allen Zeichenfolgenpaaren ermittelt.

Die Charaktere werden von innen sein a-zA-Z0-9.

Die Zeichenfolgen sind möglicherweise nicht gleich lang. Daher muss für jeden Vergleich die kürzere Zeichenfolge wie folgt aufgefüllt werden:

  • Wickeln Sie die Zeichenfolge von Anfang an so oft ein, bis die erforderliche Länge erreicht ist
  • Ändern Sie die Groß- und Kleinschreibung der Buchstaben bei jedem ungeraden Umbruch (1., 3., 5. usw.)
  • Lassen Sie die Dinge a-zA-Zbeim Wickeln draußen unverändert

Angenommen, Sie müssen die Zeichenfolge mit 5 Zeichen auffüllen, ab9Cddamit sie 18 Zeichen enthält. Sie würden am Ende mit:

ab9CdAB9cDab9CdAB9
     ^^^^^     ^^^

mit ^unter dem 1. und 3. Umbruch hinzugefügt, um Änderungen an Groß- und Kleinschreibung hervorzuheben.

Input-Output

Das Eingabe- / Ausgabeformat ist flexibel. Sie können davon ausgehen, dass die Eingabe mindestens zwei Zeichen enthält und dass alle Zeichen mindestens ein Zeichen enthalten.

Die Ausgabe ist eine Ganzzahl.

Regeln

Das ist . Es gelten Standardregeln.

Testfälle

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

Referenzimplementierung

Ich habe die Beispiele mit (vollständig ungolfed) R-Code getestet, den Sie hier ausprobieren können , um andere Beispiele, die Sie möglicherweise ausprobieren, mit Ihrem Code zu vergleichen.

ngm
quelle
1
Ändern Sie die Fälle der Buchstaben jedes Mal ungerade Verpackung - Oh Junge, diese Anforderung wird ein Schmerz für meine Lösung sein ... Ich mag die Herausforderung, so +1
Mr. Xcoder
Empfohlene Testfall: ["AacaAc", "Aab"] => 2. Ein gezieltes Golfspielen auf meine Jelly-Antwort hätte diesen Fall nicht bestanden, aber alle anderen bestanden.
Mr. Xcoder
@ngm Ausgezeichnete Herausforderung! +1
Don Thousand

Antworten:

7

Gelee , 20 Bytes

Bin nicht wirklich glücklich damit. Sollte golffähig sein, vielleicht sogar bis zu ~ 15 Bytes.

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

Probieren Sie es online!

oder Testen Sie eine Testsuite!

Erläuterung

LÞŒcµṁ / sḢL $ ŒsŒeFn) §Ṁ Vollständiges Programm oder monadischer Link. N = Eingabe. | Beispiel: ["abc12D5", "abC34d3", "ABC14dabc23DAbC89d"]
LÞ N nach Länge sortieren. | [['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 ']] (in Jelly sind Zeichenfolgen eine Liste von Zeichen)
  Œc Ungeordnete Paare: [x, y] für alle unterschiedlichen x, y in 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',
                        Hier meine ich mit eindeutig an verschiedenen Positionen. |
    µ) Karte mit einem monadischen Link. |
     ṁ / Schimmel x wie y. Das heißt, Zyklus x, bis Länge y erreicht ist. | [['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 $ In Stücke von x-Länge aufteilen. | [[['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 Swape Vertauschen Sie den Fall von Chunks mit geradem Index (1-indexiert). | [[['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 Abflachen. | [['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 Vektorisierte Ungleichung mit 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, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1]]
                  § Summieren Sie nach dem Beenden der Map jedes bool-Array (0 oder 1). | [[5], [17], [14]]
                   Ṁ Maximum. | 17
Mr. Xcoder
quelle
Ich kenne Jelly überhaupt nicht, aber ich denke, man kann es weglassen und am Ende immer noch das gleiche Maximum erreichen.
Chas Brown
@ChasBrown Ugh, nein, das sollte ich brauchen. Ansonsten, anstatt die kürzeste auf die Länge der längsten aufzufüllen,ṁ/ die längste in einigen Fällen auf die Länge der kürzesten zuschneiden, was nicht das ist, was wir wollen .... Ich denke, die Testfälle sind zu gut gewählt (und das ist ein eher unglücklicher Zufall) ...
Mr. Xcoder
@ChasBrown Versuchen Sie es als Beispiel ["AacaAc", "Aab"].
Mr. Xcoder
Ah ja, ich
Chas Brown
5

Python 2 , 86 Bytes

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)

Probieren Sie es online!

Gegeben seien zwei Strings s,t, zip((s+s.swapcase())*len(t),t))wird eine Liste von Tupeln der Länge sein , len(t)da zipauf dem kürzesten iterable abschneidet. Wenn ja len(s)<len(t), dann wird dies smit dem gewünschten Fall vertauscht und es werden die sumunterschiedlichen Zeichen berechnet .

Wenn len(t)<=len(s), dann wird das Ergebnis sumkleiner oder gleich dem sumsein, was wir ausgewertet haben t,s; es hat also keine Auswirkung auf das Ergebnis maxin diesem Fall.

Chas Brown
quelle
Sie können y!=anstelle von !=y1 Byte speichern
Mr. Xcoder
@Herr. Xcoder: Danke, aber ich habe meine Lösung drastisch überarbeitet ...
Chas Brown
3

Gelee , 19 Bytes

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

Probieren Sie es 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
quelle
2

Ruby , 89 82 Bytes

Erstellt das Kreuzprodukt der Eingabeliste gegen sich selbst, bevor die Hamming-Distanz jedes Paares unter Verwendung einer Duplizierungsmethode berechnet wird, die der Antwort von Chas Brown ähnelt . Ruby kann Strings nicht zusammenzippen oder Boolesche Werte ohne zusätzlichen Overhead hinzufügen. Daher muss stattdessen das Stringpaar manuell durchlaufen werden.

-7 Bytes von GB.

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

Probieren Sie es online!

Wert Tinte
quelle
1
82 Bytes
GB
2

Java 10 ,748 740 667 666 616 Bytes

Dies muss das dichteste und unleserlichste sein, aber das längste Golf, das ich je hatte.

Aufrufmethode h(String[])mit einem expliziten Array (keine var args): zB

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

kehrt zurück 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();}

Sie können es online ausprobieren !

Ungolfed und kommentiert:

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

Ich weiß, dass eine bessere Lösung erzielt werden kann, insbesondere für den Teil der Saitenpaarung.

BEARBEITEN : 8 Bytes durch Ändern der Größe des Int-Arrays in hammingDistance()das Quadrat der angegebenen Anzahl von Zeichenfolgen entfernen. Es behebt auch einArrayIndexOutOfBounds in einem der Testfälle geworfenen Fehler.

EDIT 2 : 33 Bytes dank Kevin Cruijssens Kommentaren gespart : Klassendeklaration entfernt, Namen auf 1 Zeichen gekürzt, Operatoren geändert, etc.

EDIT 3 : Speichern Sie 1 Byte und erreichen Sie die vom Satan genehmigte Punktzahl, indem Sie die Methode mit var-arg in array ändern.

EDIT 4 : Sparen Sie nochmals 50 Bytes dank Kevin Cruijssen : Aktualisieren Sie die Java-Version von 8 auf 10, um varSchlüsselwörter, entfernte StringBuilderInstanzen usw. zu verwenden.

joH1
quelle
1
Ich habe nicht viel Zeit, aber ein paar grundlegende Dinge zum Golfen: Lass den Kurs aus, nur die Methoden sind ausreichend. Ändern Sie alle Methoden- und Variablennamen in einzelne Bytes. hammingDistanceVerwenden Sie stattdessen deine andere nicht verwendete Variable. Die meisten von Ihnen &&können &und ||können sein |. c^' 'kann sein c^32. boolean w = false;kann sein boolean w=0>1;. i=0in der Schleifeninitialisierung kann entfernt und geändert werden die ,i,jzu ,i=0,j. ++jkann entfernt und dem ++hinzugefügt werden .charAt(j++). .toString()kann sein +"". for(j=i+1;j<l;++j)kann sein for(j=0;++j<l;). Etc. etc.
Kevin Cruijssen
1
Tipps zum Golfen in Java und Tipps zum Golfen in <allen Sprachen> könnten ebenfalls interessant sein. :)
Kevin Cruijssen
Vielen Dank! Das ist ein nettes Byte-Lifting. Danke auch für die Links, ich schaue es mir an und werde es so schnell wie möglich bearbeiten!
JoH1
1
Upvoted for the Satan-approved score. xD Noch ein paar Kleinigkeiten: StringBuilderkann sein StringBuffer(wenn Sie auf Java 10 umsteigen, könnte es sein var b=new StringBuffer(l);. Das booleanund charkann es dann auch sein var. Wenn Sie Java 10 nicht lokal haben, ist es auf TIO verfügbar ). Außerdem for(;i<n;++i){for(char c:s.toCharArray())b.append(e(w,c));w=!w;}kann for(;i++<n;w=!w)for(char c:s.toCharArray())b.append(e(w,c));. Und ich bin mir ziemlich sicher, dass Sie das StringBufferkomplett entfernen und einfach Stringund +=statt verwenden können append.
Kevin Cruijssen
Mann, einige Monate sauberer Code und gute Codierungspraktiken haben mich vergessen lassen, wie man überhaupt Golf spielt! Ich aktualisiere meine Antwort und füge TIO hinzu.
JoH1
1

05AB1E , 33 29 Bytes

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

Probieren Sie es online aus oder überprüfen Sie alle Testfälle .

Kann höchstwahrscheinlich in Bytezahl halbiert werden, aber es funktioniert ..

Erläuterung:

Ć           # 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
quelle
1

Java 11, 387 Bytes

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

Probieren Sie es online aus. (HINWEIS: Da Java 11 noch nicht auf TIO ist, String.repeat(int)wurde es mit repeat(String,int)der gleichen Byte-Anzahl emuliert .)

Erläuterung:

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
quelle
1

R 173 Bytes

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

Probieren Sie es online!

@ngm: Ich habe versucht , mein Bestes zu Golf Code (mit meiner schweren Anpassung natürlich) , aber, wie Sie wissen, ist R nicht sehr Golfy manipulieren Strings: P

digEmAll
quelle
Ich wette, das können unter 150 Bytes sein, aber ich bin mir noch nicht sicher, wie.
Giuseppe
@ Giuseppe: Ich vermute das auch ... aber ich bin nicht wirklich gut darin, Manipulationscodes für kurze Zeichenfolgen zu schreiben, und R hilft mir auch nicht viel: D
digEmAll
@digEmAll Ich werde nicht versuchen, meine eigene Herausforderung zu lösen, aber es gibt nur wenige Möglichkeiten outer, alle Kombinationen zu erhalten und die Codepunkte stattdessen modular zu berechnen chartr.
ngm
@ngm: möglich ... Ich habe die arithmetische Methode verworfen, weil ich keine kurze Lösung / Formel gefunden habe, um die Groß- / Kleinschreibung für Buchstaben zu ändern, ohne die Zahlen zu berühren ...
digEmAll