Conta quante sequenze di distanza sono lontane da tutte le altre


13

La distanza di Hamming tra due stringhe di uguale lunghezza è il numero di posizioni in cui i simboli corrispondenti sono diversi.

Lascia che Psia una stringa binaria di lunghezza ne che Tsia una stringa binaria di lunghezza 2n-1. Possiamo calcolare le ndistanze di Hamming tra Pe tutte le nsottostringhe di Tin ordine da sinistra a destra e metterle in un array (o elenco).

Esempio di sequenza della distanza di Hamming

Let P = 101and T = 01100. La sequenza delle distanze di Hamming che ottieni da questa coppia è 2,2,1.

Definizione di vicinanza

Consideriamo ora due di queste sequenze di distanze di Hamming. Dire x = (0, 2, 2, 3, 0)e y = (2, 1, 4, 4, 2)come esempi. Lo diciamo xe ysiamo closese y <= x <= 2*yo se x <= y <= 2*x. Qui la moltiplicazione scalare e la disuguaglianza sono prese elementalmente. Vale a dire, per due sequenze Ae B, A <= B iff A[i] <= B[i]per tutti gli indici i.

Si noti che le sequenze delle distanze di Hamming formano un ordine parziale in questo modo di confrontarle. In altre parole, molte coppie di sequenze non sono né maggiori né uguali né minori o uguali tra loro. Ad esempio (1,2)e (2,1).

Quindi usando l'esempio sopra, (0, 2, 2, 3, 0) <= 2*(2, 1, 4, 4, 2) = (4, 2, 8, 8, 4)ma (0, 2, 2, 3, 0)non è più grande di (2, 1, 4, 4, 2). Inoltre (2, 1, 4, 4, 2)non è inferiore o uguale a 2*(0, 2, 2, 3, 0) = (0, 4, 4, 6, 0). Di conseguenza xe ynon sono vicini l'uno all'altro.

Compito

Per aumentare a npartire da n=1, considera tutte le possibili coppie di stringhe binarie Pdi lunghezza ne Tlunghezza 2n-1. Esistono 2^(n+2n-1)coppie del genere e quindi molte sequenze di distanze di Hamming. Tuttavia, molte di queste sequenze saranno identiche. Il compito è quello di trovare la dimensione del set più grande di sequenze di distanza di Hamming in modo che non vi siano due sequenze vicine l'una all'altra.

Il tuo codice dovrebbe generare un numero per valore di n.

Punto

Il tuo punteggio è sostanzialmente il più alto che il ntuo codice raggiunge sulla mia macchina in 5 minuti (ma continua a leggere). Il tempismo è per il tempo di esecuzione totale, non solo per quello n.

Al fine di dare punteggi per risposte non ottimali, poiché è probabile che trovare risposte ottimali sia difficile, avremo bisogno di un sistema di punteggio leggermente sottile. Il tuo punteggio è il valore più alto nper il quale nessun altro ha pubblicato una risposta corretta più alta per qualsiasi dimensione inferiore a uguale a questa. Ad esempio, se si 2, 4, 21emette e qualcun altro emette, 2, 5, 15si otterrebbe un punteggio solo 1perché qualcun altro ha una risposta migliore n = 2. Se produci un output 2, 5, 21, assegnerai 3un punteggio a prescindere da ciò che qualcun altro produce perché quelle risposte sono tutte ottimali. Chiaramente se hai tutte le risposte ottimali otterrai il punteggio per il punteggio più alto nche pubblichi . Tuttavia, anche se la tua risposta non è ottimale, puoi comunque ottenere il punteggio se nessun altro può batterlo.

Esempio di risposte ed esempio funzionato

(Questa risposta è ancora deselezionata. Una verifica indipendente verrebbe ricevuta con gratitudine.)

Grazie a ETHproductions:

  • n = 1 dà 2.
  • n = 2 dà 5.
  • n = 3 dà 21.

Diamo un'occhiata n = 2in modo più dettagliato. In questo caso l'elenco completo delle sequenze della distanza di Hamming (qui rappresentate dalle tuple) è:

