Cuenta cuántas secuencias de distancia están lejos de todas las demás

13

La distancia de Hamming entre dos cadenas de igual longitud es el número de posiciones en las que los símbolos correspondientes son diferentes.

Dejado Pser una cadena binaria de longitud ny Tser una cadena binaria de longitud 2n-1. Podemos calcular las ndistancias de Hamming entre Py cada nsubcadena de longitud Ten orden de izquierda a derecha y ponerlas en una matriz (o lista).

Ejemplo de secuencia de distancia de Hamming

Deje P = 101y T = 01100. La secuencia de distancias de Hamming que obtienes de este par es 2,2,1.

Definición de cercanía

Ahora consideremos dos secuencias de distancias de Hamming. Decir x = (0, 2, 2, 3, 0)y y = (2, 1, 4, 4, 2)como ejemplos. Decimos eso xy ysomos closesi y <= x <= 2*yo si x <= y <= 2*x. Aquí la multiplicación escalar y la desigualdad se toman de manera elemento. Es decir, para dos secuencias Ay B, A <= B iff A[i] <= B[i]para todos los índices i.

Tenga en cuenta que las secuencias de distancias de Hamming forman un orden parcial en esta forma de compararlas. En otras palabras, muchos pares de secuencias no son ni mayores ni iguales ni menores ni iguales entre sí. Por ejemplo (1,2)y (2,1).

Entonces, usando el ejemplo anterior, (0, 2, 2, 3, 0) <= 2*(2, 1, 4, 4, 2) = (4, 2, 8, 8, 4)pero (0, 2, 2, 3, 0)no es más grande que (2, 1, 4, 4, 2). Tampoco (2, 1, 4, 4, 2)es menor o igual que 2*(0, 2, 2, 3, 0) = (0, 4, 4, 6, 0). Como resultado xy yno están cerca el uno del otro.

Tarea

Para aumentar a npartir de n=1, considere todos los pares posibles de cadenas binarias Pde longitud ny Tlongitud 2n-1. Hay 2^(n+2n-1)tales pares y, por lo tanto, muchas secuencias de distancias de Hamming. Sin embargo, muchas de esas secuencias serán idénticas. La tarea es encontrar el tamaño del conjunto más grande de secuencias de distancia de Hamming para que no haya dos secuencias cercanas entre sí.

Su código debe generar un número por valor de n.

Puntuación

En general, su puntaje es el más alto nque alcanza su código en mi máquina en 5 minutos (pero siga leyendo). El tiempo es para el tiempo total de funcionamiento, no el tiempo solo para eso n.

Para dar puntajes a las respuestas no óptimas, ya que es probable que sea difícil encontrar respuestas óptimas, necesitaremos un sistema de puntuación ligeramente sutil. Su puntaje es el valor más alto npara el cual nadie más ha publicado una respuesta correcta más alta para cualquier tamaño que sea menor que igual a esto. Por ejemplo, si usted emite 2, 4, 21y alguien más emite, 2, 5, 15entonces solo puntuaría 1como alguien más tiene una mejor respuesta para n = 2. Si genera 2, 5, 21resultados, obtendría puntajes 3sin importar los resultados de cualquier otra persona, porque esas respuestas son todas óptimas. Claramente, si tiene todas las respuestas óptimas, obtendrá la puntuación más alta nque publique. Sin embargo, incluso si su respuesta no es la óptima, aún puede obtener el puntaje si nadie más puede superarlo.

Ejemplo de respuestas y ejemplo trabajado

(Estas respuestas aún no están marcadas. Se recibiría agradecidamente la verificación independiente).

Gracias a ETHproductions:

  • n = 1 da 2.
  • n = 2 da 5.
  • n = 3 da 21.

Veamos n = 2con más detalle. En este caso, la lista completa de secuencias de distancia de Hamming (representada por tuplas aquí) es:

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

Podemos ver que (0,0)no está cerca de ninguna otra tupla. De hecho, si tomamos (0, 0), (0, 1), (1, 0), (2, 1), (1,2)entonces ninguna de esas tuplas están cerca de cualquiera de los otros. Esto da una puntuación de 5para n = 2.

