Conte quantas seqüências de distância estão longe de todas as outras

13

A distância de Hamming entre duas cordas de igual comprimento é o número de posições nas quais os símbolos correspondentes são diferentes.

Let PSer uma seqüência de comprimento binária ne Tser uma seqüência de comprimento binária 2n-1. Podemos calcular as ndistâncias de Hamming entre Pe cada nsubstring de comprimento da Tordem da esquerda para a direita e colocá-las em uma matriz (ou lista).

Exemplo de seqüência de distância de Hamming

Let P = 101e T = 01100. A sequência de distâncias de Hamming que você obtém desse par é 2,2,1.

Definição de proximidade

Agora vamos considerar duas dessas seqüências de distâncias de Hamming. Diga x = (0, 2, 2, 3, 0)e y = (2, 1, 4, 4, 2)como exemplos. Dizemos isso xe ysomos closese y <= x <= 2*you se x <= y <= 2*x. Aqui a multiplicação escalar e a desigualdade são consideradas elementares. Ou seja, para duas seqüências Ae B, A <= B iff A[i] <= B[i]para todos os índices i.

Observe que seqüências de distâncias de Hamming formam uma ordem parcial sob essa maneira de compará-las. Em outras palavras, muitos pares de sequências não são maiores ou iguais nem menores que ou iguais um ao outro. Por exemplo (1,2)e (2,1).

Então, usando o exemplo acima, (0, 2, 2, 3, 0) <= 2*(2, 1, 4, 4, 2) = (4, 2, 8, 8, 4)mas (0, 2, 2, 3, 0)não é maior que (2, 1, 4, 4, 2). Também (2, 1, 4, 4, 2)não é menor ou igual a 2*(0, 2, 2, 3, 0) = (0, 4, 4, 6, 0). Como resultado xe ynão estão próximos um do outro.

Tarefa

Para aumentar a npartir de n=1, considere todos os pares possíveis de cadeias binárias Pde comprimento ne Tcomprimento 2n-1. Existem 2^(n+2n-1)tais pares e, portanto, muitas seqüências de distâncias de Hamming. No entanto, muitas dessas sequências serão idênticas. A tarefa é encontrar o tamanho do maior conjunto de seqüências de distância de Hamming para que não haja duas sequências próximas umas das outras.

Seu código deve gerar um número por valor de n.

Ponto

Em geral, sua pontuação é a mais alta que nseu código atinge na minha máquina em 5 minutos (mas continue lendo). O tempo é para o tempo total de execução, não o tempo apenas para essen .

Para fornecer pontuações para respostas não ideais, porque é provável que seja difícil encontrar respostas ótimas, precisaremos de um sistema de pontuação um pouco sutil. Sua pontuação é o valor mais alto npara o qual mais ninguém postou uma resposta correta mais alta para qualquer tamanho menor que igual a isso. Por exemplo, se você produzir 2, 4, 21e alguém produzir 2, 5, 15, você só pontuará se 1alguém tiver uma resposta melhor n = 2. Se você produzir 2, 5, 21, pontuará, 3independentemente do resultado de qualquer outra pessoa, porque essas respostas são ótimas. Claramente, se você tiver todas as respostas ideais, obterá a pontuação mais alta que nvocê postar. No entanto, mesmo que sua resposta não seja ótima, você ainda pode obter a pontuação se ninguém mais conseguir vencê-la.

Respostas de exemplo e exemplo trabalhado

(Essas respostas ainda estão desmarcadas. A verificação independente seria recebida com gratidão.)

Graças a ETHproductions:

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

Vamos olhar com n = 2mais detalhes. Nesse caso, a lista completa de sequências de distâncias de Hamming (representadas por tuplas aqui) é:

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

Podemos ver que (0,0)não está perto de nenhuma outra tupla. De fato, se tomarmos (0, 0), (0, 1), (1, 0), (2, 1), (1,2)em seguida, nenhuma dessas tuplas estão perto de qualquer um dos outros. Isso dá uma pontuação de 5para n = 2.

Para n = 3a lista completa de distintas seqüências de distância de Hamming, consulte:

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

Nessas 48seqüências, podemos escolher um conjunto de tamanho 21para que nenhum par nesse conjunto esteja próximo um do outro.

Línguas e bibliotecas

Você pode usar qualquer idioma e bibliotecas disponíveis que desejar. Sempre que possível, seria bom poder executar seu código; portanto, inclua uma explicação completa de como executar / compilar seu código no Linux, se possível.

Minha máquina Os tempos serão executados na minha máquina de 64 bits. Esta é uma instalação padrão do ubuntu com 8GB de RAM, processador de oito núcleos AMD FX-8350 e Radeon HD 4250. Isso também significa que eu preciso executar seu código.

Resposta principal

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

fonte
Depois de olhar para a sua pergunta, ela mostra algumas semelhanças com espiões, revisto em hackerrank, que é um NP-completos problema
fənɛtɪk
@ fəˈnɛtɪk Ótimo! Observe que minha pergunta não exige soluções ideais para obter uma boa pontuação.
@ fəˈnɛtɪk Você também pode confirmar as respostas para 1,2,3 na pergunta?
@ fəˈnɛtɪk Duvido muito que seja NP-difícil. Você precisaria codificar Set Packing ou outro problema completo de NP em um único número inteiro com apenas uma alteração polinomial no tamanho do problema.
297 matrizes hamming únicas para 4, 2040 matrizes únicas para 5
fəˈnɛtɪk

Respostas:

5

C ++ usando a biblioteca igraph

Obrigado por uma boa oportunidade de aprender uma nova biblioteca!

Este programa agora calcula 2, 5, 21, 83, 361rapidamente. Você pode controlar a impressão dos nós com a PRINTNODESconstante.