[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

Possiamo vedere che (0,0)non è vicino a nessun'altra tupla. Infatti se prendiamo (0, 0), (0, 1), (1, 0), (2, 1), (1,2)allora nessuno di questi tuple sono vicini ad uno qualsiasi degli altri. Questo dà un punteggio di 5per n = 2.

Per n = 3l'elenco completo delle distinte sequenze della distanza di Hamming è:

 [(0, 0, 0), (0, 0, 1), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 2, 1), (0, 2, 2), (0, 2, 3), (0, 3, 0), (0, 3, 1), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3), (1, 3, 0), (1, 3, 1), (1, 3, 2), (2, 0, 1), (2, 0, 2), (2, 0, 3), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 1, 3), (2, 2, 0), (2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 3, 1), (2, 3, 2), (2, 3, 3), (3, 0, 2), (3, 0, 3), (3, 1, 0), (3, 1, 1), (3, 1, 2), (3, 2, 0), (3, 2, 1), (3, 2, 2), (3, 3, 2), (3, 3, 3)]

Di queste 48sequenze, possiamo scegliere un insieme di dimensioni in 21modo che nessuna coppia in quell'insieme sia ravvicinata.

Lingue e biblioteche

Puoi utilizzare qualsiasi lingua e libreria disponibili. Laddove possibile, sarebbe opportuno poter eseguire il codice, quindi includere una spiegazione completa su come eseguire / compilare il codice in Linux, se possibile.

La mia macchina I tempi verranno eseguiti sulla mia macchina a 64 bit. Questa è un'installazione Ubuntu standard con 8 GB di RAM, processore AMD FX-8350 Eight-Core e Radeon HD 4250. Ciò significa anche che devo essere in grado di eseguire il codice.

Risposta principale

  • Punteggio di 4 per 2, 5, 21, 83, 361 di Christian Sievers. C ++
  • Punteggio di 5 per 2, 5, 21, 83, 372 di fəˈnɛtɪk. Javascript

Dopo aver esaminato la tua domanda, mostra alcune somiglianze con le spie, riviste su hackerrank, che è un problema NP-completo
f 15nɛtɪk

@ fəˈnɛtɪk Great! Nota che la mia domanda non richiede soluzioni ottimali per ottenere un buon punteggio.

@ fəˈnɛtɪk Puoi anche confermare le risposte per 1,2,3 nella domanda?

@ fəˈnɛtɪk Dubito fortemente che sia NP-difficile. Dovresti codificare Set Packing o un altro problema NP completo in un unico numero intero con solo una modifica polinomiale nella dimensione del problema.

297 array di hamming unici per 4, 2040 array unici per 5
f 16nɛtɪk

Risposte:


5

C ++ utilizzando la libreria igraph

Grazie per la bella opportunità di imparare una nuova biblioteca!

Questo programma ora calcola 2, 5, 21, 83, 361velocemente. È possibile controllare la stampa dei nodi con la PRINTNODEScostante.

Il grafico utilizzato ha bordi extra tra i nodi corrispondenti ai vettori di distanza in cui uno è vicino (ma non uguale) all'altro invertito. Ciò accelera il calcolo e qualsiasi set indipendente trovato è ovviamente anche uno dei grafici originali. Inoltre, anche se non viene applicato completamente, l'insieme indipendente calcolato viene chiuso in modalità inversa. Credo che esista sempre un insieme indipendente massimo con quella proprietà. Almeno ce n'è uno per n<=4. (Sono sicuro di poter mostrare 83 è ottimale.)

#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
#include<igraph.h>

using vect = std::vector<int>;

constexpr int MAXDIRECT=100;
constexpr int PRINTNODES=1;

std::set<int> avoid{};
igraph_t graph;
std::vector<vect> distance_vectors{};
int count;

int close_h(const vect &a, const vect &b ){
  // check one direction of the closeness condition
  for(auto i=a.begin(), j=b.begin(); i!=a.end(); i++,j++)
    if ( (*i > *j) || (*j > 2 * *i))
      return 0;
  return 1;
}

int close(const vect &a, const vect &b ){
  return close_h(a,b) || close_h(b,a);
}