Para n = 3la lista completa de distintas secuencias de distancia de Hamming es:

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

De esas 48secuencias, podemos elegir un conjunto de tamaños 21para que ningún par en ese conjunto esté cerca el uno del otro.

Idiomas y bibliotecas

Puede usar cualquier idioma y bibliotecas disponibles que desee. Siempre que sea posible, sería bueno poder ejecutar su código, por lo tanto, si es posible, incluya una explicación completa sobre cómo ejecutar / compilar su código en Linux.

Mi máquina Los tiempos se ejecutarán en mi máquina de 64 bits. Esta es una instalación estándar de ubuntu con 8 GB de RAM, procesador AMD FX-8350 de ocho núcleos y Radeon HD 4250. Esto también significa que necesito poder ejecutar su código.

Respuesta líder

  • Puntuación de 4 por 2, 5, 21, 83, 361 por Christian Sievers. C ++
  • Puntuación de 5 para 2, 5, 21, 83, 372 por fəˈnɛtɪk. Javascript

fuente
Después de mirar a su pregunta, que muestra algunas similitudes con espías, revisados en hackerrank, que es un problema NP-completo
fənɛtɪk
@ fəˈnɛtɪk ¡Genial! Tenga en cuenta que mi pregunta no requiere soluciones óptimas para obtener una buena puntuación.
@ fəˈnɛtɪk ¿Puedes confirmar también las respuestas para 1,2,3 en la pregunta?
@ fəˈnɛtɪk Dudo mucho que sea NP-hard. Tendría que codificar Set Packing u otro problema NP-complete en un solo entero con solo un cambio polinómico en el tamaño del problema.
297 conjuntos de hamming únicos para 4, 2040 conjuntos únicos para 5
f --nɛtɪk

Respuestas:

5

C ++ usando la biblioteca igraph

¡Gracias por una buena oportunidad para aprender una nueva biblioteca!

Este programa ahora calcula 2, 5, 21, 83, 361rápido. Puede controlar la impresión de los nodos con la PRINTNODESconstante.

El gráfico utilizado tiene bordes adicionales entre los nodos correspondientes a los vectores de distancia donde uno está cerca (pero no es igual) al otro invertido. Eso acelera el cálculo, y cualquier conjunto independiente encontrado es, por supuesto, también uno de los gráficos originales. Además, incluso si no se aplica por completo, el conjunto independiente calculado se cierra bajo reversión. Creo que siempre existe un conjunto independiente máximo con esa propiedad. Al menos hay uno para n<=4. (Estoy seguro de que puedo mostrar que 83 es ​​óptimo).

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

Para compilar en Debian, instalar libigraph0-devy hacer g++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o ig ig.cpp -ligraph.

Descripción anterior:

La biblioteca igraph tiene una función para calcular el tamaño máximo de un conjunto de vértices independiente de un gráfico. Puede manejar este problema hasta n=3en menos de un segundo y no termina en días n=4.

Entonces, lo que hago es descomponer el gráfico en componentes conectados y dejar que la biblioteca maneje los MAXDIRECTcomponentes pequeños (menos que los nodos). Para los otros componentes, selecciono un vértice y lo elimino. En el mejor de los casos, esto divide el gráfico en varios componentes, pero generalmente no lo hace. De todos modos, los componentes (tal vez solo uno) son más pequeños y podemos usar la recursividad.

Obviamente, la selección del vértice es importante. Solo tomo uno de grado máximo. Descubrí que obtengo mejores resultados (pero solo para n=4) cuando uso una lista de nodos invertida. Eso explica la parte mágica de la constructfunción.

Puede valer la pena mejorar la selección. Pero parece más importante reconsiderar los nodos eliminados. En este momento, nunca los vuelvo a mirar. Algunos de ellos pueden estar desconectados de cualquiera de los nodos seleccionados. El problema es que no sé qué nodos forman el conjunto independiente. Por un lado, la eliminación de nodos renumera los nodos restantes. Eso puede manejarse adjuntando atributos a ellos. Pero peor, el cálculo del número de independencia solo da este número. La mejor alternativa que ofrece la biblioteca es calcular todos los conjuntos independientes más grandes, que es más lento (cuánto parece depender del tamaño del gráfico). Aún así, este parece ser el camino inmediato a seguir. Mucho más vagamente, también creo que podría ser útil considerar si podemos usar la forma especial en que se define el gráfico.

