Distanza massima di Hamming tra un elenco di stringhe imbottite


18

La distanza di Hamming tra due stringhe di uguale lunghezza è il numero di posizioni in cui i caratteri corrispondenti sono diversi. Se le stringhe non hanno la stessa lunghezza, la distanza di Hamming non è definita.

Sfida

Scrivi un programma o una funzione che trova la più grande distanza di Hamming tra tutte le coppie di stringhe da un elenco di stringhe, imbottito come richiesto in base alle regole descritte di seguito.

I personaggi verranno dall'interno a-zA-Z0-9.

Le stringhe potrebbero non essere uguali in lunghezza, quindi per ogni confronto la stringa più corta deve essere riempita come segue:

  • avvolgere la stringa dall'inizio tutte le volte necessarie per adattarsi alla lunghezza richiesta
  • cambia i casi delle lettere ogni volta dispari (1 °, 3 °, 5 °, ecc.)
  • lasciare le cose all'esterno a-zA-Zinvariate quando si avvolgono

Ad esempio, supponiamo che sia necessario riempire la stringa di 5 caratteri in ab9Cdmodo che finisca con 18 caratteri. Si finirebbe con:

ab9CdAB9cDab9CdAB9
     ^^^^^     ^^^

con l' ^aggiunta sotto il 1 ° e il 3 ° involucro per evidenziare le modifiche al caso.

Input Output

Il formato di input / output è flessibile. Puoi supporre che l'input abbia almeno due stringhe e che tutte le stringhe abbiano almeno un carattere.

L'output è un numero intero.

Regole

Questo è . Si applicano le regole standard.

Casi test

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

Implementazione di riferimento

Ho testato gli esempi con il codice R (completamente non salvato) che puoi provare qui per confrontare qualsiasi altro esempio che potresti provare con il tuo codice.


1
cambia i casi delle lettere ogni volta che passa il tempo - Oh ragazzo, questo requisito sarà un dolore per la mia soluzione ... Mi piace la sfida, però, quindi +1
Mr. Xcoder

Banco di prova consigliato: ["AacaAc", "Aab"] => 2. Un golf intenzionale alla mia risposta di Jelly avrebbe fallito quel caso, ma avrebbe superato tutti gli altri.
Mr. Xcoder,

@ngm Ottima sfida! +1
Don Mille

Risposte:


7

Gelatina , 20 byte

Non molto contento. Dovrebbe essere golfabile, forse anche a ~ 15 byte.

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

Provalo online!

oppure Dai un'occhiata a una suite di test!

Spiegazione

LÞŒcµṁ / sḢL $ ŒsÐeFn) §Ṁ Programma completo o collegamento monadico. N = input. | Esempio: ["abc12D5", "abC34d3", "ABC14dabc23DAbC89d"]
LÞ Ordina N per lunghezza. | [['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, le stringhe sono un elenco di caratteri)
  Œc Coppie non ordinate: [x, y] per tutte le x, y distinte 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',
                        Qui, per distinto, intendo in diverse posizioni. |
    µ) Mappa con un collegamento monadico. |
     ṁ / Muffa x come y. Cioè, ciclo x fino a raggiungere la lunghezza 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 $ Dividi in blocchi della lunghezza di 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 Scambia il caso di blocchi con indice pari (1-indicizzato). | [[['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 Appiattire. | [['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 Disuguaglianza vettorializzata con 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, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1]]]
                  § Dopo aver terminato la mappa, sommare ogni array bool (0 o 1). | [[5], [17], [14]]
                   Ṁ massimo. | 17

Non ho familiarità con Jelly, ma penso che tu possa omettere e ottenere comunque lo stesso massimo alla fine.
Chas Brown,

@ChasBrown Ugh, no, dovrei averne bisogno. Altrimenti, invece di riempire il più corto alla lunghezza del più lungo, ṁ/in alcuni casi tagliarebbe il più lungo alla lunghezza del più corto, il che non è quello che vogliamo .... Immagino che i casi di test siano troppo scelti (e questa è una coincidenza piuttosto sfortunata) ...
Mr. Xcoder il

@ChasBrown Ad esempio, prova ["AacaAc", "Aab"].
Mr. Xcoder,

Ah sì, vedo ... Devo imparare un po 'di più 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)

Provalo online!

Date due stringhe, s,t, zip((s+s.swapcase())*len(t),t))sarà una lista di tuple di lunghezza len(t)dal ziptronca a più breve iterabile. Se len(s)<len(t), allora questo "rimbalza" scon lo scambio di maiuscole desiderato e calcoliamo i sumcaratteri diversi.

Se len(t)<=len(s), allora il risultato sumsarà inferiore o uguale al sumse stessimo valutando t,s; quindi non ha alcun effetto sul risultato maxin quel caso.


Puoi usare y!=invece di !=ysalvare 1 byte
Mr. Xcoder

@Sig. Xcoder: Grazie, ma ho finito per rielaborare drasticamente la mia soluzione ...
Chas Brown