vect distances(int n, int p, int t){
  vect res{};
  for (int i=0; i<n; ++i){
    int count = 0;
    for (int j=0; j<n; ++j)
      count += 1 & ((p>>j)^(t>>j));
    res.push_back(count);
    t >>= 1;
  }
  return res;
}

void print_vect( vect &v ){
  std::cout << "(";
  auto i=v.begin();
  std::cout << *i++;
  for( ; i!=v.end(); ++i)
    std::cout << "," << *i ;
  std::cout << ")\n";
}

void use_node( int n ){
  if(PRINTNODES)
    print_vect( distance_vectors[n] );
  ++count;
  avoid.insert( n );
  igraph_vector_t neighs;
  igraph_vector_init( &neighs, 0 );
  igraph_neighbors( &graph , &neighs, n, IGRAPH_OUT );
  for(int i=0; i<igraph_vector_size( &neighs ); ++i)
    avoid.insert( VECTOR(neighs)[i] );
  igraph_vector_destroy( &neighs );
}

void construct(int n){
  std::set<vect> dist_vects;
  for(int p=0; p>>n == 0; ++p)
    for(int t=0; t>>(2*n-2) == 0; ++t)   // sic! (because 0/1-symmetry)
      dist_vects.insert(distances(n,p,t));
  int nodes = dist_vects.size();
  std::cout << "distinct distance vectors: " << nodes << "\n";

  distance_vectors.clear();
  distance_vectors.reserve(nodes);
  std::copy(dist_vects.begin(), dist_vects.end(),
            back_inserter(distance_vectors));

  igraph_vector_t edges;
  igraph_vector_init( &edges, 0 );
  igraph_vector_t reversed;
  igraph_vector_init_seq( &reversed, 0, nodes-1 );
  for (int i=0; i<nodes-1; ++i){
    vect &x = distance_vectors[i];
    vect xr ( x.rbegin(), x.rend() );
    for(int j=i+1; j<nodes; ++j){
      vect &y = distance_vectors[j];
      if( xr==y ){
        VECTOR(reversed)[i] = j;
        VECTOR(reversed)[j] = i;
      }else if( close( x, y ) || close( xr, y) ){
        igraph_vector_push_back(&edges,i);
        igraph_vector_push_back(&edges,j);
      }
    }
  }
  std::cout << "edges: " << igraph_vector_size(&edges)/2 << "\n";

  igraph_create( &graph, &edges, nodes, IGRAPH_UNDIRECTED);
  igraph_vector_destroy( &edges );

  igraph_cattribute_VAN_setv( &graph, "r", &reversed );
  igraph_vector_destroy( &reversed );

  igraph_vector_t names;
  igraph_vector_init_seq( &names, 0, nodes-1 );
  igraph_cattribute_VAN_setv( &graph, "n", &names );
  igraph_vector_destroy( &names );

}

void max_independent( igraph_t *g ){
  igraph_vector_ptr_t livs;
  igraph_vector_ptr_init( &livs , 0 );
  igraph_largest_independent_vertex_sets( g, &livs );

  igraph_vector_t *nodes = (igraph_vector_t *) VECTOR(livs)[0];
  igraph_vector_t names;
  igraph_vector_init( &names, 0 );
  igraph_cattribute_VANV( g, "n", igraph_vss_vector( nodes ), &names );

  for(int i=0; i<igraph_vector_size(&names); ++i)
    use_node( VECTOR(names)[i] );
  igraph_vector_destroy( &names );
  igraph_vector_ptr_destroy_all( &livs );
}

void independent_comp( igraph_t *g );

void independent( igraph_t *g ){
  if(igraph_vcount( g ) < MAXDIRECT){
    max_independent( g );
    return;
  }
  igraph_vector_ptr_t components;
  igraph_vector_ptr_init( &components, 0 );
  igraph_decompose( g, &components, IGRAPH_WEAK, -1, 1);
  for(int i=0; i<igraph_vector_ptr_size( &components ); ++i)
    independent_comp( (igraph_t *) VECTOR(components)[i] );
  igraph_decompose_destroy( &components );
}