O gráfico usado possui arestas extras entre os nós correspondentes aos vetores de distância em que um está próximo (mas não é igual) ao outro invertido. Isso acelera o cálculo, e qualquer conjunto independente encontrado é, obviamente, também um dos gráficos originais. Além disso, mesmo que não seja completamente aplicado, o conjunto independente calculado é fechado em reversão. Acredito que sempre exista um conjunto independente máximo com essa propriedade. Pelo menos há um para n<=4. (Tenho certeza de que posso mostrar que 83 é o ideal.)

#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 no debian, instale libigraph0-deve faça g++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o ig ig.cpp -ligraph.

Descrição antiga:

A biblioteca igraph possui uma função para calcular o tamanho máximo de um conjunto de vértices independente de um gráfico. Ele pode lidar com esse problema n=3em menos de um segundo e não termina em dias por n=4.

Então, o que faço é decompor o gráfico em componentes conectados e deixar a biblioteca manipular os MAXDIRECTcomponentes pequenos (menos de nós). Para os outros componentes, seleciono um vértice e o apago. Na melhor das hipóteses, isso divide o gráfico em vários componentes, mas geralmente não. De qualquer forma, os componentes (talvez apenas um) são menores e podemos usar recursão.

Obviamente, a seleção do vértice é importante. Eu apenas tomo um grau máximo. Descobri que obtenho um melhor resultado (mas apenas para n=4) quando uso uma lista de nós invertidos. Isso explica a parte mágica da constructfunção.

Pode valer a pena melhorar a seleção. Mas parece mais importante reconsiderar os nós excluídos. No momento, nunca mais os olho. Alguns deles podem estar desconectados de qualquer um dos nós selecionados. O problema é que não sei quais nós formam o conjunto independente. Por um lado, a exclusão de nós renumera os nós restantes. Isso pode ser tratado anexando atributos a eles. Mas pior, o cálculo do número de independência apenas fornece esse número. A melhor alternativa que a biblioteca oferece é calcular todos os maiores conjuntos independentes, o que é mais lento (o quanto parece depender do tamanho do gráfico). Ainda assim, este parece o caminho imediato a seguir. Muito mais vagamente, também acho útil considerar se podemos usar a maneira especial como o gráfico é definido.

O caso n=6pode se tornar acessível (não necessariamente em 5 minutos) se eu substituir a recursão por um loop usando uma fila para os componentes restantes.

Achei interessante observar os componentes dos gráficos. Pois n=4, seus tamanhos são 168, 2*29, 2*28, 3, 4*2, 4*1. Somente o maior não pode ser tratado diretamente.

Pois n=5, os tamanhos são 1376, 2*128, 2*120, 119, several <=6.

Espero que esses tamanhos duplos correspondam a gráficos isomórficos, mas usar isso não parece valer a pena porque sempre há um único componente maior:

Pois n=6, o maior componente contém 11941nós (de um total de 15425), os próximos dois maiores componentes têm tamanho 596.

Pois n=7, esses números são 107593 (125232), 2647.

Peneiradores cristãos
fonte
Você poderia me informar o que o conjunto é para 83, eu quero saber por que o meu algoritmo não conseguir que alta para 4, mas de alguma forma fica maior para 5: P
fənɛtɪk
Tem que ser g++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o sievers sievers.cpp -ligraph. Importa onde -ligraphestá.
@ChristianSievers Como a geração de arestas funciona no código?
58517
@ChristianSievers Eu queria saber como determina o que cada vértice deve se conectar. Inverter a matriz pode estar estragando tudo.
21417
@ fəˈnɛtɪk Os vetores de distância parecem ter sido resolvidos com os que seteu uso para evitar duplicatas, mas eu nem pensei na ordem deles quando escrevi esse código. O loop interno que começa i+1apenas evita olhar para um par e também sua versão trocada, que não é necessária, e é a maneira mais fácil de evitar loops (arestas (a,a)). Não depende da ordem em que os nós vêm, não me importo se recebo (a,b)ou (b,a).
Christian Sievers
3

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

Consegui aumentar o valor de 4 usando a remoção aleatória de elementos no início da minha pesquisa. Curiosamente, remover 20 elementos com mais de 6 conexões foi mais rápido do que remover 5 elementos com mais de 8 conexões ...

Essa sequência provavelmente não é ideal para 5 e pode não ser ideal para 4. Nenhum dos nós está perto de outro no 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));
}

Experimente online!

Trecho que pode ser adicionado ao final do programa para mostrar quais seqüências de distâncias de Hamming cada sequência de distâncias de Hamming selecionada

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

Explicação:

Primeiro, o código gera todas as distâncias de impedimento exclusivas das substrings.

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

Em seguida, o código converte essa lista em um gráfico não direcionado

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

Por fim, o código percorre esse gráfico, removendo o vértice com mais conexões a cada ciclo antes de restaurar os nós que agora teriam menos conexões que o máximo atual. Quando termina este ciclo, gera o número de nós 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
fonte
Obrigado por dar a primeira resposta! Você poderia dar um guia passo a passo para idiotas sobre como executar seu código no Linux, por favor?
Talvez fəˈnɛtɪk possa transformar seu código em um snippet de pilha?
mbomb007
@ mbomb007 por alguma razão, fazendo isso em um trecho causa o erro 0 não é uma função ... na linha para (j = 0; j <t; j ++)
fənɛtɪk
Talvez você possa experimentar o JSFiddle?
mbomb007
Se você possui o chrome, pode copiar, colar o código no console e executá-lo pressionando enter. Não tem muita certeza sobre outros navegadores. O Chrome executa o código mais rapidamente do que os sistemas online para mim. Conseguiu obter o 5º valor de 349
fəˈnɛtɪk 17/03/2017