3

Gelatina , 19 byte

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

Provalo 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.

2

rubino , 89 82 byte

Crea il prodotto incrociato dell'elenco di input rispetto a se stesso prima di calcolare la distanza di Hamming di ciascuna coppia, utilizzando un metodo di duplicazione simile alla risposta di Chas Brown . Ruby non può comprimere le stringhe insieme o aggiungere booleani senza sovraccarico aggiuntivo, quindi diventa invece necessario scorrere manualmente la coppia di stringhe.

-7 byte da GB.

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

Provalo online!



2

Java 10 ,748 740 667 666 616 byte

Questo deve essere il più denso e illeggibile, eppure il golf più lungo che abbia mai inventato.

Chiama il metodo h(String[])con un array esplicito (no var args): ad es.

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

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

Puoi provarlo online !

Ungolf e commentato:

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

Io conosco una soluzione migliore può essere realizzato, in particolare per la parte stringa di accoppiamento.

EDIT : radere 8 byte modificando la dimensione dell'array int nel hammingDistance()quadrato del numero di stringhe fornite. Risolve anche un ArrayIndexOutOfBoundslancio in uno dei casi di test.

EDIT 2 : Salvato 33 byte grazie ai commenti di Kevin Cruijssen : dichiarazione di classe rimossa, nomi abbreviati in 1 carattere, operatori cambiati, ecc.

EDIT 3 : salva 1 byte e raggiungi il punteggio approvato da Satana cambiando metodo con var-arg in array.

EDIT 4 : Salva altri 50 byte grazie a Kevin Cruijssen , di nuovo: aggiorna la versione Java da 8 a 10 per usare la varparola chiave, l' StringBuilderistanza rimossa , ecc.


1
Non ho molto tempo, ma alcune cose basilari per giocare a golf: abbandonare la lezione, solo i metodi sono sufficienti. Cambia tutti i nomi dei metodi e delle variabili in singoli byte. Quindi, invece di hammingDistanceutilizzare do qualche altra variabile non utilizzata. La maggior parte dei tuoi &&può essere &e ||può essere |. c^' 'può essere c^32. boolean w = false;può essere boolean w=0>1;. i=0nel ciclo l'inizializzazione può essere rimossa e cambiare ,i,jin ,i=0,j. ++jpuò essere rimosso e ++può essere aggiunto a .charAt(j++). .toString()può essere +"". for(j=i+1;j<l;++j)può essere for(j=0;++j<l;). Ecc. Ecc.
Kevin Cruijssen,


Grazie! Questo è un bel sollevamento dei byte. Grazie anche per i collegamenti, ci sto dando un'occhiata e li modificherò al più presto!
joH1

1
È stato votato per il punteggio approvato da Satana. xD Altre piccole cose: StringBuilderpuò essere StringBuffer(se si passa a Java 10 potrebbe essere var b=new StringBuffer(l);. L' booleane charpuò anche essere var. Se non si dispone di Java 10 localmente, è disponibile su TIO ). Inoltre, for(;i<n;++i){for(char c:s.toCharArray())b.append(e(w,c));w=!w;}può essere for(;i++<n;w=!w)for(char c:s.toCharArray())b.append(e(w,c));. E sono abbastanza sicuro che puoi rimuovere StringBuffercompletamente e solo usare Stringe +=invece di append.
Kevin Cruijssen,

Amico, alcuni mesi di codice pulito e buone pratiche di codifica mi hanno fatto dimenticare come giocare a golf! Aggiornerò la mia risposta e includerò TIO.
joH1

1

05AB1E , 33 29 byte

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

Provalo online o verifica tutti i casi di test .

Molto probabilmente può essere dimezzato nel conteggio dei byte, ma funziona ..

Spiegazione:

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

Provalo online. (NOTA: poiché Java 11 non è ancora su TIO, String.repeat(int)è stato emulato come repeat(String,int)per lo stesso conteggio byte.)

Spiegazione:

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

Provalo online!

@ngm: ho fatto del mio meglio per giocare a golf del tuo codice (con le mie pesanti personalizzazioni ovviamente) ma, come ben sai, R non è molto golfoso nel manipolare le stringhe: P


Scommetto che questo può essere inferiore a 150 byte, ma non sono ancora sicuro di come.
Giuseppe,

@Giuseppe: lo sospetto anch'io ... ma non sono davvero bravo a scrivere codici di manipolazione di stringhe brevi e R non mi aiuta molto neanche: D
digEmAll

@digEmAll Non proverò a risolvere la mia sfida, ma poche possibilità potrebbero includere l'ottenimento di outertutte le combinazioni e l'esecuzione dell'aritmetica modulare sui punti di codice al posto di chartr.
ngm

@ngm: possibile ... Ho scartato l'approccio aritmetico perché non sono riuscito a trovare una soluzione / formula breve per cambiare il caso delle lettere senza toccare i numeri ...
digEmAll
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.