void independent_comp( igraph_t *g ){
  if (igraph_vcount( g ) < MAXDIRECT){
    max_independent( g );
    return;
  }
  igraph_vector_t degs;
  igraph_vector_init( &degs, 0 );
  igraph_degree( g, &degs, igraph_vss_all(), IGRAPH_OUT, 1 );
  int maxpos = igraph_vector_which_max( &degs );
  igraph_vector_destroy( &degs );  

  int name = igraph_cattribute_VAN( g, "n", maxpos );
  int revname = igraph_cattribute_VAN( g, "r", maxpos );
  int rev = -1;
  if(name!=revname){
    igraph_vector_ptr_t reversed_candidates_singleton;
    igraph_vector_ptr_init( &reversed_candidates_singleton, 0 );
    igraph_neighborhood( g, &reversed_candidates_singleton,
                         igraph_vss_1(maxpos), 2, IGRAPH_OUT );
    igraph_vector_t * reversed_candidates =
      (igraph_vector_t *) VECTOR(reversed_candidates_singleton)[0];
    igraph_vector_t names;
    igraph_vector_init( &names, 0 );
    igraph_cattribute_VANV( g, "n", igraph_vss_vector( reversed_candidates ),
                        &names );
    long int pos;
    igraph_vector_search( &names, 0, revname, &pos );
    rev = VECTOR(*reversed_candidates)[pos];
    igraph_vector_destroy( &names );
    igraph_vector_ptr_destroy( &reversed_candidates_singleton );
  }
  igraph_vs_t delnodes;
  igraph_vs_vector_small( &delnodes, maxpos, rev, -1 );
  igraph_delete_vertices( g, delnodes );
  igraph_vs_destroy( &delnodes );

  independent( g );
}

void handle(int n){
  std::cout << "n=" << n << "\n";
  avoid.clear();
  count = 0;
  construct( n );
  independent( &graph );
  // try all nodes again:
  for(int node=0; node<igraph_vcount( &graph ); ++node)
    if(avoid.count(node)==0)
      use_node(node);
  std::cout << "result: " << count << "\n\n";
  igraph_destroy( &graph );
}

int main(){
  igraph_i_set_attribute_table( &igraph_cattribute_table );
  for(int i=1; i<6; ++i)
    handle(i);
}

Per compilare su debian, installa libigraph0-deve fai g++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o ig ig.cpp -ligraph.

Vecchia descrizione:

La libreria igraph ha una funzione per calcolare la dimensione massima di un insieme di vertici indipendente di un grafico. Può gestire questo problema fino a n=3 in meno di un secondo e non termina in giorni per n=4.

Quindi quello che faccio è scomporre il grafico in componenti collegati e lasciare che la libreria gestisca i piccoli (meno di MAXDIRECT nodi). Per gli altri componenti, seleziono un vertice e lo elimino. Nel migliore dei casi, questo divide il grafico in diversi componenti, ma di solito non lo fa. Comunque, i componenti (forse solo uno) sono più piccoli e possiamo usare la ricorsione.

Ovviamente la selezione del vertice è importante. Ne prendo solo uno di massimo grado. Ho scoperto che ottengo risultati migliori (ma solo per n=4) quando utilizzo un elenco di nodi invertiti. Questo spiega la parte magica della constructfunzione.

Potrebbe valere la pena migliorare la selezione. Ma sembra più importante riconsiderare i nodi eliminati. In questo momento, non li guardo mai più. Alcuni di essi potrebbero non essere collegati a nessuno dei nodi selezionati. Il problema è che non so quali nodi formano l'insieme indipendente. Per uno, l'eliminazione dei nodi rinumera i nodi rimanenti. Ciò può essere gestito allegando loro attributi. Ma peggio, il calcolo del numero di indipendenza fornisce solo questo numero. La migliore alternativa offerta dalla biblioteca è il calcolo tutti i più grandi set indipendenti, che è più lento (quanto sembra dipendere dalla dimensione del grafico). Tuttavia, questo sembra il modo immediato di procedere. Molto più vagamente, penso anche che potrebbe essere utile considerare se possiamo usare il modo speciale in cui è definito il grafico.