El caso n=6podría ser accesible (en absoluto, no necesariamente en 5 minutos) si reemplazo la recursión con un bucle usando una cola para los componentes restantes.

Me pareció interesante mirar los componentes de los gráficos. Para n=4, sus tamaños son 168, 2*29, 2*28, 3, 4*2, 4*1. Solo el más grande no se puede manejar directamente.

Para n=5, los tamaños son 1376, 2*128, 2*120, 119, several <=6.

Espero que esos tamaños dobles correspondan a gráficos isomórficos, pero usar esto no parece valioso porque siempre hay un único componente dominante:

Para n=6, el componente más grande contiene 11941nodos (de un total de 15425), los siguientes dos componentes más grandes tienen tamaño 596.

Para n=7, estos números son 107593 (125232), 2647.

Christian Sievers
fuente
¿Podría decirme para qué es el conjunto de 83? Quiero saber por qué mi algoritmo no sube tanto para 4, pero de alguna manera
aumenta
Tiene que ser g++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o sievers sievers.cpp -ligraph. Importa dónde -ligraphestá.
@ChristianSievers ¿Cómo funciona la generación de bordes en el código?
fəˈnɛtɪk
@ ChristianSievers Me preguntaba cómo determina a qué se debe conectar cada vértice. Invertir la matriz podría estar arruinando eso.
fəˈnɛtɪk
@ fəˈnɛtɪk Los vectores de distancia parecen salir de lo setque uso para evitar duplicados, pero ni siquiera pensé en su orden cuando escribí ese código. El bucle interno que comienza en i+1solo evita mirar un par y también su versión intercambiada, que no es necesaria, y es la forma más fácil de evitar bucles (bordes (a,a)). No depende del orden en que vienen los nodos, no me importa si consigo (a,b)o (b,a).
Christian Sievers
3

Javascript, Seq: 2,5,21, 81 83,372 67,349

Logré aumentar el valor para 4 usando la eliminación aleatoria de elementos al comienzo de mi búsqueda. Por extraño que parezca, eliminar 20 elementos con más de 6 conexiones fue más rápido que eliminar 5 elementos con más de 8 conexiones ...

Sin embargo, esta secuencia probablemente no sea óptima para 5 y podría no ser óptima para 4. Sin embargo, ninguno de los nodos está cerca de otro en el conjunto.

Código:

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

Pruébalo en línea!

Fragmento que se puede agregar al final del programa para mostrar qué secuencias de distancia de Hamming seleccionan cada secuencia de distancia de 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)
  }
}

Explicación:

Primero, el código genera todas las distancias de hamming únicas desde las subcadenas.

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

Luego, el código convierte esta lista en un gráfico no dirigido

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

Finalmente, el código recorre este gráfico, eliminando el vértice con la mayor cantidad de conexiones en cada ciclo antes de restaurar cualquier nodo que ahora tenga menos conexiones que el máximo actual. Cuando ha terminado con este ciclo, genera el número de nodos restantes

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

Conjuntos

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
fəˈnɛtɪk
fuente
¡Gracias por dar la primera respuesta! ¿Podría dar una guía paso a paso para idiotas sobre cómo ejecutar su código en Linux, por favor?
¿Quizás fəˈnɛtɪk podría convertir su código en un fragmento de pila?
mbomb007
@ mbomb007 por alguna razón, convertir esto en un fragmento provoca que el error 0 no sea una función ... en la línea para (j = 0; j <t; j ++)
fəˈnɛtɪk
¿Quizás podrías probar JSFiddle?
mbomb007
Si tiene Chrome, puede copiar y pegar el código en la consola y ejecutarlo presionando Intro. No estoy completamente seguro acerca de otros navegadores. Chrome ejecuta el código más rápido que los sistemas en línea para mí. Logró obtener un 5to valor de 349
fəˈnɛtɪk