Il caso n=6 potrebbe diventare raggiungibile (per niente, non necessariamente in 5 minuti) se sostituisco la ricorsione con un ciclo usando una coda per i componenti rimanenti.

Ho trovato interessante guardare i componenti dei grafici. Per n=4, le loro dimensioni sono 168, 2*29, 2*28, 3, 4*2, 4*1. Solo il più grande non può essere gestito direttamente.

Per n=5, le dimensioni sono 1376, 2*128, 2*120, 119, several <=6 .

Mi aspetto che quelle doppie dimensioni corrispondano ai grafici isomorfi, ma l'utilizzo di questo non sembra valere la pena perché c'è sempre un singolo componente principale dominante:

Perché n=6, il componente più grande contiene 11941nodi (da un totale di 15425), i due componenti più grandi successivi hanno dimensioni596 .

Per n=7, questi numeri sono 107593 (125232), 2647.


Potresti farmi sapere qual è il set per 83, voglio sapere perché il mio algoritmo non arriva così in alto per 4 ma in qualche modo aumenta per 5: P
fəˈnɛtɪk

Deve essere g++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o sievers sievers.cpp -ligraph. Importa dove si -ligraphtrova.

@ChristianSievers Come funziona la generazione dei bordi nel codice?
fəˈnɛtɪk,

@ChristianSievers Mi chiedevo come determina a cosa dovrebbe connettersi ciascun vertice. L'inversione dell'array potrebbe rovinare tutto.
fəˈnɛtɪk,

@ fəˈnɛtɪk I vettori di distanza sembrano essere stati separati da quelli setche uso per evitare duplicati, ma non ho nemmeno pensato al loro ordine quando ho scritto quel codice. Il ciclo interno a partire i+1evita solo di guardare una coppia e anche la sua versione scambiata che non è necessaria, ed è il modo più semplice per evitare loop (bordi (a,a)). Non dipende dall'ordine in cui arrivano i nodi, non mi importa se ottengo (a,b)o (b,a).
Christian Sievers,

3

Javascript, Seq: 2,5,21, 81 83.372 67.349

Sono riuscito ad aumentare il valore di 4 utilizzando la rimozione casuale degli elementi all'inizio della mia ricerca. Stranamente, rimuovere 20 elementi con più di 6 connessioni è stato più veloce della rimozione di 5 elementi con più di 8 connessioni ...

Questa sequenza probabilmente non è ottimale per 5 e potrebbe non essere ottimale per 4. Nessuno dei nodi è vicino a un altro nel set.

Codice:

input=4;
maxConnections=6;
numRand=20;

hammings=[];
h=(x,y)=>{retVal=0;while(x||y){if(x%2!=y%2)retVal++;x>>=1;y>>=1}return retVal};
for(i=1<<(input-1);i<1<<input;i++){
  for(j=0;j<1<<(2*input);j++){
    hamming=[];
    for(k=0;k<input;k++){
      hamming.push(h((j>>k)%(1<<input),i));
    }
    equal=0;
    for(k=0;k<hammings.length;k++){
      if(hamming.join("")==hammings[k].join("")){
        equal=1;
        break;
      }
    }
    if(!equal)hammings.push(hamming);
  }
}
adjMat=[];
for(i=0;i<Math.pow(input+1,input);i++){
  row=[];
  for(j=0;j<Math.pow(input+1,input);j++){
    row.push(0);
  }
  adjMat.push(row);
}
nodes=[]
for(i=0;i<Math.pow(input+1,input);i++){
  nodes[i]=0;
}
for(i=0;i<hammings.length;i++){
  sum=0;
  chkNodes=[[]];
  for(j=0;j<input;j++){
    chkVal=[];
    t=Math.pow(input+1,j);
    sum+=t*hammings[i][j];
    tmp=[];
    for(r=0;r<chkNodes.length;r++){
      for(k=hammings[i][j];k<=Math.min(hammings[i][j]*2,input);k++){
        stor=[]
        for(s=0;s<chkNodes[r].length;s++){
          stor.push(chkNodes[r][s])
        }
        stor.push(k)
        tmp.push(stor);
      }
    }
    chkNodes=[];
    for(r=0;r<tmp.length;r++){
      chkNodes.push(tmp[r])
    }
  }
  nodes[sum]=1;
  for(j=0;j<chkNodes.length;j++){
    adjSum=0
    for(k=0;k<input;k++){
      adjSum+=Math.pow(input+1,k)*chkNodes[j][k]
    }
    if(adjSum!=sum)adjMat[sum][adjSum]=adjMat[adjSum][sum]=1
  }
}
t=nodes.length;
for(i=0;i<t;i++){
  if(!nodes[i]){
    for(k=0;k<t;k++){
      adjMat[i][k]=adjMat[k][i]=0
    }
  }
}
sum=(a,b)=>a+b;
console.log(nodes.reduce(sum))
connections=x=>x.reduce(sum)
counts=adjMat.map(connections);
stor=[];
for(i=0;i<t;i++){
  stor.push(nodes[i]);
}
maxRemainder=0;

greater=[]
for(i=0;i<t;i++){
  if(nodes[i]&&counts[i]>maxConnections){
    greater.push(i);
  }
}

if(input==4){
  for(w=0;w<greater.length*numRand;w++){
    for(i=0;i<t;i++){
      nodes[i]=stor[i];
    }
    counts=adjMat.map(connections);
    toRemove=Math.floor(Math.random()*numRand*2)
    for(i=0;i<toRemove&&i<greater.length;i++){
      rand=Math.floor(Math.random()*greater.length);
      if(nodes[greater[rand]]){
        nodes[greater[rand]]=0;
        for(j=0;j<t;j++){
          if(adjMat[rand][j]){
            counts[j]--;
          }
        }
      }
    }

    for(i=0;i<t*t;i++){
      max=0;
      maxLoc=0;
      for(j=0;j<t;j++){
        if(counts[j]>=max&&nodes[j]){
          max=counts[j];
          maxLoc=j;
        }
      }
      if(max>0){
        for(j=0;j<t;j++){
          if(adjMat[maxLoc][j]){
            counts[j]--;
            if(counts[j]<max-1&&stor[j]&&!nodes[j]){
              nodes[j]=1;
              for(k=0;k<t;k++){
                if(adjMat[j][k])counts[k]++;
              }
            }
          }
          nodes[maxLoc]=0;
        }
      }
      else{
        break;
      }
    }
    maxRemainder=Math.max(maxRemainder,nodes.reduce(sum))
    //console.log(nodes.reduce(sum));
  }
  console.log(maxRemainder);
}
else{
  for(i=0;i<t*t;i++){
    max=0;
    maxLoc=0;
    for(j=0;j<t;j++){
      if(counts[j]>=max&&nodes[j]){
        max=counts[j];
        maxLoc=j;
      }
    }
    if(max>0){
      for(j=0;j<t;j++){
        if(adjMat[maxLoc][j]){
          counts[j]--;
          if(counts[j]<max-1&&stor[j]&&!nodes[j]){
            nodes[j]=1;
            for(k=0;k<t;k++){
              if(adjMat[j][k])counts[k]++;
            }
          }
        }
        nodes[maxLoc]=0;
      }
    }
    else{
      break;
    }
  }
  console.log(nodes.reduce(sum));
}

Provalo online!

Snippet che può essere aggiunto alla fine del programma per mostrare quali sequenze di distanza di Hamming hanno selezionato ciascuna sequenza di distanze di Hamming

for(i=0;i<t;i++){
  if(nodes[i]){
    tmp=[]
    for(j=0;j<input;j++){
      tmp.unshift(Math.floor(i/Math.pow(input+1,j))%(input+1))
    }
    console.log(tmp.join(""))
    output=""
    for(j=0;j<t;j++){
      if(adjMat[i][j]&&stor[j]){
        outArr=[]
        for(k=0;k<input;k++){
          outArr.unshift(Math.floor(j/Math.pow(input+1,k))%(input+1))
        }
        output+=" "+outArr.join("");
      }
    }
    console.log(output)
  }
}

Spiegazione:

Innanzitutto, il codice genera tutte le distanze di martellamento uniche dalle sottostringhe.

input=3;
hammings=[];
h=(x,y)=>{retVal=0;while(x||y){if(x%2!=y%2)retVal++;x>>=1;y>>=1}return retVal};
for(i=1<<(input-1);i<1<<input;i++){
  for(j=0;j<1<<(2*input);j++){
    hamming=[];
    for(k=0;k<input;k++){
      hamming.push(h((j>>k)%(1<<input),i));
    }
    equal=0;
    for(k=0;k<hammings.length;k++){
      if(hamming.join("")==hammings[k].join("")){
        equal=1;
        break;
      }
    }
    if(!equal)hammings.push(hamming);
  }
}

Successivamente, il codice converte questo elenco in un grafico non indirizzato

adjMat=[];
for(i=0;i<Math.pow(input+1,input);i++){
  row=[];
  for(j=0;j<Math.pow(input+1,input);j++){
    row.push(0);
  }
  adjMat.push(row);
}
nodes=[]
for(i=0;i<Math.pow(input+1,input);i++){
  nodes[i]=0;
}
for(i=0;i<hammings.length;i++){
  sum=0;
  chkNodes=[[]];
  for(j=0;j<input;j++){
    chkVal=[];
    t=Math.pow(input+1,j);
    sum+=t*hammings[i][j];
    tmp=[];
    for(r=0;r<chkNodes.length;r++){
      for(k=hammings[i][j];k<=Math.min(hammings[i][j]*2,input);k++){
        stor=[]
        for(s=0;s<chkNodes[r].length;s++){
          stor.push(chkNodes[r][s])
        }
        stor.push(k)
        tmp.push(stor);
      }
    }
    chkNodes=[];
    for(r=0;r<tmp.length;r++){
      chkNodes.push(tmp[r])
    }
  }
  nodes[sum]=1;
  for(j=0;j<chkNodes.length;j++){
    adjSum=0
    for(k=0;k<input;k++){
      adjSum+=Math.pow(input+1,k)*chkNodes[j][k]
    }
    if(adjSum!=sum)adjMat[sum][adjSum]=adjMat[adjSum][sum]=1
  }
}

Infine, il codice scorre ciclicamente questo grafico, rimuovendo il vertice con il maggior numero di connessioni ogni ciclo prima di ripristinare eventuali nodi che ora avrebbero meno connessioni rispetto al massimo corrente. Al termine di questo ciclo, genera il numero di nodi rimanenti

t=nodes.length;
for(i=0;i<t;i++){
  if(!nodes[i]){
    for(k=0;k<t;k++){
      adjMat[i][k]=adjMat[k][i]=0
    }
  }
}
sum=(a,b)=>a+b;
counts=adjMat.map(x=>x.reduce(sum));
stor=[];
for(i=0;i<t;i++){
  stor.push(nodes[i]);
}
for(i=0;i<t*t;i++){
  max=0;
  maxLoc=0;
  for(j=0;j<t;j++){
    if(counts[j]>=max&&nodes[j]){
      max=counts[j];
      maxLoc=j;
    }
  }
  if(max>0){
    for(j=0;j<t;j++){
      if(adjMat[maxLoc][j]){
        counts[j]--;
        if(counts[j]<max-1&&stor[j]&&!nodes[j]){
          nodes[j]=1;
          for(k=0;k<t;k++){
            if(adjMat[j][k])counts[k]++;
          }
        }
      }
      nodes[maxLoc]=0;
    }
  }
  else{
    break;
  }
}
console.log(nodes.reduce(sum));

Imposta:

1:

0 1

2:

00 01 10 12 21

3:

000 001 011 013 030 031 100 101 110 111 123 130 132 203 213 231 302 310 312 
321 333

4:

0000 0001 0011 0111 0124 0133 0223 0230 0232 0241 0313 0320 0322 0331 0403 
0412 1000 1001 1013 1021 1100 1102 1110 1111 1134 1201 1224 1233 1243 1304 
1314 1323 1330 1332 1342 1403 1413 1420 1422 2011 2033 2124 2133 2140 2142 
2214 2230 2241 2303 2313 2320 2331 2411 3023 3032 3040 3041 3101 3114 3123 
3130 3132 3141 3203 3213 3220 3231 3302 3310 3312 3321 3334 3343 3433 4031 
4113 4122 4131 4210 4212 4221 4311 4333

5:

00000 00001 00011 00111 00123 01112 01235 01244 01324 01343 02111 02230 
02234 02333 02342 02432 02441 02522 02530 02531 03134 03142 03220 03224 
03233 03241 03314 03323 03331 03403 03412 03421 03520 04133 04141 04214 
04223 04232 04303 04313 04322 05042 05050 05051 05132 10000 10001 10011 
10122 10212 10221 10245 11000 11001 11013 11022 11100 11112 11120 11121 
11202 11211 11345 11353 11443 12012 12111 12201 12245 12253 12335 12344 
12352 12425 12430 12434 12442 12513 12532 13033 13042 13244 13252 13325 
13330 13334 13342 13404 13424 13433 13441 13520 13522 13531 14032 14051 
14140 14152 14225 14230 14234 14241 14243 14304 14315 14324 14332 14413 
14420 14422 14431 15041 15050 15125 15133 15142 15215 15223 15232 20112 
20135 20211 20253 20334 20352 21012 21021 21102 21110 21111 21201 21245 
21344 21352 21430 21433 21442 21514 21523 22011 22101 22135 22244 22252 
22325 22334 22340 22343 22405 22415 22424 22441 22520 22522 22531 23041 
23144 23150 23152 23225 23234 23240 23243 23251 23304 23315 23324 23333 
23341 23403 23413 23420 23432 23521 24031 24050 24125 24130 24134 24142 
24151 24215 24224 24233 24303 24314 24320 24323 24331 24412 24421 25123 
25132 25141 25203 25214 25222 25231 25302 25312 25321 30234 30243 30252 
30324 30333 30340 30342 30414 30423 30430 30432 31011 31235 31244 31253 
31325 31334 31340 31343 31405 31415 31424 31432 31441 31504 31521 32025 
32034 32100 32144 32152 32225 32234 32240 32243 32251 32304 32315 32324 
32330 32333 32342 32403 32414 32423 32512 33024 33031 33033 33125 33134 
33140 33143 33151 33215 33224 33230 33233 33242 33303 33314 33320 33323 
33332 33412 33431 34124 34133 34203 34214 34223 34232 34241 34310 34313 
34322 34411 35202 35213 35221 35311 40323 40332 40341 40431 40505 40513 
41135 41144 41240 41243 41252 41324 41330 41333 41342 41403 41414 41423 
41512 42033 42134 42143 42230 42233 42242 42303 42310 42314 42323 42332 
42341 42413 42422 42431 43023 43124 43130 43133 43142 43203 43220 43223 
43232 43241 43302 43313 43322 43331 43421 44114 44123 44132 44210 44213 
44222 44231 44312 44321 50413 50422 50504 51233 51242 51251 51323 51332 
51341 51413 51422 52023 52133 52142 52151 52223 52232 52241 52313 52322 
52331 52421 53102 53114 53122 53210 53213 53321 54201 54212 54221 54311

Grazie per aver dato la prima risposta! Potresti fornire una guida passo passo per gli idioti su come eseguire il tuo codice in Linux, per favore?

Forse fəˈnɛtɪk potrebbe trasformare il suo codice in uno snippet di stack?
mbomb007,

@ mbomb007 per qualche motivo, trasformarlo in uno snippet provoca l'errore 0 non è una funzione ... nella riga per (j = 0; j <t; j ++)
fəˈnɛtɪk

Forse potresti provare JSFiddle?
mbomb007,

Se hai Chrome puoi copiare incolla il codice nella console ed eseguirlo premendo Invio. Non sono del tutto sicuro di altri browser. Chrome esegue il codice più velocemente dei sistemi online per me. Gestito per ottenere un 5 ° valore di 349
fəˈnɛtɪk
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.